From 0314cbe225dce796e09ae9abbd450323808fe493 Mon Sep 17 00:00:00 2001 From: Aidan Skinner Date: Tue, 18 Aug 2009 16:16:10 +0000 Subject: QPID-2024: Add ProtocolEngine and NetworkDriver interfaces and a NetworkDriver implementation that uses MINA. git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/java-network-refactor@805477 13f79535-47bb-0310-9956-ffa450edef68 --- .../qpid/client/transport/QpidThreadExecutor.java | 22 - .../qpid/client/transport/TransportConnection.java | 1 + .../org/apache/qpid/protocol/ProtocolEngine.java | 62 +++ .../qpid/protocol/ProtocolEngineFactory.java | 29 ++ .../org/apache/qpid/thread/QpidThreadExecutor.java | 43 ++ .../org/apache/qpid/transport/NetworkDriver.java | 61 +++ .../qpid/transport/NetworkDriverConfiguration.java | 44 ++ .../org/apache/qpid/transport/OpenException.java | 32 ++ .../transport/network/mina/MINANetworkDriver.java | 379 +++++++++++++++++ .../network/mina/MINANetworkDriverTest.java | 473 +++++++++++++++++++++ 10 files changed, 1124 insertions(+), 22 deletions(-) delete mode 100644 qpid/java/client/src/main/java/org/apache/qpid/client/transport/QpidThreadExecutor.java create mode 100644 qpid/java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngine.java create mode 100644 qpid/java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngineFactory.java create mode 100644 qpid/java/common/src/main/java/org/apache/qpid/thread/QpidThreadExecutor.java create mode 100644 qpid/java/common/src/main/java/org/apache/qpid/transport/NetworkDriver.java create mode 100644 qpid/java/common/src/main/java/org/apache/qpid/transport/NetworkDriverConfiguration.java create mode 100644 qpid/java/common/src/main/java/org/apache/qpid/transport/OpenException.java create mode 100644 qpid/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java create mode 100644 qpid/java/common/src/test/java/org/apache/qpid/transport/network/mina/MINANetworkDriverTest.java (limited to 'qpid/java') diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/transport/QpidThreadExecutor.java b/qpid/java/client/src/main/java/org/apache/qpid/client/transport/QpidThreadExecutor.java deleted file mode 100644 index 3de410fb69..0000000000 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/transport/QpidThreadExecutor.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.apache.qpid.client.transport; - -import org.apache.qpid.thread.Threading; - -import edu.emory.mathcs.backport.java.util.concurrent.Executor; - -public class QpidThreadExecutor implements Executor -{ - @Override - public void execute(Runnable command) - { - try - { - Threading.getThreadFactory().createThread(command).start(); - } - catch(Exception e) - { - throw new RuntimeException("Error creating a thread using Qpid thread factory",e); - } - } - -} diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/transport/TransportConnection.java b/qpid/java/client/src/main/java/org/apache/qpid/client/transport/TransportConnection.java index 0bacda04ff..32cc8c4cb5 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/transport/TransportConnection.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/transport/TransportConnection.java @@ -31,6 +31,7 @@ import org.apache.mina.transport.vmpipe.VmPipeAddress; import org.apache.qpid.client.vmbroker.AMQVMBrokerCreationException; import org.apache.qpid.jms.BrokerDetails; import org.apache.qpid.pool.ReadWriteThreadModel; +import org.apache.qpid.thread.QpidThreadExecutor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/qpid/java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngine.java b/qpid/java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngine.java new file mode 100644 index 0000000000..8ab845454a --- /dev/null +++ b/qpid/java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngine.java @@ -0,0 +1,62 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.protocol; + +import java.net.SocketAddress; + +import org.apache.qpid.framing.AMQDataBlock; +import org.apache.qpid.transport.NetworkDriver; +import org.apache.qpid.transport.Receiver; + +/** + * A ProtocolEngine is a Receiver for java.nio.ByteBuffers. It takes the data passed to it in the received + * decodes it and then process the result. + */ +public interface ProtocolEngine extends Receiver +{ + // Sets the network driver providing data for this ProtocolEngine + void setNetworkDriver (NetworkDriver driver); + + // Returns the remote address of the NetworkDriver + SocketAddress getRemoteAddress(); + + // Returns number of bytes written + long getWrittenBytes(); + + // Returns number of bytes read + long getReadBytes(); + + // Called by the NetworkDriver when the socket has been closed for reading + void closed(); + + // Called when the NetworkEngine has not written data for the specified period of time (will trigger a + // heartbeat) + void writerIdle(); + + // Called when the NetworkEngine has not read data for the specified period of time (will close the connection) + void readerIdle(); + + /** + * Accepts an AMQFrame for writing to the network. The ProtocolEngine encodes the frame into bytes and + * passes the data onto the NetworkDriver for sending + */ + void writeFrame(AMQDataBlock frame); +} \ No newline at end of file diff --git a/qpid/java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngineFactory.java b/qpid/java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngineFactory.java new file mode 100644 index 0000000000..d8c0f2c916 --- /dev/null +++ b/qpid/java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngineFactory.java @@ -0,0 +1,29 @@ +/* + * + * 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.protocol; + +public interface ProtocolEngineFactory +{ + + // Returns a new instance of a ProtocolEngine + ProtocolEngine newProtocolEngine(); + +} \ No newline at end of file diff --git a/qpid/java/common/src/main/java/org/apache/qpid/thread/QpidThreadExecutor.java b/qpid/java/common/src/main/java/org/apache/qpid/thread/QpidThreadExecutor.java new file mode 100644 index 0000000000..376658bb99 --- /dev/null +++ b/qpid/java/common/src/main/java/org/apache/qpid/thread/QpidThreadExecutor.java @@ -0,0 +1,43 @@ +/* + * + * 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.thread; + +import org.apache.qpid.thread.Threading; + +import edu.emory.mathcs.backport.java.util.concurrent.Executor; + +public class QpidThreadExecutor implements Executor +{ + @Override + public void execute(Runnable command) + { + try + { + Threading.getThreadFactory().createThread(command).start(); + } + catch(Exception e) + { + throw new RuntimeException("Error creating a thread using Qpid thread factory",e); + } + } + +} diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/NetworkDriver.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/NetworkDriver.java new file mode 100644 index 0000000000..d45cee8004 --- /dev/null +++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/NetworkDriver.java @@ -0,0 +1,61 @@ +/* + * + * 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.transport; + +import java.net.BindException; +import java.net.InetAddress; +import java.net.SocketAddress; + +import javax.net.ssl.SSLEngine; + +import org.apache.qpid.protocol.ProtocolEngine; +import org.apache.qpid.protocol.ProtocolEngineFactory; +import org.apache.qpid.ssl.SSLContextFactory; + +public interface NetworkDriver extends Sender +{ + // Creates a NetworkDriver which attempts to connect to destination on port and attaches the ProtocolEngine to + // it using the SSLEngine if provided + void open(int port, InetAddress destination, ProtocolEngine engine, + NetworkDriverConfiguration config, SSLEngine sslEngine) + throws OpenException; + + // listens for incoming connections on the specified ports and address and creates a new NetworkDriver which + // processes incoming connections with ProtocolEngines created from factory using the SSLEngine if provided + void bind (int port, InetAddress[] addresses, ProtocolEngineFactory protocolFactory, + NetworkDriverConfiguration config, SSLContextFactory sslFactory) throws BindException; + + // Returns the remote address of underlying socket + SocketAddress getRemoteAddress(); + + /** + * The length of time after which the ProtocolEngines readIdle() method should be called if no data has been + * read in seconds + */ + void setMaxReadIdle(int idleTime); + + /** + * The length of time after which the ProtocolEngines writeIdle() method should be called if no data has been + * written in seconds + */ + void setMaxWriteIdle(int idleTime); + +} \ No newline at end of file diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/NetworkDriverConfiguration.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/NetworkDriverConfiguration.java new file mode 100644 index 0000000000..18cae6bf85 --- /dev/null +++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/NetworkDriverConfiguration.java @@ -0,0 +1,44 @@ +/* + * + * 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.transport; + +/** + * This interface provides a means for NetworkDrivers to configure TCP options such as incoming and outgoing + * buffer sizes and set particular options on the socket. NetworkDrivers should honour the values returned + * from here if the underlying implementation supports them. + */ +public interface NetworkDriverConfiguration +{ + // Taken from Socket + boolean getKeepAlive(); + boolean getOOBInline(); + boolean getReuseAddress(); + Integer getSoLinger(); // null means off + int getSoTimeout(); + boolean getTcpNoDelay(); + int getTrafficClass(); + + // The amount of memory in bytes to allocate to the incoming buffer + int getReceiveBufferSize(); + + // The amount of memory in bytes to allocate to the outgoing buffer + int getSendBufferSize(); +} diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/OpenException.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/OpenException.java new file mode 100644 index 0000000000..8628b8c7aa --- /dev/null +++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/OpenException.java @@ -0,0 +1,32 @@ +/* + * + * 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.transport; + +public class OpenException extends Exception +{ + + public OpenException(String string, Throwable lastException) + { + super(string, lastException); + } + +} diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java new file mode 100644 index 0000000000..96fb7b1ef8 --- /dev/null +++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java @@ -0,0 +1,379 @@ +/* + * + * 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.transport.network.mina; + +import java.io.IOException; +import java.net.BindException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.nio.ByteBuffer; + +import javax.net.ssl.SSLEngine; + +import org.apache.mina.common.ConnectFuture; +import org.apache.mina.common.IdleStatus; +import org.apache.mina.common.IoAcceptor; +import org.apache.mina.common.IoFilterChain; +import org.apache.mina.common.IoHandlerAdapter; +import org.apache.mina.common.IoSession; +import org.apache.mina.common.IoSessionConfig; +import org.apache.mina.common.SimpleByteBufferAllocator; +import org.apache.mina.common.WriteFuture; +import org.apache.mina.filter.ReadThrottleFilterBuilder; +import org.apache.mina.filter.SSLFilter; +import org.apache.mina.filter.WriteBufferLimitFilterBuilder; +import org.apache.mina.filter.executor.ExecutorFilter; +import org.apache.mina.transport.socket.nio.MultiThreadSocketConnector; +import org.apache.mina.transport.socket.nio.SocketAcceptorConfig; +import org.apache.mina.transport.socket.nio.SocketConnector; +import org.apache.mina.transport.socket.nio.SocketConnectorConfig; +import org.apache.mina.transport.socket.nio.SocketSessionConfig; +import org.apache.mina.util.NewThreadExecutor; +import org.apache.mina.util.SessionUtil; +import org.apache.qpid.pool.ReadWriteThreadModel; +import org.apache.qpid.protocol.ProtocolEngine; +import org.apache.qpid.protocol.ProtocolEngineFactory; +import org.apache.qpid.ssl.SSLContextFactory; +import org.apache.qpid.thread.QpidThreadExecutor; +import org.apache.qpid.transport.NetworkDriver; +import org.apache.qpid.transport.NetworkDriverConfiguration; +import org.apache.qpid.transport.OpenException; + +public class MINANetworkDriver extends IoHandlerAdapter implements NetworkDriver +{ + + private static final int DEFAULT_BUFFER_SIZE = 32 * 1024; + + ProtocolEngine _protocolEngine; + private boolean _useNIO = false; + private int _processors = 4; + private boolean _executorPool = false; + private SSLContextFactory _sslFactory = null; + private SocketConnector _socketConnector; + private IoAcceptor _acceptor; + private IoSession _ioSession; + private ProtocolEngineFactory _factory; + private boolean _protectIO; + private NetworkDriverConfiguration _config; + private Throwable _lastException; + private boolean _acceptingConnections = false; + + public MINANetworkDriver(boolean useNIO, int processors, boolean executorPool, boolean protectIO) + { + _useNIO = useNIO; + _processors = processors; + _executorPool = executorPool; + _protectIO = protectIO; + } + + public MINANetworkDriver(boolean useNIO, int processors, boolean executorPool, boolean protectIO, + ProtocolEngine protocolEngine, IoSession session) + { + _useNIO = useNIO; + _processors = processors; + _executorPool = executorPool; + _protectIO = protectIO; + _protocolEngine = protocolEngine; + _ioSession = session; + } + + public MINANetworkDriver() + { + + } + + public void bind(int port, InetAddress[] addresses, ProtocolEngineFactory factory, + NetworkDriverConfiguration config, SSLContextFactory sslFactory) throws BindException + { + + _factory = factory; + _config = config; + + if (_useNIO) + { + _acceptor = new org.apache.mina.transport.socket.nio.MultiThreadSocketAcceptor(_processors, + new NewThreadExecutor()); + } + else + { + _acceptor = new org.apache.mina.transport.socket.nio.SocketAcceptor(_processors, new NewThreadExecutor()); + } + + SocketAcceptorConfig sconfig = (SocketAcceptorConfig) _acceptor.getDefaultConfig(); + SocketSessionConfig sc = (SocketSessionConfig) sconfig.getSessionConfig(); + + if (config != null) + { + sc.setReceiveBufferSize(config.getReceiveBufferSize()); + sc.setSendBufferSize(config.getSendBufferSize()); + sc.setTcpNoDelay(config.getTcpNoDelay()); + } + + // if we do not use the executor pool threading model we get the default + // leader follower + // implementation provided by MINA + if (_executorPool) + { + sconfig.setThreadModel(ReadWriteThreadModel.getInstance()); + } + + if (sslFactory != null) + { + _sslFactory = sslFactory; + } + + if (addresses != null && addresses.length > 0) + { + for (InetAddress addr : addresses) + { + try + { + _acceptor.bind(new InetSocketAddress(addr, port), this, sconfig); + } + catch (IOException e) + { + throw new BindException(String.format("Could not bind to {0}:{2}", addr, port)); + } + } + } + else + { + try + { + _acceptor.bind(new InetSocketAddress(port), this, sconfig); + } + catch (IOException e) + { + throw new BindException(String.format("Could not bind to *:{1}", port)); + } + } + _acceptingConnections = true; + } + + public SocketAddress getRemoteAddress() + { + return _ioSession.getRemoteAddress(); + } + + public void open(int port, InetAddress destination, ProtocolEngine engine, NetworkDriverConfiguration config, + SSLEngine sslEngine) throws OpenException + { + if (_useNIO) + { + _socketConnector = new MultiThreadSocketConnector(1, new QpidThreadExecutor()); + } + else + { + _socketConnector = new SocketConnector(1, new QpidThreadExecutor()); // non-blocking + // connector + } + + org.apache.mina.common.ByteBuffer.setUseDirectBuffers(Boolean.getBoolean("amqj.enableDirectBuffers")); + // the MINA default is currently to use the pooled allocator although this may change in future + // once more testing of the performance of the simple allocator has been done + if (!Boolean.getBoolean("amqj.enablePooledAllocator")) + { + org.apache.mina.common.ByteBuffer.setAllocator(new SimpleByteBufferAllocator()); + } + + + SocketConnectorConfig cfg = (SocketConnectorConfig) _socketConnector.getDefaultConfig(); + + // if we do not use our own thread model we get the MINA default which is to use + // its own leader-follower model + boolean readWriteThreading = Boolean.getBoolean("amqj.shared_read_write_pool"); + if (readWriteThreading) + { + cfg.setThreadModel(ReadWriteThreadModel.getInstance()); + } + + SocketSessionConfig scfg = (SocketSessionConfig) cfg.getSessionConfig(); + scfg.setTcpNoDelay((config != null) ? config.getTcpNoDelay() : true); + scfg.setSendBufferSize((config != null) ? config.getSendBufferSize() : DEFAULT_BUFFER_SIZE); + scfg.setReceiveBufferSize((config != null) ? config.getReceiveBufferSize() : DEFAULT_BUFFER_SIZE); + + // Don't have the connector's worker thread wait around for other + // connections (we only use + // one SocketConnector per connection at the moment anyway). This allows + // short-running + // clients (like unit tests) to complete quickly. + _socketConnector.setWorkerTimeout(0); + ConnectFuture future = _socketConnector.connect(new InetSocketAddress(destination, port), this, cfg); + future.join(); + if (!future.isConnected()) + { + throw new OpenException("Could not open connection", _lastException); + } + _ioSession = future.getSession(); + ReadWriteThreadModel.getInstance().getAsynchronousReadFilter().createNewJobForSession(_ioSession); + ReadWriteThreadModel.getInstance().getAsynchronousWriteFilter().createNewJobForSession(_ioSession); + _ioSession.setAttachment(engine); + engine.setNetworkDriver(this); + _protocolEngine = engine; + } + + public void setMaxReadIdle(int idleTime) + { + _ioSession.setIdleTime(IdleStatus.READER_IDLE, idleTime); + } + + public void setMaxWriteIdle(int idleTime) + { + _ioSession.setIdleTime(IdleStatus.WRITER_IDLE, idleTime); + } + + public void close() + { + if (_acceptor != null) + { + _acceptor.unbindAll(); + } + if (_ioSession != null) + { + _ioSession.close(); + } + } + + public void flush() + { + // MINA doesn't support flush + } + + public void send(ByteBuffer msg) + { + WriteFuture future = _ioSession.write(org.apache.mina.common.ByteBuffer.wrap(msg)); + future.join(); + } + + public void setIdleTimeout(long l) + { + // MINA doesn't support setting SO_TIMEOUT + } + + public void exceptionCaught(IoSession protocolSession, Throwable throwable) throws Exception + { + if (_protocolEngine != null) + { + _protocolEngine.exception(throwable); + } + _lastException = throwable; + } + + /** + * Invoked when a message is received on a particular protocol session. Note + * that a protocol session is directly tied to a particular physical + * connection. + * + * @param protocolSession + * the protocol session that received the message + * @param message + * the message itself (i.e. a decoded frame) + * + * @throws Exception + * if the message cannot be processed + */ + public void messageReceived(IoSession protocolSession, Object message) throws Exception + { + if (message instanceof org.apache.mina.common.ByteBuffer) + { + ((ProtocolEngine) protocolSession.getAttachment()).received(((org.apache.mina.common.ByteBuffer) message).buf()); + } + else + { + throw new IllegalStateException("Handed unhandled message. message.class = " + message.getClass() + " message = " + message); + } + } + + public void sessionClosed(IoSession protocolSession) throws Exception + { + ((ProtocolEngine) protocolSession.getAttachment()).closed(); + } + + public void sessionCreated(IoSession protocolSession) throws Exception + { + if (_acceptingConnections) + { + // Configure the session with SSL if necessary + SessionUtil.initialize(protocolSession); + if (_executorPool) + { + if (_sslFactory != null) + { + protocolSession.getFilterChain().addAfter("AsynchronousReadFilter", "sslFilter", + new SSLFilter(_sslFactory.buildServerContext())); + } + } + else + { + if (_sslFactory != null) + { + protocolSession.getFilterChain().addBefore("protocolFilter", "sslFilter", + new SSLFilter(_sslFactory.buildServerContext())); + } + } + + // Do we want to have read/write buffer limits? + if (_protectIO) + { + //Add IO Protection Filters + IoFilterChain chain = protocolSession.getFilterChain(); + + protocolSession.getFilterChain().addLast("tempExecutorFilterForFilterBuilder", new ExecutorFilter()); + + ReadThrottleFilterBuilder readfilter = new ReadThrottleFilterBuilder(); + readfilter.setMaximumConnectionBufferSize(_config.getReceiveBufferSize()); + readfilter.attach(chain); + + WriteBufferLimitFilterBuilder writefilter = new WriteBufferLimitFilterBuilder(); + writefilter.setMaximumConnectionBufferSize(_config.getSendBufferSize()); + writefilter.attach(chain); + + protocolSession.getFilterChain().remove("tempExecutorFilterForFilterBuilder"); + } + + // Set up the protocol engine + ProtocolEngine protocolEngine = _factory.newProtocolEngine(); + MINANetworkDriver newDriver = new MINANetworkDriver(_useNIO, _processors, _executorPool, _protectIO, protocolEngine, protocolSession); + protocolEngine.setNetworkDriver(newDriver); + protocolSession.setAttachment(protocolEngine); + } + } + + public void sessionIdle(IoSession session, IdleStatus status) throws Exception + { + if (IdleStatus.WRITER_IDLE.equals(status)) + { + ((ProtocolEngine) session.getAttachment()).writerIdle(); + } + else if (IdleStatus.READER_IDLE.equals(status)) + { + ((ProtocolEngine) session.getAttachment()).readerIdle(); + } + } + + private ProtocolEngine getProtocolEngine() + { + return _protocolEngine; + } + +} diff --git a/qpid/java/common/src/test/java/org/apache/qpid/transport/network/mina/MINANetworkDriverTest.java b/qpid/java/common/src/test/java/org/apache/qpid/transport/network/mina/MINANetworkDriverTest.java new file mode 100644 index 0000000000..7901f6a99d --- /dev/null +++ b/qpid/java/common/src/test/java/org/apache/qpid/transport/network/mina/MINANetworkDriverTest.java @@ -0,0 +1,473 @@ +/* + * + * 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.transport.network.mina; + +import java.net.BindException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.net.UnknownHostException; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import junit.framework.TestCase; + +import org.apache.qpid.framing.AMQDataBlock; +import org.apache.qpid.protocol.ProtocolEngine; +import org.apache.qpid.protocol.ProtocolEngineFactory; +import org.apache.qpid.transport.NetworkDriver; +import org.apache.qpid.transport.OpenException; + +public class MINANetworkDriverTest extends TestCase +{ + + private static final String TEST_DATA = "YHALOTHAR"; + private static final int TEST_PORT = 2323; + private NetworkDriver _server; + private NetworkDriver _client; + private CountingProtocolEngine _countingEngine; // Keeps a count of how many bytes it's read + private Exception _thrownEx; + + @Override + public void setUp() + { + _server = new MINANetworkDriver(); + _client = new MINANetworkDriver(); + _thrownEx = null; + _countingEngine = new CountingProtocolEngine(); + } + + @Override + public void tearDown() + { + if (_server != null) + { + _server.close(); + } + + if (_client != null) + { + _client.close(); + } + } + + /** + * Tests that a socket can't be opened if a driver hasn't been bound + * to the port and can be opened if a driver has been bound. + * @throws BindException + * @throws UnknownHostException + * @throws OpenException + */ + public void testBindOpen() throws BindException, UnknownHostException, OpenException + { + try + { + _client.open(TEST_PORT, InetAddress.getLocalHost(), _countingEngine, null, null); + } + catch (OpenException e) + { + _thrownEx = e; + } + + assertNotNull("Open should have failed since no engine bound", _thrownEx); + + _server.bind(TEST_PORT, null, new EchoProtocolEngineSingletonFactory(), null, null); + + _client.open(TEST_PORT, InetAddress.getLocalHost(), _countingEngine, null, null); + } + + /** + * Tests that a socket can't be opened after a bound NetworkDriver has been closed + * @throws BindException + * @throws UnknownHostException + * @throws OpenException + */ + public void testBindOpenCloseOpen() throws BindException, UnknownHostException, OpenException + { + _server.bind(TEST_PORT, null, new EchoProtocolEngineSingletonFactory(), null, null); + _client.open(TEST_PORT, InetAddress.getLocalHost(), _countingEngine, null, null); + _client.close(); + _server.close(); + + try + { + _client.open(TEST_PORT, InetAddress.getLocalHost(), _countingEngine, null, null); + } + catch (OpenException e) + { + _thrownEx = e; + } + assertNotNull("Open should have failed", _thrownEx); + } + + /** + * Checks that the right exception is thrown when binding a NetworkDriver to an already + * existing socket. + */ + public void testBindPortInUse() + { + try + { + _server.bind(TEST_PORT, null, new EchoProtocolEngineSingletonFactory(), null, null); + } + catch (BindException e) + { + fail("First bind should not fail"); + } + + try + { + _client.bind(TEST_PORT, null, new EchoProtocolEngineSingletonFactory(), null, null); + } + catch (BindException e) + { + _thrownEx = e; + } + assertNotNull("Second bind should throw BindException", _thrownEx); + } + + /** + * tests that bytes sent on a network driver are received at the other end + * + * @throws UnknownHostException + * @throws OpenException + * @throws InterruptedException + * @throws BindException + */ + public void testSend() throws UnknownHostException, OpenException, InterruptedException, BindException + { + // Open a connection from a counting engine to an echo engine + _server.bind(TEST_PORT, null, new EchoProtocolEngineSingletonFactory(), null, null); + _client.open(TEST_PORT, InetAddress.getLocalHost(), _countingEngine, null, null); + + // Tell the counting engine how much data we're sending + _countingEngine.setNewLatch(TEST_DATA.getBytes().length); + + // Send the data and wait for up to 2 seconds to get it back + _client.send(ByteBuffer.wrap(TEST_DATA.getBytes())); + _countingEngine.getLatch().await(2, TimeUnit.SECONDS); + + // Check what we got + assertEquals("Wrong amount of data recieved", TEST_DATA.getBytes().length, _countingEngine.getReadBytes()); + } + + /** + * Opens a connection with a low read idle and check that it gets triggered + * @throws BindException + * @throws OpenException + * @throws UnknownHostException + * + */ + public void testSetReadIdle() throws BindException, UnknownHostException, OpenException + { + // Open a connection from a counting engine to an echo engine + _server.bind(TEST_PORT, null, new EchoProtocolEngineSingletonFactory(), null, null); + _client.open(TEST_PORT, InetAddress.getLocalHost(), _countingEngine, null, null); + assertFalse("Reader should not have been idle", _countingEngine.getReaderHasBeenIdle()); + _client.setMaxReadIdle(1); + try + { + Thread.sleep(1000); + } + catch (InterruptedException e) + { + // Eat it + } + assertTrue("Reader should have been idle", _countingEngine.getReaderHasBeenIdle()); + } + + /** + * Opens a connection with a low write idle and check that it gets triggered + * @throws BindException + * @throws OpenException + * @throws UnknownHostException + * + */ + public void testSetWriteIdle() throws BindException, UnknownHostException, OpenException + { + // Open a connection from a counting engine to an echo engine + _server.bind(TEST_PORT, null, new EchoProtocolEngineSingletonFactory(), null, null); + _client.open(TEST_PORT, InetAddress.getLocalHost(), _countingEngine, null, null); + assertFalse("Reader should not have been idle", _countingEngine.getWriterHasBeenIdle()); + _client.setMaxWriteIdle(1); + try + { + Thread.sleep(1000); + } + catch (InterruptedException e) + { + // Eat it + } + assertTrue("Reader should have been idle", _countingEngine.getWriterHasBeenIdle()); + } + + + /** + * Creates and then closes a connection from client to server and checks that the server + * has its closed() method called. Then creates a new client and closes the server to check + * that the client has its closed() method called. + * @throws BindException + * @throws UnknownHostException + * @throws OpenException + */ + public void testClosed() throws BindException, UnknownHostException, OpenException + { + // Open a connection from a counting engine to an echo engine + EchoProtocolEngineSingletonFactory factory = new EchoProtocolEngineSingletonFactory(); + _server.bind(TEST_PORT, null, factory, null, null); + _client.open(TEST_PORT, InetAddress.getLocalHost(), _countingEngine, null, null); + EchoProtocolEngine serverEngine = null; + while (serverEngine == null) + { + serverEngine = factory.getEngine(); + if (serverEngine == null) + { + try + { + Thread.sleep(10); + } + catch (InterruptedException e) + { + } + } + } + assertFalse("Server should not have been closed", serverEngine.getClosed()); + serverEngine.setNewLatch(1); + _client.close(); + try + { + serverEngine.getLatch().await(2, TimeUnit.SECONDS); + } + catch (InterruptedException e) + { + } + assertTrue("Server should have been closed", serverEngine.getClosed()); + + _client.open(TEST_PORT, InetAddress.getLocalHost(), _countingEngine, null, null); + _countingEngine.setClosed(false); + assertFalse("Client should not have been closed", _countingEngine.getClosed()); + _countingEngine.setNewLatch(1); + _server.close(); + try + { + _countingEngine.getLatch().await(2, TimeUnit.SECONDS); + } + catch (InterruptedException e) + { + } + assertTrue("Client should have been closed", _countingEngine.getClosed()); + } + + /** + * Create a connection and instruct the client to throw an exception when it gets some data + * and that the latch gets counted down. + * @throws BindException + * @throws UnknownHostException + * @throws OpenException + * @throws InterruptedException + */ + public void testExceptionCaught() throws BindException, UnknownHostException, OpenException, InterruptedException + { + _server.bind(TEST_PORT, null, new EchoProtocolEngineSingletonFactory(), null, null); + _client.open(TEST_PORT, InetAddress.getLocalHost(), _countingEngine, null, null); + + + assertEquals("Exception should not have been thrown", 1, + _countingEngine.getExceptionLatch().getCount()); + _countingEngine.setErrorOnNextRead(true); + _countingEngine.setNewLatch(TEST_DATA.getBytes().length); + _client.send(ByteBuffer.wrap(TEST_DATA.getBytes())); + _countingEngine.getExceptionLatch().await(2, TimeUnit.SECONDS); + assertEquals("Exception should not been thrown", 0, + _countingEngine.getExceptionLatch().getCount()); + } + + /** + * Opens a connection and checks that the remote address is the one that was asked for + * @throws BindException + * @throws UnknownHostException + * @throws OpenException + */ + public void testGetRemoteAddress() throws BindException, UnknownHostException, OpenException + { + _server.bind(TEST_PORT, null, new EchoProtocolEngineSingletonFactory(), null, null); + _client.open(TEST_PORT, InetAddress.getLocalHost(), _countingEngine, null, null); + assertEquals(new InetSocketAddress(InetAddress.getLocalHost(), TEST_PORT), + _client.getRemoteAddress()); + } + + private class EchoProtocolEngineSingletonFactory implements ProtocolEngineFactory + { + EchoProtocolEngine _engine = null; + + public ProtocolEngine newProtocolEngine() + { + if (_engine == null) + { + _engine = new EchoProtocolEngine(); + } + return getEngine(); + } + + public EchoProtocolEngine getEngine() + { + return _engine; + } + } + + public class CountingProtocolEngine implements ProtocolEngine + { + + protected NetworkDriver _driver; + public ArrayList _receivedBytes = new ArrayList(); + private int _readBytes; + private CountDownLatch _latch = new CountDownLatch(0); + private boolean _readerHasBeenIdle; + private boolean _writerHasBeenIdle; + private boolean _closed = false; + private boolean _nextReadErrors = false; + private CountDownLatch _exceptionLatch = new CountDownLatch(1); + + public void closed() + { + setClosed(true); + _latch.countDown(); + } + + public void setErrorOnNextRead(boolean b) + { + _nextReadErrors = b; + } + + public void setNewLatch(int length) + { + _latch = new CountDownLatch(length); + } + + public long getReadBytes() + { + return _readBytes; + } + + public SocketAddress getRemoteAddress() + { + if (_driver != null) + { + return _driver.getRemoteAddress(); + } + else + { + return null; + } + } + + public long getWrittenBytes() + { + return 0; + } + + public void readerIdle() + { + _readerHasBeenIdle = true; + } + + public void setNetworkDriver(NetworkDriver driver) + { + _driver = driver; + } + + public void writeFrame(AMQDataBlock frame) + { + + } + + public void writerIdle() + { + _writerHasBeenIdle = true; + } + + public void exception(Throwable t) + { + _exceptionLatch.countDown(); + } + + public CountDownLatch getExceptionLatch() + { + return _exceptionLatch; + } + + public void received(ByteBuffer msg) + { + // increment read bytes and count down the latch for that many + int bytes = msg.remaining(); + _readBytes += bytes; + for (int i = 0; i < bytes; i++) + { + _latch.countDown(); + } + + // Throw an error if we've been asked too, but we can still count + if (_nextReadErrors) + { + throw new RuntimeException("Was asked to error"); + } + } + + public CountDownLatch getLatch() + { + return _latch; + } + + public boolean getWriterHasBeenIdle() + { + return _writerHasBeenIdle; + } + + public boolean getReaderHasBeenIdle() + { + return _readerHasBeenIdle; + } + + public void setClosed(boolean _closed) + { + this._closed = _closed; + } + + public boolean getClosed() + { + return _closed; + } + } + + private class EchoProtocolEngine extends CountingProtocolEngine + { + + public void received(ByteBuffer msg) + { + super.received(msg); + msg.rewind(); + _driver.send(msg); + } + } +} \ No newline at end of file -- cgit v1.2.1 From f0051104b5b99601507c578bd0a7b819a76aef55 Mon Sep 17 00:00:00 2001 From: Aidan Skinner Date: Wed, 19 Aug 2009 14:03:25 +0000 Subject: QPID-2024: Change send to stash the future and have flush join on that so that it only returns when all data has been written. Add getLocalAddress. git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/java-network-refactor@805809 13f79535-47bb-0310-9956-ffa450edef68 --- .../java/org/apache/qpid/transport/NetworkDriver.java | 5 ++++- .../qpid/transport/network/mina/MINANetworkDriver.java | 15 ++++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) (limited to 'qpid/java') diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/NetworkDriver.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/NetworkDriver.java index d45cee8004..34b0ef65be 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/transport/NetworkDriver.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/NetworkDriver.java @@ -43,9 +43,12 @@ public interface NetworkDriver extends Sender void bind (int port, InetAddress[] addresses, ProtocolEngineFactory protocolFactory, NetworkDriverConfiguration config, SSLContextFactory sslFactory) throws BindException; - // Returns the remote address of underlying socket + // Returns the remote address of the underlying socket SocketAddress getRemoteAddress(); + // Returns the local address of the underlying socket + SocketAddress getLocalAddress(); + /** * The length of time after which the ProtocolEngines readIdle() method should be called if no data has been * read in seconds diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java index 96fb7b1ef8..7330a042df 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java @@ -78,6 +78,8 @@ public class MINANetworkDriver extends IoHandlerAdapter implements NetworkDriver private Throwable _lastException; private boolean _acceptingConnections = false; + private WriteFuture _lastWriteFuture; + public MINANetworkDriver(boolean useNIO, int processors, boolean executorPool, boolean protectIO) { _useNIO = useNIO; @@ -174,6 +176,11 @@ public class MINANetworkDriver extends IoHandlerAdapter implements NetworkDriver { return _ioSession.getRemoteAddress(); } + + public SocketAddress getLocalAddress() + { + return _ioSession.getLocalAddress(); + } public void open(int port, InetAddress destination, ProtocolEngine engine, NetworkDriverConfiguration config, SSLEngine sslEngine) throws OpenException @@ -256,13 +263,15 @@ public class MINANetworkDriver extends IoHandlerAdapter implements NetworkDriver public void flush() { - // MINA doesn't support flush + if (_lastWriteFuture != null) + { + _lastWriteFuture.join(); + } } public void send(ByteBuffer msg) { - WriteFuture future = _ioSession.write(org.apache.mina.common.ByteBuffer.wrap(msg)); - future.join(); + _lastWriteFuture = _ioSession.write(org.apache.mina.common.ByteBuffer.wrap(msg)); } public void setIdleTimeout(long l) -- cgit v1.2.1 From a7be8fc7337b5cc093f593cc1becb9fe7b4dc0fb Mon Sep 17 00:00:00 2001 From: Aidan Skinner Date: Tue, 1 Sep 2009 16:27:52 +0000 Subject: QPID-2025: Add a AMQProtocolEngine from the de-MINAfied AMQMinaProtocolSession. Remove various now-unused classes and update references. Add tests for AMQDecoder. Net -1500 lines, +25% performance on transient messaging. Nice. git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/java-network-refactor@810110 13f79535-47bb-0310-9956-ffa450edef68 --- .../src/main/java/org/apache/qpid/server/Main.java | 199 ++-- .../server/configuration/ServerConfiguration.java | 56 +- .../qpid/server/connection/ConnectionRegistry.java | 1 - .../server/connection/IConnectionRegistry.java | 1 - .../server/protocol/AMQMinaProtocolSession.java | 923 ----------------- .../qpid/server/protocol/AMQProtocolEngine.java | 1054 ++++++++++++++++++++ .../server/protocol/AMQProtocolEngineFactory.java | 29 + .../qpid/server/protocol/AMQProtocolSession.java | 15 + .../server/protocol/AMQProtocolSessionMBean.java | 42 +- .../qpid/server/registry/ApplicationRegistry.java | 2 +- .../access/plugins/network/FirewallPlugin.java | 23 +- .../apache/qpid/server/transport/QpidAcceptor.java | 12 +- .../configuration/ServerConfigurationTest.java | 56 +- .../protocol/AMQProtocolSessionMBeanTest.java | 2 +- .../protocol/InternalTestProtocolSession.java | 23 +- .../qpid/server/protocol/MaxChannelsTest.java | 2 +- .../apache/qpid/server/protocol/TestIoSession.java | 328 ------ .../qpid/server/protocol/TestNetworkDriver.java | 126 +++ .../qpid/server/queue/AMQQueueAlertTest.java | 49 +- .../access/plugins/network/FirewallPluginTest.java | 39 +- .../qpid/client/protocol/AMQProtocolHandler.java | 2 +- .../qpid/client/transport/TransportConnection.java | 12 +- .../org/apache/qpid/codec/AMQCodecFactory.java | 7 +- .../java/org/apache/qpid/codec/AMQDecoder.java | 79 +- .../apache/qpid/framing/AMQDataBlockDecoder.java | 39 +- .../apache/qpid/framing/AMQDataBlockEncoder.java | 2 +- .../apache/qpid/framing/ProtocolInitiation.java | 20 +- .../src/main/java/org/apache/qpid/pool/Event.java | 58 +- .../src/main/java/org/apache/qpid/pool/Job.java | 34 +- .../java/org/apache/qpid/pool/PoolingFilter.java | 27 +- .../org/apache/qpid/pool/ReadWriteRunnable.java | 1 - .../qpid/protocol/ProtocolEngineFactory.java | 4 +- .../qpid/transport/NetworkDriverConfiguration.java | 16 +- .../transport/network/mina/MINANetworkDriver.java | 20 +- .../java/org/apache/qpid/codec/AMQDecoderTest.java | 130 +++ .../codec/MockAMQVersionAwareProtocolSession.java | 95 ++ .../network/mina/MINANetworkDriverTest.java | 5 +- 37 files changed, 1890 insertions(+), 1643 deletions(-) delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQMinaProtocolSession.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngineFactory.java delete mode 100644 qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/TestIoSession.java create mode 100644 qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/TestNetworkDriver.java create mode 100644 qpid/java/common/src/test/java/org/apache/qpid/codec/AMQDecoderTest.java create mode 100644 qpid/java/common/src/test/java/org/apache/qpid/codec/MockAMQVersionAwareProtocolSession.java (limited to 'qpid/java') diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java index f8deb95628..c45e794145 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java @@ -20,6 +20,13 @@ */ package org.apache.qpid.server; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.util.Properties; + import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Option; @@ -30,16 +37,9 @@ import org.apache.commons.cli.PosixParser; import org.apache.log4j.Logger; import org.apache.log4j.PropertyConfigurator; import org.apache.log4j.xml.QpidLog4JConfigurator; -import org.apache.mina.common.ByteBuffer; -import org.apache.mina.common.FixedSizeByteBufferAllocator; -import org.apache.mina.common.IoAcceptor; -import org.apache.mina.transport.socket.nio.SocketAcceptorConfig; -import org.apache.mina.transport.socket.nio.SocketSessionConfig; -import org.apache.mina.util.NewThreadExecutor; import org.apache.qpid.AMQException; import org.apache.qpid.common.QpidProperties; import org.apache.qpid.framing.ProtocolVersion; -import org.apache.qpid.pool.ReadWriteThreadModel; import org.apache.qpid.server.configuration.ServerConfiguration; import org.apache.qpid.server.configuration.management.ConfigurationManagementMBean; import org.apache.qpid.server.information.management.ServerInformationMBean; @@ -48,19 +48,13 @@ import org.apache.qpid.server.logging.actors.BrokerActor; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.management.LoggingManagementMBean; import org.apache.qpid.server.logging.messages.BrokerMessages; -import org.apache.qpid.server.protocol.AMQPFastProtocolHandler; -import org.apache.qpid.server.protocol.AMQPProtocolProvider; +import org.apache.qpid.server.protocol.AMQProtocolEngineFactory; import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.registry.ConfigurationFileApplicationRegistry; import org.apache.qpid.server.transport.QpidAcceptor; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.net.BindException; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.util.Properties; +import org.apache.qpid.ssl.SSLContextFactory; +import org.apache.qpid.transport.NetworkDriver; +import org.apache.qpid.transport.network.mina.MINANetworkDriver; /** * Main entry point for AMQPD. @@ -300,20 +294,6 @@ public class Main _brokerLogger.info("Starting Qpid Broker " + QpidProperties.getReleaseVersion() + " build: " + QpidProperties.getBuildVersion()); - ByteBuffer.setUseDirectBuffers(serverConfig.getEnableDirectBuffers()); - - // the MINA default is currently to use the pooled allocator although this may change in future - // once more testing of the performance of the simple allocator has been done - if (!serverConfig.getEnablePooledAllocator()) - { - ByteBuffer.setAllocator(new FixedSizeByteBufferAllocator()); - } - - if (serverConfig.getUseBiasedWrites()) - { - System.setProperty("org.apache.qpid.use_write_biased_pool", "true"); - } - int port = serverConfig.getPort(); String portStr = commandLine.getOptionValue("p"); @@ -329,7 +309,54 @@ public class Main } } - bind(port, serverConfig); + String bindAddr = commandLine.getOptionValue("b"); + if (bindAddr == null) + { + bindAddr = serverConfig.getBind(); + } + InetAddress bindAddress = null; + if (bindAddr.equals("wildcard")) + { + bindAddress = new InetSocketAddress(port).getAddress(); + } + else + { + bindAddress = InetAddress.getByAddress(parseIP(bindAddr)); + } + + String keystorePath = serverConfig.getKeystorePath(); + String keystorePassword = serverConfig.getKeystorePassword(); + String certType = serverConfig.getCertType(); + SSLContextFactory sslFactory = null; + boolean isSsl = false; + + if (!serverConfig.getSSLOnly()) + { + NetworkDriver driver = new MINANetworkDriver(); + driver.bind(port, new InetAddress[]{bindAddress}, new AMQProtocolEngineFactory(), + serverConfig.getNetworkConfiguration(), null); + ApplicationRegistry.getInstance().addAcceptor(new InetSocketAddress(bindAddress, port), + new QpidAcceptor(driver,"TCP")); + CurrentActor.get().message(BrokerMessages.BRK_1002("TCP", port)); + } + + if (serverConfig.getEnableSSL()) + { + sslFactory = new SSLContextFactory(keystorePath, keystorePassword, certType); + NetworkDriver driver = new MINANetworkDriver(); + driver.bind(serverConfig.getSSLPort(), new InetAddress[]{bindAddress}, + new AMQProtocolEngineFactory(), serverConfig.getNetworkConfiguration(), sslFactory); + ApplicationRegistry.getInstance().addAcceptor(new InetSocketAddress(bindAddress, port), + new QpidAcceptor(driver,"TCP")); + CurrentActor.get().message(BrokerMessages.BRK_1002("TCP/SSL", serverConfig.getSSLPort())); + } + + //fixme qpid.AMQP should be using qpidproperties to get value + _brokerLogger.info("Qpid Broker Ready :" + QpidProperties.getReleaseVersion() + + " build: " + QpidProperties.getBuildVersion()); + + CurrentActor.get().message(BrokerMessages.BRK_1004()); + } finally { @@ -358,114 +385,6 @@ public class Main } } - protected void bind(int port, ServerConfiguration config) throws BindException - { - String bindAddr = commandLine.getOptionValue("b"); - if (bindAddr == null) - { - bindAddr = config.getBind(); - } - - try - { - IoAcceptor acceptor; - - if (ApplicationRegistry.getInstance().getConfiguration().getQpidNIO()) - { - _logger.warn("Using Qpid Multithreaded IO Processing"); - acceptor = new org.apache.mina.transport.socket.nio.MultiThreadSocketAcceptor(config.getProcessors(), new NewThreadExecutor()); - } - else - { - _logger.warn("Using Mina IO Processing"); - acceptor = new org.apache.mina.transport.socket.nio.SocketAcceptor(config.getProcessors(), new NewThreadExecutor()); - } - - SocketAcceptorConfig sconfig = (SocketAcceptorConfig) acceptor.getDefaultConfig(); - SocketSessionConfig sc = (SocketSessionConfig) sconfig.getSessionConfig(); - - sc.setReceiveBufferSize(config.getReceiveBufferSize()); - sc.setSendBufferSize(config.getWriteBufferSize()); - sc.setTcpNoDelay(config.getTcpNoDelay()); - - // if we do not use the executor pool threading model we get the default leader follower - // implementation provided by MINA - if (config.getEnableExecutorPool()) - { - sconfig.setThreadModel(ReadWriteThreadModel.getInstance()); - } - - if (!config.getEnableSSL() || !config.getSSLOnly()) - { - AMQPFastProtocolHandler handler = new AMQPProtocolProvider().getHandler(); - InetSocketAddress bindAddress; - if (bindAddr.equals("wildcard")) - { - bindAddress = new InetSocketAddress(port); - } - else - { - bindAddress = new InetSocketAddress(InetAddress.getByAddress(parseIP(bindAddr)), port); - } - - bind(new QpidAcceptor(acceptor,"TCP"), bindAddress, handler, sconfig); - - //fixme qpid.AMQP should be using qpidproperties to get value - _brokerLogger.info("Qpid.AMQP listening on non-SSL address " + bindAddress); - } - - if (config.getEnableSSL()) - { - AMQPFastProtocolHandler handler = new AMQPProtocolProvider().getHandler(); - try - { - - bind(new QpidAcceptor(acceptor, "TCP/SSL"), new InetSocketAddress(config.getSSLPort()), handler, sconfig); - - //fixme qpid.AMQP should be using qpidproperties to get value - _brokerLogger.info("Qpid.AMQP listening on SSL port " + config.getSSLPort()); - - } - catch (IOException e) - { - _brokerLogger.error("Unable to listen on SSL port: " + e, e); - } - } - - //fixme qpid.AMQP should be using qpidproperties to get value - _brokerLogger.info("Qpid Broker Ready :" + QpidProperties.getReleaseVersion() - + " build: " + QpidProperties.getBuildVersion()); - - CurrentActor.get().message(BrokerMessages.BRK_1004()); - - } - catch (Exception e) - { - _logger.error("Unable to bind service to registry: " + e, e); - //fixme this need tidying up - throw new BindException(e.getMessage()); - } - } - - /** - * Ensure that any bound Acceptors are recorded in the registry so they can be closed later. - * - * @param acceptor - * @param bindAddress - * @param handler - * @param sconfig - * - * @throws IOException from the acceptor.bind command - */ - private void bind(QpidAcceptor acceptor, InetSocketAddress bindAddress, AMQPFastProtocolHandler handler, SocketAcceptorConfig sconfig) throws IOException - { - acceptor.getIoAcceptor().bind(bindAddress, handler, sconfig); - - CurrentActor.get().message(BrokerMessages.BRK_1002(acceptor.toString(), bindAddress.getPort())); - - ApplicationRegistry.getInstance().addAcceptor(bindAddress, acceptor); - } - public static void main(String[] args) { //if the -Dlog4j.configuration property has not been set, enable the init override diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java index 7ea7738189..b3c8975c7c 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java @@ -38,6 +38,7 @@ import org.apache.qpid.server.configuration.management.ConfigurationManagementMB import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.server.virtualhost.VirtualHostRegistry; +import org.apache.qpid.transport.NetworkDriverConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -564,7 +565,7 @@ public class ServerConfiguration implements SignalHandler public boolean getSSLOnly() { - return getConfig().getBoolean("connector.ssl.sslOnly", true); + return getConfig().getBoolean("connector.ssl.sslOnly", false); } public int getSSLPort() @@ -613,4 +614,57 @@ public class ServerConfiguration implements SignalHandler getConfig().getLong("housekeeping.expiredMessageCheckPeriod", DEFAULT_HOUSEKEEPING_PERIOD)); } + + public NetworkDriverConfiguration getNetworkConfiguration() + { + return new NetworkDriverConfiguration() + { + + public Integer getTrafficClass() + { + return null; + } + + public Boolean getTcpNoDelay() + { + // Can't call parent getTcpNoDelay since it just calls this one + return getConfig().getBoolean("connector.tcpNoDelay", true); + } + + public Integer getSoTimeout() + { + return null; + } + + public Integer getSoLinger() + { + return null; + } + + public Integer getSendBufferSize() + { + return getBufferWriteLimit(); + } + + public Boolean getReuseAddress() + { + return null; + } + + public Integer getReceiveBufferSize() + { + return getBufferReadLimit(); + } + + public Boolean getOOBInline() + { + return null; + } + + public Boolean getKeepAlive() + { + return null; + } + }; + } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/connection/ConnectionRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/connection/ConnectionRegistry.java index d287595e2d..71e07172ed 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/connection/ConnectionRegistry.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/connection/ConnectionRegistry.java @@ -21,7 +21,6 @@ package org.apache.qpid.server.connection; import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.server.protocol.AMQMinaProtocolSession; import org.apache.qpid.server.protocol.AMQProtocolSession; import org.apache.qpid.AMQException; import org.apache.qpid.AMQConnectionException; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/connection/IConnectionRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/connection/IConnectionRegistry.java index d64fde1c20..002269bbaa 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/connection/IConnectionRegistry.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/connection/IConnectionRegistry.java @@ -20,7 +20,6 @@ */ package org.apache.qpid.server.connection; -import org.apache.qpid.server.protocol.AMQMinaProtocolSession; import org.apache.qpid.server.protocol.AMQProtocolSession; import org.apache.qpid.AMQException; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQMinaProtocolSession.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQMinaProtocolSession.java deleted file mode 100644 index 7bc4365152..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQMinaProtocolSession.java +++ /dev/null @@ -1,923 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.protocol; - -import org.apache.log4j.Logger; -import org.apache.mina.common.CloseFuture; -import org.apache.mina.common.IdleStatus; -import org.apache.mina.common.IoServiceConfig; -import org.apache.mina.common.IoSession; -import org.apache.mina.transport.vmpipe.VmPipeAddress; -import org.apache.qpid.AMQChannelException; -import org.apache.qpid.AMQConnectionException; -import org.apache.qpid.AMQException; -import org.apache.qpid.codec.AMQCodecFactory; -import org.apache.qpid.codec.AMQDecoder; -import org.apache.qpid.common.ClientProperties; -import org.apache.qpid.framing.AMQBody; -import org.apache.qpid.framing.AMQDataBlock; -import org.apache.qpid.framing.AMQFrame; -import org.apache.qpid.framing.AMQMethodBody; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.ChannelCloseOkBody; -import org.apache.qpid.framing.ContentBody; -import org.apache.qpid.framing.ContentHeaderBody; -import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.framing.HeartbeatBody; -import org.apache.qpid.framing.MethodDispatcher; -import org.apache.qpid.framing.MethodRegistry; -import org.apache.qpid.framing.ProtocolInitiation; -import org.apache.qpid.framing.ProtocolVersion; -import org.apache.qpid.pool.ReadWriteThreadModel; -import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.protocol.AMQMethodEvent; -import org.apache.qpid.protocol.AMQMethodListener; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.handler.ServerMethodDispatcherImpl; -import org.apache.qpid.server.logging.actors.AMQPConnectionActor; -import org.apache.qpid.server.logging.actors.CurrentActor; -import org.apache.qpid.server.logging.subjects.ConnectionLogSubject; -import org.apache.qpid.server.logging.LogSubject; -import org.apache.qpid.server.logging.LogActor; -import org.apache.qpid.server.logging.messages.ConnectionMessages; -import org.apache.qpid.server.management.Managable; -import org.apache.qpid.server.management.ManagedObject; -import org.apache.qpid.server.output.ProtocolOutputConverter; -import org.apache.qpid.server.output.ProtocolOutputConverterRegistry; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.state.AMQState; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.server.virtualhost.VirtualHostRegistry; -import org.apache.qpid.transport.Sender; - -import javax.management.JMException; -import javax.security.sasl.SaslServer; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.security.Principal; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.CopyOnWriteArraySet; -import java.util.concurrent.atomic.AtomicLong; - -public class AMQMinaProtocolSession implements AMQProtocolSession, Managable -{ - private static final Logger _logger = Logger.getLogger(AMQProtocolSession.class); - - private static final String CLIENT_PROPERTIES_INSTANCE = ClientProperties.instance.toString(); - - private static final AtomicLong idGenerator = new AtomicLong(0); - - // to save boxing the channelId and looking up in a map... cache in an array the low numbered - // channels. This value must be of the form 2^x - 1. - private static final int CHANNEL_CACHE_SIZE = 0xff; - - private final IoSession _minaProtocolSession; - - private AMQShortString _contextKey; - - private AMQShortString _clientVersion = null; - - private VirtualHost _virtualHost; - - private final Map _channelMap = new HashMap(); - - private final AMQChannel[] _cachedChannels = new AMQChannel[CHANNEL_CACHE_SIZE + 1]; - - private final CopyOnWriteArraySet _frameListeners = new CopyOnWriteArraySet(); - - private final AMQStateManager _stateManager; - - private AMQCodecFactory _codecFactory; - - private AMQProtocolSessionMBean _managedObject; - - private SaslServer _saslServer; - - private Object _lastReceived; - - private Object _lastSent; - - protected boolean _closed; - // maximum number of channels this session should have - private long _maxNoOfChannels = 1000; - - /* AMQP Version for this session */ - private ProtocolVersion _protocolVersion = ProtocolVersion.getLatestSupportedVersion(); - - private FieldTable _clientProperties; - private final List _taskList = new CopyOnWriteArrayList(); - - private List _closingChannelsList = new CopyOnWriteArrayList(); - private ProtocolOutputConverter _protocolOutputConverter; - private Principal _authorizedID; - private MethodDispatcher _dispatcher; - private ProtocolSessionIdentifier _sessionIdentifier; - - private static final long LAST_WRITE_FUTURE_JOIN_TIMEOUT = 60000L; - private org.apache.mina.common.WriteFuture _lastWriteFuture; - - // Create a simple ID that increments for ever new Session - private final long _sessionID = idGenerator.getAndIncrement(); - - private AMQPConnectionActor _actor; - private LogSubject _logSubject; - - public ManagedObject getManagedObject() - { - return _managedObject; - } - - public AMQMinaProtocolSession(IoSession session, VirtualHostRegistry virtualHostRegistry, AMQCodecFactory codecFactory) - throws AMQException - { - _stateManager = new AMQStateManager(virtualHostRegistry, this); - _minaProtocolSession = session; - session.setAttachment(this); - - _codecFactory = codecFactory; - - _actor = new AMQPConnectionActor(this, virtualHostRegistry.getApplicationRegistry().getRootMessageLogger()); - - _actor.message(ConnectionMessages.CON_1001(null, null, false, false)); - - try - { - IoServiceConfig config = session.getServiceConfig(); - ReadWriteThreadModel threadModel = (ReadWriteThreadModel) config.getThreadModel(); - threadModel.getAsynchronousReadFilter().createNewJobForSession(session); - threadModel.getAsynchronousWriteFilter().createNewJobForSession(session); - } - catch (RuntimeException e) - { - e.printStackTrace(); - throw e; - - } - } - - private AMQProtocolSessionMBean createMBean() throws AMQException - { - try - { - return new AMQProtocolSessionMBean(this); - } - catch (JMException ex) - { - _logger.error("AMQProtocolSession MBean creation has failed ", ex); - throw new AMQException("AMQProtocolSession MBean creation has failed ", ex); - } - } - - public IoSession getIOSession() - { - return _minaProtocolSession; - } - - public static AMQProtocolSession getAMQProtocolSession(IoSession minaProtocolSession) - { - return (AMQProtocolSession) minaProtocolSession.getAttachment(); - } - - public long getSessionID() - { - return _sessionID; - } - - public LogActor getLogActor() - { - return _actor; - } - - public void dataBlockReceived(AMQDataBlock message) throws Exception - { - _lastReceived = message; - if (message instanceof ProtocolInitiation) - { - protocolInitiationReceived((ProtocolInitiation) message); - - } - else if (message instanceof AMQFrame) - { - AMQFrame frame = (AMQFrame) message; - frameReceived(frame); - - } - else - { - throw new UnknnownMessageTypeException(message); - } - } - - private void frameReceived(AMQFrame frame) throws AMQException - { - int channelId = frame.getChannel(); - AMQBody body = frame.getBodyFrame(); - - //Look up the Channel's Actor and set that as the current actor - // If that is not available then we can use the ConnectionActor - // that is associated with this AMQMPSession. - LogActor channelActor = null; - if (_channelMap.get(channelId) != null) - { - channelActor = _channelMap.get(channelId).getLogActor(); - } - CurrentActor.set(channelActor == null ? _actor : channelActor); - - try - { - if (_logger.isDebugEnabled()) - { - _logger.debug("Frame Received: " + frame); - } - - // Check that this channel is not closing - if (channelAwaitingClosure(channelId)) - { - if ((frame.getBodyFrame() instanceof ChannelCloseOkBody)) - { - if (_logger.isInfoEnabled()) - { - _logger.info("Channel[" + channelId + "] awaiting closure - processing close-ok"); - } - } - else - { - if (_logger.isInfoEnabled()) - { - _logger.info("Channel[" + channelId + "] awaiting closure. Should close socket as client did not close-ok :" + frame); - } - - closeProtocolSession(); - return; - } - } - - try - { - body.handle(channelId, this); - } - catch (AMQException e) - { - closeChannel(channelId); - throw e; - } - } - finally - { - CurrentActor.remove(); - } - } - - private void protocolInitiationReceived(ProtocolInitiation pi) - { - // this ensures the codec never checks for a PI message again - ((AMQDecoder) _codecFactory.getDecoder()).setExpectProtocolInitiation(false); - try - { - // Log incomming protocol negotiation request - _actor.message(ConnectionMessages.CON_1001(null, pi._protocolMajor + "-" + pi._protocolMinor, false, true)); - - ProtocolVersion pv = pi.checkVersion(); // Fails if not correct - - // This sets the protocol version (and hence framing classes) for this session. - setProtocolVersion(pv); - - String mechanisms = ApplicationRegistry.getInstance().getAuthenticationManager().getMechanisms(); - - String locales = "en_US"; - - AMQMethodBody responseBody = getMethodRegistry().createConnectionStartBody((short) getProtocolMajorVersion(), - (short) getProtocolMinorVersion(), - null, - mechanisms.getBytes(), - locales.getBytes()); - _minaProtocolSession.write(responseBody.generateFrame(0)); - - } - catch (AMQException e) - { - _logger.info("Received unsupported protocol initiation for protocol version: " + getProtocolVersion()); - - _minaProtocolSession.write(new ProtocolInitiation(ProtocolVersion.getLatestSupportedVersion())); - - // TODO: Close connection (but how to wait until message is sent?) - // ritchiem 2006-12-04 will this not do? - // WriteFuture future = _minaProtocolSession.write(new ProtocolInitiation(pv[i][PROTOCOLgetProtocolMajorVersion()], pv[i][PROTOCOLgetProtocolMinorVersion()])); - // future.join(); - // close connection - - } - } - - public void methodFrameReceived(int channelId, AMQMethodBody methodBody) - { - - final AMQMethodEvent evt = new AMQMethodEvent(channelId, methodBody); - - try - { - try - { - - boolean wasAnyoneInterested = _stateManager.methodReceived(evt); - - if (!_frameListeners.isEmpty()) - { - for (AMQMethodListener listener : _frameListeners) - { - wasAnyoneInterested = listener.methodReceived(evt) || wasAnyoneInterested; - } - } - - if (!wasAnyoneInterested) - { - throw new AMQNoMethodHandlerException(evt); - } - } - catch (AMQChannelException e) - { - if (getChannel(channelId) != null) - { - if (_logger.isInfoEnabled()) - { - _logger.info("Closing channel due to: " + e.getMessage()); - } - - writeFrame(e.getCloseFrame(channelId)); - closeChannel(channelId); - } - else - { - if (_logger.isDebugEnabled()) - { - _logger.debug("ChannelException occured on non-existent channel:" + e.getMessage()); - } - - if (_logger.isInfoEnabled()) - { - _logger.info("Closing connection due to: " + e.getMessage()); - } - - AMQConnectionException ce = - evt.getMethod().getConnectionException(AMQConstant.CHANNEL_ERROR, - AMQConstant.CHANNEL_ERROR.getName().toString()); - - closeConnection(channelId, ce, false); - } - } - catch (AMQConnectionException e) - { - closeConnection(channelId, e, false); - } - } - catch (Exception e) - { - - for (AMQMethodListener listener : _frameListeners) - { - listener.error(e); - } - - _logger.error("Unexpected exception while processing frame. Closing connection.", e); - - closeProtocolSession(); - } - } - - public void contentHeaderReceived(int channelId, ContentHeaderBody body) throws AMQException - { - - AMQChannel channel = getAndAssertChannel(channelId); - - channel.publishContentHeader(body); - - } - - public void contentBodyReceived(int channelId, ContentBody body) throws AMQException - { - AMQChannel channel = getAndAssertChannel(channelId); - - channel.publishContentBody(body); - } - - public void heartbeatBodyReceived(int channelId, HeartbeatBody body) - { - // NO - OP - } - - /** - * Convenience method that writes a frame to the protocol session. Equivalent to calling - * getProtocolSession().write(). - * - * @param frame the frame to write - */ - public void writeFrame(AMQDataBlock frame) - { - _lastSent = frame; - - _lastWriteFuture = _minaProtocolSession.write(frame); - } - - public AMQShortString getContextKey() - { - return _contextKey; - } - - public void setContextKey(AMQShortString contextKey) - { - _contextKey = contextKey; - } - - public List getChannels() - { - return new ArrayList(_channelMap.values()); - } - - public AMQChannel getAndAssertChannel(int channelId) throws AMQException - { - AMQChannel channel = getChannel(channelId); - if (channel == null) - { - throw new AMQException(AMQConstant.NOT_FOUND, "Channel not found with id:" + channelId); - } - - return channel; - } - - public AMQChannel getChannel(int channelId) throws AMQException - { - final AMQChannel channel = - ((channelId & CHANNEL_CACHE_SIZE) == channelId) ? _cachedChannels[channelId] : _channelMap.get(channelId); - if ((channel == null) || channel.isClosing()) - { - return null; - } - else - { - return channel; - } - } - - public boolean channelAwaitingClosure(int channelId) - { - return !_closingChannelsList.isEmpty() && _closingChannelsList.contains(channelId); - } - - public void addChannel(AMQChannel channel) throws AMQException - { - if (_closed) - { - throw new AMQException("Session is closed"); - } - - final int channelId = channel.getChannelId(); - - if (_closingChannelsList.contains(channelId)) - { - throw new AMQException("Session is marked awaiting channel close"); - } - - if (_channelMap.size() == _maxNoOfChannels) - { - String errorMessage = - toString() + ": maximum number of channels has been reached (" + _maxNoOfChannels - + "); can't create channel"; - _logger.error(errorMessage); - throw new AMQException(AMQConstant.NOT_ALLOWED, errorMessage); - } - else - { - _channelMap.put(channel.getChannelId(), channel); - } - - if (((channelId & CHANNEL_CACHE_SIZE) == channelId)) - { - _cachedChannels[channelId] = channel; - } - - checkForNotification(); - } - - private void checkForNotification() - { - int channelsCount = _channelMap.size(); - if (channelsCount >= _maxNoOfChannels) - { - _managedObject.notifyClients("Channel count (" + channelsCount + ") has reached the threshold value"); - } - } - - public Long getMaximumNumberOfChannels() - { - return _maxNoOfChannels; - } - - public void setMaximumNumberOfChannels(Long value) - { - _maxNoOfChannels = value; - } - - public void commitTransactions(AMQChannel channel) throws AMQException - { - if ((channel != null) && channel.isTransactional()) - { - channel.commit(); - } - } - - public void rollbackTransactions(AMQChannel channel) throws AMQException - { - if ((channel != null) && channel.isTransactional()) - { - channel.rollback(); - } - } - - /** - * Close a specific channel. This will remove any resources used by the channel, including:
  • any queue - * subscriptions (this may in turn remove queues if they are auto delete
- * - * @param channelId id of the channel to close - * - * @throws AMQException if an error occurs closing the channel - * @throws IllegalArgumentException if the channel id is not valid - */ - public void closeChannel(int channelId) throws AMQException - { - final AMQChannel channel = getChannel(channelId); - if (channel == null) - { - throw new IllegalArgumentException("Unknown channel id"); - } - else - { - try - { - channel.close(); - markChannelAwaitingCloseOk(channelId); - } - finally - { - removeChannel(channelId); - } - } - } - - public void closeChannelOk(int channelId) - { - // todo QPID-847 - This is called from two lcoations ChannelCloseHandler and ChannelCloseOkHandler. - // When it is the CC_OK_Handler then it makes sence to remove the channel else we will leak memory. - // We do it from the Close Handler as we are sending the OK back to the client. - // While this is AMQP spec compliant. The Java client in the event of an IllegalArgumentException - // will send a close-ok.. Where we should call removeChannel. - // However, due to the poor exception handling on the client. The client-user will be notified of the - // InvalidArgument and if they then decide to close the session/connection then the there will be time - // for that to occur i.e. a new close method be sent before the exeption handling can mark the session closed. - //removeChannel(channelId); - _closingChannelsList.remove(new Integer(channelId)); - } - - private void markChannelAwaitingCloseOk(int channelId) - { - _closingChannelsList.add(channelId); - } - - /** - * In our current implementation this is used by the clustering code. - * - * @param channelId The channel to remove - */ - public void removeChannel(int channelId) - { - _channelMap.remove(channelId); - if ((channelId & CHANNEL_CACHE_SIZE) == channelId) - { - _cachedChannels[channelId] = null; - } - } - - /** - * Initialise heartbeats on the session. - * - * @param delay delay in seconds (not ms) - */ - public void initHeartbeats(int delay) - { - if (delay > 0) - { - _minaProtocolSession.setIdleTime(IdleStatus.WRITER_IDLE, delay); - _minaProtocolSession.setIdleTime(IdleStatus.READER_IDLE, (int) (ApplicationRegistry.getInstance().getConfiguration().getHeartBeatTimeout() * delay)); - } - } - - /** - * Closes all channels that were opened by this protocol session. This frees up all resources used by the channel. - * - * @throws AMQException if an error occurs while closing any channel - */ - private void closeAllChannels() throws AMQException - { - for (AMQChannel channel : _channelMap.values()) - { - channel.close(); - } - - _channelMap.clear(); - for (int i = 0; i <= CHANNEL_CACHE_SIZE; i++) - { - _cachedChannels[i] = null; - } - } - - /** This must be called when the session is _closed in order to free up any resources managed by the session. */ - public void closeSession() throws AMQException - { - if (!_closed) - { - if (_virtualHost != null) - { - _virtualHost.getConnectionRegistry().deregisterConnection(this); - } - - closeAllChannels(); - if (_managedObject != null) - { - _managedObject.unregister(); - } - - for (Task task : _taskList) - { - task.doTask(this); - } - - _closed = true; - - CurrentActor.get().message(_logSubject, ConnectionMessages.CON_1002()); - } - } - - public void closeConnection(int channelId, AMQConnectionException e, boolean closeProtocolSession) throws AMQException - { - if (_logger.isInfoEnabled()) - { - _logger.info("Closing connection due to: " + e.getMessage()); - } - - markChannelAwaitingCloseOk(channelId); - closeSession(); - _stateManager.changeState(AMQState.CONNECTION_CLOSING); - writeFrame(e.getCloseFrame(channelId)); - - if (closeProtocolSession) - { - closeProtocolSession(); - } - } - - public void closeProtocolSession() - { - closeProtocolSession(true); - } - - public void closeProtocolSession(boolean waitLast) - { - if (waitLast && (_lastWriteFuture != null)) - { - _logger.debug("Waiting for last write to join."); - _lastWriteFuture.join(LAST_WRITE_FUTURE_JOIN_TIMEOUT); - } - - _logger.debug("REALLY Closing protocol session:" + _minaProtocolSession); - final CloseFuture future = _minaProtocolSession.close(); - future.join(LAST_WRITE_FUTURE_JOIN_TIMEOUT); - - try - { - _stateManager.changeState(AMQState.CONNECTION_CLOSED); - } - catch (AMQException e) - { - _logger.info(e.getMessage()); - } - } - - public String toString() - { - return _minaProtocolSession.getRemoteAddress() + "(" + (getAuthorizedID() == null ? "?" : getAuthorizedID().getName() + ")"); - } - - public String dump() - { - return this + " last_sent=" + _lastSent + " last_received=" + _lastReceived; - } - - /** @return an object that can be used to identity */ - public Object getKey() - { - return _minaProtocolSession.getRemoteAddress(); - } - - /** - * Get the fully qualified domain name of the local address to which this session is bound. Since some servers may - * be bound to multiple addresses this could vary depending on the acceptor this session was created from. - * - * @return a String FQDN - */ - public String getLocalFQDN() - { - SocketAddress address = _minaProtocolSession.getLocalAddress(); - // we use the vmpipe address in some tests hence the need for this rather ugly test. The host - // information is used by SASL primary. - if (address instanceof InetSocketAddress) - { - return ((InetSocketAddress) address).getHostName(); - } - else if (address instanceof VmPipeAddress) - { - return "vmpipe:" + ((VmPipeAddress) address).getPort(); - } - else - { - throw new IllegalArgumentException("Unsupported socket address class: " + address); - } - } - - public SaslServer getSaslServer() - { - return _saslServer; - } - - public void setSaslServer(SaslServer saslServer) - { - _saslServer = saslServer; - } - - public FieldTable getClientProperties() - { - return _clientProperties; - } - - public void setClientProperties(FieldTable clientProperties) - { - _clientProperties = clientProperties; - if (_clientProperties != null) - { - if (_clientProperties.getString(CLIENT_PROPERTIES_INSTANCE) != null) - { - String clientID = _clientProperties.getString(CLIENT_PROPERTIES_INSTANCE); - setContextKey(new AMQShortString(clientID)); - - // Log the Opening of the connection for this client - _actor.message(ConnectionMessages.CON_1001(clientID, _protocolVersion.toString(), true, true)); - } - - if (_clientProperties.getString(ClientProperties.version.toString()) != null) - { - _clientVersion = new AMQShortString(_clientProperties.getString(ClientProperties.version.toString())); - } - } - _sessionIdentifier = new ProtocolSessionIdentifier(this); - } - - private void setProtocolVersion(ProtocolVersion pv) - { - _protocolVersion = pv; - - _protocolOutputConverter = ProtocolOutputConverterRegistry.getConverter(this); - _dispatcher = ServerMethodDispatcherImpl.createMethodDispatcher(_stateManager, _protocolVersion); - } - - public byte getProtocolMajorVersion() - { - return _protocolVersion.getMajorVersion(); - } - - public ProtocolVersion getProtocolVersion() - { - return _protocolVersion; - } - - public byte getProtocolMinorVersion() - { - return _protocolVersion.getMinorVersion(); - } - - public boolean isProtocolVersion(byte major, byte minor) - { - return (getProtocolMajorVersion() == major) && (getProtocolMinorVersion() == minor); - } - - public MethodRegistry getRegistry() - { - return getMethodRegistry(); - } - - public Object getClientIdentifier() - { - return (_minaProtocolSession != null) ? _minaProtocolSession.getRemoteAddress() : null; - } - - public VirtualHost getVirtualHost() - { - return _virtualHost; - } - - public void setVirtualHost(VirtualHost virtualHost) throws AMQException - { - _virtualHost = virtualHost; - - _actor.virtualHostSelected(this); - _logSubject = new ConnectionLogSubject(this); - - _virtualHost.getConnectionRegistry().registerConnection(this); - - _managedObject = createMBean(); - _managedObject.register(); - } - - public void addSessionCloseTask(Task task) - { - _taskList.add(task); - } - - public void removeSessionCloseTask(Task task) - { - _taskList.remove(task); - } - - public ProtocolOutputConverter getProtocolOutputConverter() - { - return _protocolOutputConverter; - } - - public void setAuthorizedID(Principal authorizedID) - { - _authorizedID = authorizedID; - - // Let the actor know that this connection is now Authorized - _actor.connectionAuthorized(this); - } - - public Principal getAuthorizedID() - { - return _authorizedID; - } - - public SocketAddress getRemoteAddress() - { - return _minaProtocolSession.getRemoteAddress(); - } - - public MethodRegistry getMethodRegistry() - { - return MethodRegistry.getMethodRegistry(getProtocolVersion()); - } - - public MethodDispatcher getMethodDispatcher() - { - return _dispatcher; - } - - public ProtocolSessionIdentifier getSessionIdentifier() - { - return _sessionIdentifier; - } - - public String getClientVersion() - { - return (_clientVersion == null) ? null : _clientVersion.toString(); - } - - public void setSender(Sender sender) - { - // No-op, interface munging between this and AMQProtocolSession - } - - public void init() - { - // No-op, interface munging between this and AMQProtocolSession - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java new file mode 100644 index 0000000000..49bdffb584 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java @@ -0,0 +1,1054 @@ +/* + * + * 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.protocol; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.nio.ByteBuffer; +import java.security.Principal; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.CopyOnWriteArraySet; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.atomic.AtomicLong; + +import javax.management.JMException; +import javax.security.sasl.SaslServer; + +import org.apache.log4j.Logger; +import org.apache.mina.transport.vmpipe.VmPipeAddress; +import org.apache.qpid.AMQChannelException; +import org.apache.qpid.AMQConnectionException; +import org.apache.qpid.AMQException; +import org.apache.qpid.codec.AMQCodecFactory; +import org.apache.qpid.codec.AMQDecoder; +import org.apache.qpid.common.ClientProperties; +import org.apache.qpid.framing.AMQBody; +import org.apache.qpid.framing.AMQDataBlock; +import org.apache.qpid.framing.AMQFrame; +import org.apache.qpid.framing.AMQMethodBody; +import org.apache.qpid.framing.AMQProtocolHeaderException; +import org.apache.qpid.framing.AMQProtocolVersionException; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.ChannelCloseOkBody; +import org.apache.qpid.framing.ConnectionCloseBody; +import org.apache.qpid.framing.ContentBody; +import org.apache.qpid.framing.ContentHeaderBody; +import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.framing.HeartbeatBody; +import org.apache.qpid.framing.MethodDispatcher; +import org.apache.qpid.framing.MethodRegistry; +import org.apache.qpid.framing.ProtocolInitiation; +import org.apache.qpid.framing.ProtocolVersion; +import org.apache.qpid.pool.Event; +import org.apache.qpid.pool.Job; +import org.apache.qpid.pool.PoolingFilter; +import org.apache.qpid.pool.ReadWriteThreadModel; +import org.apache.qpid.pool.ReferenceCountingExecutorService; +import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.protocol.AMQMethodEvent; +import org.apache.qpid.protocol.AMQMethodListener; +import org.apache.qpid.protocol.ProtocolEngine; +import org.apache.qpid.server.AMQChannel; +import org.apache.qpid.server.handler.ServerMethodDispatcherImpl; +import org.apache.qpid.server.logging.LogActor; +import org.apache.qpid.server.logging.LogSubject; +import org.apache.qpid.server.logging.actors.AMQPConnectionActor; +import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.server.logging.messages.ConnectionMessages; +import org.apache.qpid.server.logging.subjects.ConnectionLogSubject; +import org.apache.qpid.server.management.Managable; +import org.apache.qpid.server.management.ManagedObject; +import org.apache.qpid.server.output.ProtocolOutputConverter; +import org.apache.qpid.server.output.ProtocolOutputConverterRegistry; +import org.apache.qpid.server.registry.ApplicationRegistry; +import org.apache.qpid.server.state.AMQState; +import org.apache.qpid.server.state.AMQStateManager; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.server.virtualhost.VirtualHostRegistry; +import org.apache.qpid.transport.NetworkDriver; +import org.apache.qpid.transport.Sender; + +public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocolSession +{ + private static final Logger _logger = Logger.getLogger(AMQProtocolSession.class); + + private static final String CLIENT_PROPERTIES_INSTANCE = ClientProperties.instance.toString(); + + private static final AtomicLong idGenerator = new AtomicLong(0); + + // to save boxing the channelId and looking up in a map... cache in an array the low numbered + // channels. This value must be of the form 2^x - 1. + private static final int CHANNEL_CACHE_SIZE = 0xff; + + private AMQShortString _contextKey; + + private AMQShortString _clientVersion = null; + + private VirtualHost _virtualHost; + + private final Map _channelMap = new HashMap(); + + private final AMQChannel[] _cachedChannels = new AMQChannel[CHANNEL_CACHE_SIZE + 1]; + + private final CopyOnWriteArraySet _frameListeners = new CopyOnWriteArraySet(); + + private final AMQStateManager _stateManager; + + private AMQCodecFactory _codecFactory; + + private AMQProtocolSessionMBean _managedObject; + + private SaslServer _saslServer; + + private Object _lastReceived; + + private Object _lastSent; + + protected boolean _closed; + // maximum number of channels this session should have + private long _maxNoOfChannels = 1000; + + /* AMQP Version for this session */ + private ProtocolVersion _protocolVersion = ProtocolVersion.getLatestSupportedVersion(); + + private FieldTable _clientProperties; + private final List _taskList = new CopyOnWriteArrayList(); + + private List _closingChannelsList = new CopyOnWriteArrayList(); + private ProtocolOutputConverter _protocolOutputConverter; + private Principal _authorizedID; + private MethodDispatcher _dispatcher; + private ProtocolSessionIdentifier _sessionIdentifier; + + // Create a simple ID that increments for ever new Session + private final long _sessionID = idGenerator.getAndIncrement(); + + private AMQPConnectionActor _actor; + private LogSubject _logSubject; + + private NetworkDriver _networkDriver; + + private long _lastIoTime; + + private long _writtenBytes; + private long _readBytes; + + private Job _readJob; + private Job _writeJob; + + private ReferenceCountingExecutorService _poolReference = ReferenceCountingExecutorService.getInstance(); + + public ManagedObject getManagedObject() + { + return _managedObject; + } + + public AMQProtocolEngine(VirtualHostRegistry virtualHostRegistry, NetworkDriver driver) + { + _stateManager = new AMQStateManager(virtualHostRegistry, this); + _networkDriver = driver; + + _codecFactory = new AMQCodecFactory(true, this); + + ReadWriteThreadModel threadModel = ReadWriteThreadModel.getInstance(); + _readJob = new Job(threadModel.getAsynchronousReadFilter(), PoolingFilter.MAX_JOB_EVENTS, true); + _writeJob = new Job(threadModel.getAsynchronousWriteFilter(), PoolingFilter.MAX_JOB_EVENTS, false); + + _actor = new AMQPConnectionActor(this, virtualHostRegistry.getApplicationRegistry().getRootMessageLogger()); + _actor.message(ConnectionMessages.CON_1001(null, null, false, false)); + } + + private AMQProtocolSessionMBean createMBean() throws AMQException + { + try + { + return new AMQProtocolSessionMBean(this); + } + catch (JMException ex) + { + _logger.error("AMQProtocolSession MBean creation has failed ", ex); + throw new AMQException("AMQProtocolSession MBean creation has failed ", ex); + } + } + + public long getSessionID() + { + return _sessionID; + } + + public LogActor getLogActor() + { + return _actor; + } + + @Override + public void received(final ByteBuffer msg) + { + _lastIoTime = System.currentTimeMillis(); + try + { + final ArrayList dataBlocks = _codecFactory.getDecoder().decodeBuffer(msg); + fireAsynchEvent(_readJob, new Event(new Runnable() + { + @Override + public void run() + { + // Decode buffer + + for (AMQDataBlock dataBlock : dataBlocks) + { + try + { + dataBlockReceived(dataBlock); + } + catch (Exception e) + { + e.printStackTrace(); + closeProtocolSession(); + } + } + } + })); + } + catch (Exception e) + { + e.printStackTrace(); + closeProtocolSession(); + } + } + + public void dataBlockReceived(AMQDataBlock message) throws Exception + { + _lastReceived = message; + if (message instanceof ProtocolInitiation) + { + protocolInitiationReceived((ProtocolInitiation) message); + + } + else if (message instanceof AMQFrame) + { + AMQFrame frame = (AMQFrame) message; + frameReceived(frame); + + } + else + { + throw new UnknnownMessageTypeException(message); + } + } + + private void frameReceived(AMQFrame frame) throws AMQException + { + int channelId = frame.getChannel(); + AMQBody body = frame.getBodyFrame(); + + //Look up the Channel's Actor and set that as the current actor + // If that is not available then we can use the ConnectionActor + // that is associated with this AMQMPSession. + LogActor channelActor = null; + if (_channelMap.get(channelId) != null) + { + channelActor = _channelMap.get(channelId).getLogActor(); + } + CurrentActor.set(channelActor == null ? _actor : channelActor); + + try + { + if (_logger.isDebugEnabled()) + { + _logger.debug("Frame Received: " + frame); + } + + // Check that this channel is not closing + if (channelAwaitingClosure(channelId)) + { + if ((frame.getBodyFrame() instanceof ChannelCloseOkBody)) + { + if (_logger.isInfoEnabled()) + { + _logger.info("Channel[" + channelId + "] awaiting closure - processing close-ok"); + } + } + else + { + if (_logger.isInfoEnabled()) + { + _logger.info("Channel[" + channelId + "] awaiting closure. Should close socket as client did not close-ok :" + frame); + } + + closeProtocolSession(); + return; + } + } + + try + { + body.handle(channelId, this); + } + catch (AMQException e) + { + closeChannel(channelId); + throw e; + } + } + finally + { + CurrentActor.remove(); + } + } + + private void protocolInitiationReceived(ProtocolInitiation pi) + { + // this ensures the codec never checks for a PI message again + ((AMQDecoder) _codecFactory.getDecoder()).setExpectProtocolInitiation(false); + try + { + // Log incomming protocol negotiation request + _actor.message(ConnectionMessages.CON_1001(null, pi._protocolMajor + "-" + pi._protocolMinor, false, true)); + + ProtocolVersion pv = pi.checkVersion(); // Fails if not correct + + // This sets the protocol version (and hence framing classes) for this session. + setProtocolVersion(pv); + + String mechanisms = ApplicationRegistry.getInstance().getAuthenticationManager().getMechanisms(); + + String locales = "en_US"; + + AMQMethodBody responseBody = getMethodRegistry().createConnectionStartBody((short) getProtocolMajorVersion(), + (short) getProtocolMinorVersion(), + null, + mechanisms.getBytes(), + locales.getBytes()); + _networkDriver.send(responseBody.generateFrame(0).toNioByteBuffer()); + + } + catch (AMQException e) + { + _logger.info("Received unsupported protocol initiation for protocol version: " + getProtocolVersion()); + + _networkDriver.send(new ProtocolInitiation(ProtocolVersion.getLatestSupportedVersion()).toNioByteBuffer()); + } + } + + public void methodFrameReceived(int channelId, AMQMethodBody methodBody) + { + + final AMQMethodEvent evt = new AMQMethodEvent(channelId, methodBody); + + try + { + try + { + + boolean wasAnyoneInterested = _stateManager.methodReceived(evt); + + if (!_frameListeners.isEmpty()) + { + for (AMQMethodListener listener : _frameListeners) + { + wasAnyoneInterested = listener.methodReceived(evt) || wasAnyoneInterested; + } + } + + if (!wasAnyoneInterested) + { + throw new AMQNoMethodHandlerException(evt); + } + } + catch (AMQChannelException e) + { + if (getChannel(channelId) != null) + { + if (_logger.isInfoEnabled()) + { + _logger.info("Closing channel due to: " + e.getMessage()); + } + + writeFrame(e.getCloseFrame(channelId)); + closeChannel(channelId); + } + else + { + if (_logger.isDebugEnabled()) + { + _logger.debug("ChannelException occured on non-existent channel:" + e.getMessage()); + } + + if (_logger.isInfoEnabled()) + { + _logger.info("Closing connection due to: " + e.getMessage()); + } + + AMQConnectionException ce = + evt.getMethod().getConnectionException(AMQConstant.CHANNEL_ERROR, + AMQConstant.CHANNEL_ERROR.getName().toString()); + + closeConnection(channelId, ce, false); + } + } + catch (AMQConnectionException e) + { + closeConnection(channelId, e, false); + } + } + catch (Exception e) + { + + for (AMQMethodListener listener : _frameListeners) + { + listener.error(e); + } + + _logger.error("Unexpected exception while processing frame. Closing connection.", e); + + closeProtocolSession(); + } + } + + public void contentHeaderReceived(int channelId, ContentHeaderBody body) throws AMQException + { + + AMQChannel channel = getAndAssertChannel(channelId); + + channel.publishContentHeader(body); + + } + + public void contentBodyReceived(int channelId, ContentBody body) throws AMQException + { + AMQChannel channel = getAndAssertChannel(channelId); + + channel.publishContentBody(body); + } + + public void heartbeatBodyReceived(int channelId, HeartbeatBody body) + { + // NO - OP + } + + /** + * Convenience method that writes a frame to the protocol session. Equivalent to calling + * getProtocolSession().write(). + * + * @param frame the frame to write + */ + public void writeFrame(AMQDataBlock frame) + { + _lastSent = frame; + final ByteBuffer buf = frame.toNioByteBuffer(); + _lastIoTime = System.currentTimeMillis(); + _writtenBytes += buf.remaining(); + fireAsynchEvent(_writeJob, new Event(new Runnable() + { + @Override + public void run() + { + _networkDriver.send(buf); + } + })); + } + + public AMQShortString getContextKey() + { + return _contextKey; + } + + public void setContextKey(AMQShortString contextKey) + { + _contextKey = contextKey; + } + + public List getChannels() + { + return new ArrayList(_channelMap.values()); + } + + public AMQChannel getAndAssertChannel(int channelId) throws AMQException + { + AMQChannel channel = getChannel(channelId); + if (channel == null) + { + throw new AMQException(AMQConstant.NOT_FOUND, "Channel not found with id:" + channelId); + } + + return channel; + } + + public AMQChannel getChannel(int channelId) throws AMQException + { + final AMQChannel channel = + ((channelId & CHANNEL_CACHE_SIZE) == channelId) ? _cachedChannels[channelId] : _channelMap.get(channelId); + if ((channel == null) || channel.isClosing()) + { + return null; + } + else + { + return channel; + } + } + + public boolean channelAwaitingClosure(int channelId) + { + return !_closingChannelsList.isEmpty() && _closingChannelsList.contains(channelId); + } + + public void addChannel(AMQChannel channel) throws AMQException + { + if (_closed) + { + throw new AMQException("Session is closed"); + } + + final int channelId = channel.getChannelId(); + + if (_closingChannelsList.contains(channelId)) + { + throw new AMQException("Session is marked awaiting channel close"); + } + + if (_channelMap.size() == _maxNoOfChannels) + { + String errorMessage = + toString() + ": maximum number of channels has been reached (" + _maxNoOfChannels + + "); can't create channel"; + _logger.error(errorMessage); + throw new AMQException(AMQConstant.NOT_ALLOWED, errorMessage); + } + else + { + _channelMap.put(channel.getChannelId(), channel); + } + + if (((channelId & CHANNEL_CACHE_SIZE) == channelId)) + { + _cachedChannels[channelId] = channel; + } + + checkForNotification(); + } + + private void checkForNotification() + { + int channelsCount = _channelMap.size(); + if (channelsCount >= _maxNoOfChannels) + { + _managedObject.notifyClients("Channel count (" + channelsCount + ") has reached the threshold value"); + } + } + + public Long getMaximumNumberOfChannels() + { + return _maxNoOfChannels; + } + + public void setMaximumNumberOfChannels(Long value) + { + _maxNoOfChannels = value; + } + + public void commitTransactions(AMQChannel channel) throws AMQException + { + if ((channel != null) && channel.isTransactional()) + { + channel.commit(); + } + } + + public void rollbackTransactions(AMQChannel channel) throws AMQException + { + if ((channel != null) && channel.isTransactional()) + { + channel.rollback(); + } + } + + /** + * Close a specific channel. This will remove any resources used by the channel, including:
  • any queue + * subscriptions (this may in turn remove queues if they are auto delete
+ * + * @param channelId id of the channel to close + * + * @throws AMQException if an error occurs closing the channel + * @throws IllegalArgumentException if the channel id is not valid + */ + public void closeChannel(int channelId) throws AMQException + { + final AMQChannel channel = getChannel(channelId); + if (channel == null) + { + throw new IllegalArgumentException("Unknown channel id"); + } + else + { + try + { + channel.close(); + markChannelAwaitingCloseOk(channelId); + } + finally + { + removeChannel(channelId); + } + } + } + + public void closeChannelOk(int channelId) + { + // todo QPID-847 - This is called from two lcoations ChannelCloseHandler and ChannelCloseOkHandler. + // When it is the CC_OK_Handler then it makes sence to remove the channel else we will leak memory. + // We do it from the Close Handler as we are sending the OK back to the client. + // While this is AMQP spec compliant. The Java client in the event of an IllegalArgumentException + // will send a close-ok.. Where we should call removeChannel. + // However, due to the poor exception handling on the client. The client-user will be notified of the + // InvalidArgument and if they then decide to close the session/connection then the there will be time + // for that to occur i.e. a new close method be sent before the exeption handling can mark the session closed. + //removeChannel(channelId); + _closingChannelsList.remove(new Integer(channelId)); + } + + private void markChannelAwaitingCloseOk(int channelId) + { + _closingChannelsList.add(channelId); + } + + /** + * In our current implementation this is used by the clustering code. + * + * @param channelId The channel to remove + */ + public void removeChannel(int channelId) + { + _channelMap.remove(channelId); + if ((channelId & CHANNEL_CACHE_SIZE) == channelId) + { + _cachedChannels[channelId] = null; + } + } + + /** + * Initialise heartbeats on the session. + * + * @param delay delay in seconds (not ms) + */ + public void initHeartbeats(int delay) + { + if (delay > 0) + { + _networkDriver.setMaxWriteIdle(delay); + _networkDriver.setMaxReadIdle((int) (ApplicationRegistry.getInstance().getConfiguration().getHeartBeatTimeout() * delay)); + } + } + + /** + * Closes all channels that were opened by this protocol session. This frees up all resources used by the channel. + * + * @throws AMQException if an error occurs while closing any channel + */ + private void closeAllChannels() throws AMQException + { + for (AMQChannel channel : _channelMap.values()) + { + channel.close(); + } + + _channelMap.clear(); + for (int i = 0; i <= CHANNEL_CACHE_SIZE; i++) + { + _cachedChannels[i] = null; + } + } + + /** This must be called when the session is _closed in order to free up any resources managed by the session. */ + public void closeSession() throws AMQException + { + if (!_closed) + { + if (_virtualHost != null) + { + _virtualHost.getConnectionRegistry().deregisterConnection(this); + } + + closeAllChannels(); + if (_managedObject != null) + { + _managedObject.unregister(); + } + + for (Task task : _taskList) + { + task.doTask(this); + } + + _closed = true; + + CurrentActor.get().message(_logSubject, ConnectionMessages.CON_1002()); + } + } + + public void closeConnection(int channelId, AMQConnectionException e, boolean closeProtocolSession) throws AMQException + { + if (_logger.isInfoEnabled()) + { + _logger.info("Closing connection due to: " + e.getMessage()); + } + + markChannelAwaitingCloseOk(channelId); + closeSession(); + _stateManager.changeState(AMQState.CONNECTION_CLOSING); + writeFrame(e.getCloseFrame(channelId)); + + if (closeProtocolSession) + { + closeProtocolSession(); + } + } + + public void closeProtocolSession() + { + _networkDriver.close(); + try + { + _stateManager.changeState(AMQState.CONNECTION_CLOSED); + } + catch (AMQException e) + { + _logger.info(e.getMessage()); + } + } + + public String toString() + { + return getRemoteAddress() + "(" + (getAuthorizedID() == null ? "?" : getAuthorizedID().getName() + ")"); + } + + public String dump() + { + return this + " last_sent=" + _lastSent + " last_received=" + _lastReceived; + } + + /** @return an object that can be used to identity */ + public Object getKey() + { + return getRemoteAddress(); + } + + /** + * Get the fully qualified domain name of the local address to which this session is bound. Since some servers may + * be bound to multiple addresses this could vary depending on the acceptor this session was created from. + * + * @return a String FQDN + */ + public String getLocalFQDN() + { + SocketAddress address = _networkDriver.getLocalAddress(); + // we use the vmpipe address in some tests hence the need for this rather ugly test. The host + // information is used by SASL primary. + if (address instanceof InetSocketAddress) + { + return ((InetSocketAddress) address).getHostName(); + } + else if (address instanceof VmPipeAddress) + { + return "vmpipe:" + ((VmPipeAddress) address).getPort(); + } + else + { + throw new IllegalArgumentException("Unsupported socket address class: " + address); + } + } + + public SaslServer getSaslServer() + { + return _saslServer; + } + + public void setSaslServer(SaslServer saslServer) + { + _saslServer = saslServer; + } + + public FieldTable getClientProperties() + { + return _clientProperties; + } + + public void setClientProperties(FieldTable clientProperties) + { + _clientProperties = clientProperties; + if (_clientProperties != null) + { + if (_clientProperties.getString(CLIENT_PROPERTIES_INSTANCE) != null) + { + String clientID = _clientProperties.getString(CLIENT_PROPERTIES_INSTANCE); + setContextKey(new AMQShortString(clientID)); + + // Log the Opening of the connection for this client + _actor.message(ConnectionMessages.CON_1001(clientID, _protocolVersion.toString(), true, true)); + } + + if (_clientProperties.getString(ClientProperties.version.toString()) != null) + { + _clientVersion = new AMQShortString(_clientProperties.getString(ClientProperties.version.toString())); + } + } + _sessionIdentifier = new ProtocolSessionIdentifier(this); + } + + private void setProtocolVersion(ProtocolVersion pv) + { + _protocolVersion = pv; + + _protocolOutputConverter = ProtocolOutputConverterRegistry.getConverter(this); + _dispatcher = ServerMethodDispatcherImpl.createMethodDispatcher(_stateManager, _protocolVersion); + } + + public byte getProtocolMajorVersion() + { + return _protocolVersion.getMajorVersion(); + } + + public ProtocolVersion getProtocolVersion() + { + return _protocolVersion; + } + + public byte getProtocolMinorVersion() + { + return _protocolVersion.getMinorVersion(); + } + + public boolean isProtocolVersion(byte major, byte minor) + { + return (getProtocolMajorVersion() == major) && (getProtocolMinorVersion() == minor); + } + + public MethodRegistry getRegistry() + { + return getMethodRegistry(); + } + + public Object getClientIdentifier() + { + return (_networkDriver != null) ? _networkDriver.getRemoteAddress() : null; + } + + public VirtualHost getVirtualHost() + { + return _virtualHost; + } + + public void setVirtualHost(VirtualHost virtualHost) throws AMQException + { + _virtualHost = virtualHost; + + _actor.virtualHostSelected(this); + _logSubject = new ConnectionLogSubject(this); + + _virtualHost.getConnectionRegistry().registerConnection(this); + + _managedObject = createMBean(); + _managedObject.register(); + } + + public void addSessionCloseTask(Task task) + { + _taskList.add(task); + } + + public void removeSessionCloseTask(Task task) + { + _taskList.remove(task); + } + + public ProtocolOutputConverter getProtocolOutputConverter() + { + return _protocolOutputConverter; + } + + public void setAuthorizedID(Principal authorizedID) + { + _authorizedID = authorizedID; + + // Let the actor know that this connection is now Authorized + _actor.connectionAuthorized(this); + } + + public Principal getAuthorizedID() + { + return _authorizedID; + } + + public SocketAddress getRemoteAddress() + { + return _networkDriver.getRemoteAddress(); + } + + public MethodRegistry getMethodRegistry() + { + return MethodRegistry.getMethodRegistry(getProtocolVersion()); + } + + public MethodDispatcher getMethodDispatcher() + { + return _dispatcher; + } + + @Override + public void closed() + { + try + { + closeSession(); + } + catch (AMQException e) + { + _logger.error("Could not close protocol engine", e); + } + } + + @Override + public void readerIdle() + { + // Nothing + } + + @Override + public void setNetworkDriver(NetworkDriver driver) + { + _networkDriver = driver; + } + + @Override + public void writerIdle() + { + _networkDriver.send(HeartbeatBody.FRAME.toNioByteBuffer()); + } + + @Override + public void exception(Throwable throwable) + { + if (throwable instanceof AMQProtocolHeaderException) + { + + writeFrame(new ProtocolInitiation(ProtocolVersion.getLatestSupportedVersion())); + _networkDriver.close(); + + _logger.error("Error in protocol initiation " + this + ":" + getRemoteAddress() + " :" + throwable.getMessage(), throwable); + } + else if (throwable instanceof IOException) + { + _logger.error("IOException caught in" + this + ", session closed implictly: " + throwable); + } + else + { + _logger.error("Exception caught in" + this + ", closing session explictly: " + throwable, throwable); + + + MethodRegistry methodRegistry = MethodRegistry.getMethodRegistry(getProtocolVersion()); + ConnectionCloseBody closeBody = methodRegistry.createConnectionCloseBody(200,new AMQShortString(throwable.getMessage()),0,0); + + writeFrame(closeBody.generateFrame(0)); + + _networkDriver.close(); + } + } + + @Override + public void init() + { + // Do nothing + } + + @Override + public void setSender(Sender sender) + { + // Do nothing + } + + @Override + public long getReadBytes() + { + return _readBytes; + } + + public long getWrittenBytes() + { + return _writtenBytes; + } + + public long getLastIoTime() + { + return _lastIoTime; + } + + public ProtocolSessionIdentifier getSessionIdentifier() + { + return _sessionIdentifier; + } + + public String getClientVersion() + { + return (_clientVersion == null) ? null : _clientVersion.toString(); + } + + /** + * Adds an {@link Event} to a {@link Job}, triggering the execution of the job if it is not already running. + * + * @param job The job. + * @param event The event to hand off asynchronously. + */ + void fireAsynchEvent(Job job, Event event) + { + + job.add(event); + + final ExecutorService pool = _poolReference .getPool(); + + if(pool == null) + { + return; + } + + // rather than perform additional checks on pool to check that it hasn't shutdown. + // catch the RejectedExecutionException that will result from executing on a shutdown pool + if (job.activate()) + { + try + { + pool.execute(job); + } + catch(RejectedExecutionException e) + { + _logger.warn("Thread pool shutdown while tasks still outstanding"); + } + } + + } + +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngineFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngineFactory.java new file mode 100644 index 0000000000..ff0c007a60 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngineFactory.java @@ -0,0 +1,29 @@ +package org.apache.qpid.server.protocol; + +import org.apache.qpid.protocol.ProtocolEngine; +import org.apache.qpid.protocol.ProtocolEngineFactory; +import org.apache.qpid.server.registry.ApplicationRegistry; +import org.apache.qpid.server.virtualhost.VirtualHostRegistry; +import org.apache.qpid.transport.NetworkDriver; + +public class AMQProtocolEngineFactory implements ProtocolEngineFactory +{ + private VirtualHostRegistry _vhosts; + + public AMQProtocolEngineFactory() + { + this(1); + } + + public AMQProtocolEngineFactory(Integer port) + { + _vhosts = ApplicationRegistry.getInstance(port).getVirtualHostRegistry(); + } + + + public ProtocolEngine newProtocolEngine(NetworkDriver networkDriver) + { + return new AMQProtocolEngine(_vhosts, networkDriver); + } + +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java index fff406bb3d..b0bef04354 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java @@ -34,6 +34,7 @@ import org.apache.qpid.server.output.ProtocolOutputConverter; import org.apache.qpid.server.virtualhost.VirtualHost; import java.security.Principal; +import java.util.List; public interface AMQProtocolSession extends AMQVersionAwareProtocolSession @@ -210,5 +211,19 @@ public interface AMQProtocolSession extends AMQVersionAwareProtocolSession public MethodDispatcher getMethodDispatcher(); public ProtocolSessionIdentifier getSessionIdentifier(); + + String getClientVersion(); + + long getLastIoTime(); + + long getWrittenBytes(); + + Long getMaximumNumberOfChannels(); + + void setMaximumNumberOfChannels(Long value); + + void commitTransactions(AMQChannel channel) throws AMQException; + + List getChannels(); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java index 81dbeeded2..8497c95e26 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java @@ -79,7 +79,7 @@ import org.apache.qpid.server.management.ManagedObject; @MBeanDescription("Management Bean for an AMQ Broker Connection") public class AMQProtocolSessionMBean extends AMQManagedObject implements ManagedConnection { - private AMQMinaProtocolSession _session = null; + private AMQProtocolSession _protocolSession = null; private String _name = null; // openmbean data types for representing the channel attributes @@ -92,10 +92,10 @@ public class AMQProtocolSessionMBean extends AMQManagedObject implements Managed new AMQShortString("Broker Management Console has closed the connection."); @MBeanConstructor("Creates an MBean exposing an AMQ Broker Connection") - public AMQProtocolSessionMBean(AMQMinaProtocolSession session) throws NotCompliantMBeanException, OpenDataException + public AMQProtocolSessionMBean(AMQProtocolSession amqProtocolSession) throws NotCompliantMBeanException, OpenDataException { super(ManagedConnection.class, ManagedConnection.TYPE, ManagedConnection.VERSION); - _session = session; + _protocolSession = amqProtocolSession; String remote = getRemoteAddress(); remote = "anonymous".equals(remote) ? (remote + hashCode()) : remote; _name = jmxEncode(new StringBuffer(remote), 0).toString(); @@ -128,52 +128,52 @@ public class AMQProtocolSessionMBean extends AMQManagedObject implements Managed public String getClientId() { - return (_session.getContextKey() == null) ? null : _session.getContextKey().toString(); + return (_protocolSession.getContextKey() == null) ? null : _protocolSession.getContextKey().toString(); } public String getAuthorizedId() { - return (_session.getAuthorizedID() != null ) ? _session.getAuthorizedID().getName() : null; + return (_protocolSession.getAuthorizedID() != null ) ? _protocolSession.getAuthorizedID().getName() : null; } public String getVersion() { - return (_session.getClientVersion() == null) ? null : _session.getClientVersion().toString(); + return (_protocolSession.getClientVersion() == null) ? null : _protocolSession.getClientVersion().toString(); } public Date getLastIoTime() { - return new Date(_session.getIOSession().getLastIoTime()); + return new Date(_protocolSession.getLastIoTime()); } public String getRemoteAddress() { - return _session.getIOSession().getRemoteAddress().toString(); + return _protocolSession.getRemoteAddress().toString(); } public ManagedObject getParentObject() { - return _session.getVirtualHost().getManagedObject(); + return _protocolSession.getVirtualHost().getManagedObject(); } public Long getWrittenBytes() { - return _session.getIOSession().getWrittenBytes(); + return _protocolSession.getWrittenBytes(); } public Long getReadBytes() { - return _session.getIOSession().getReadBytes(); + return _protocolSession.getWrittenBytes(); } public Long getMaximumNumberOfChannels() { - return _session.getMaximumNumberOfChannels(); + return _protocolSession.getMaximumNumberOfChannels(); } public void setMaximumNumberOfChannels(Long value) { - _session.setMaximumNumberOfChannels(value); + _protocolSession.setMaximumNumberOfChannels(value); } public String getObjectInstanceName() @@ -192,13 +192,13 @@ public class AMQProtocolSessionMBean extends AMQManagedObject implements Managed CurrentActor.set(new ManagementActor(_logActor.getRootMessageLogger())); try { - AMQChannel channel = _session.getChannel(channelId); + AMQChannel channel = _protocolSession.getChannel(channelId); if (channel == null) { throw new JMException("The channel (channel Id = " + channelId + ") does not exist"); } - _session.commitTransactions(channel); + _protocolSession.commitTransactions(channel); } catch (AMQException ex) { @@ -221,13 +221,13 @@ public class AMQProtocolSessionMBean extends AMQManagedObject implements Managed CurrentActor.set(new ManagementActor(_logActor.getRootMessageLogger())); try { - AMQChannel channel = _session.getChannel(channelId); + AMQChannel channel = _protocolSession.getChannel(channelId); if (channel == null) { throw new JMException("The channel (channel Id = " + channelId + ") does not exist"); } - _session.rollbackTransactions(channel); + _protocolSession.commitTransactions(channel); } catch (AMQException ex) { @@ -248,7 +248,7 @@ public class AMQProtocolSessionMBean extends AMQManagedObject implements Managed public TabularData channels() throws OpenDataException { TabularDataSupport channelsList = new TabularDataSupport(_channelsType); - List list = _session.getChannels(); + List list = _protocolSession.getChannels(); for (AMQChannel channel : list) { @@ -274,7 +274,7 @@ public class AMQProtocolSessionMBean extends AMQManagedObject implements Managed public void closeConnection() throws JMException { - MethodRegistry methodRegistry = _session.getMethodRegistry(); + MethodRegistry methodRegistry = _protocolSession.getMethodRegistry(); ConnectionCloseBody responseBody = methodRegistry.createConnectionCloseBody(AMQConstant.REPLY_SUCCESS.getCode(), // replyCode @@ -301,12 +301,12 @@ public class AMQProtocolSessionMBean extends AMQManagedObject implements Managed try { - _session.writeFrame(responseBody.generateFrame(0)); + _protocolSession.writeFrame(responseBody.generateFrame(0)); try { - _session.closeSession(); + _protocolSession.closeSession(); } catch (AMQException ex) { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java index b6137e83de..9575bfa1ec 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java @@ -258,7 +258,7 @@ public abstract class ApplicationRegistry implements IApplicationRegistry for (InetSocketAddress bindAddress : _acceptors.keySet()) { QpidAcceptor acceptor = _acceptors.get(bindAddress); - acceptor.getIoAcceptor().unbind(bindAddress); + acceptor.getNetworkDriver().close(); CurrentActor.get().message(BrokerMessages.BRK_1003(acceptor.toString(), bindAddress.getPort())); } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/network/FirewallPlugin.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/network/FirewallPlugin.java index 810be8ae22..3a81932123 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/network/FirewallPlugin.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/network/FirewallPlugin.java @@ -23,7 +23,6 @@ package org.apache.qpid.server.security.access.plugins.network; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; -import java.util.Iterator; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import java.util.regex.Pattern; @@ -32,7 +31,6 @@ import org.apache.commons.configuration.CompositeConfiguration; import org.apache.commons.configuration.Configuration; import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.XMLConfiguration; -import org.apache.qpid.server.protocol.AMQMinaProtocolSession; import org.apache.qpid.server.protocol.AMQProtocolSession; import org.apache.qpid.server.security.access.ACLPlugin; import org.apache.qpid.server.security.access.ACLPluginFactory; @@ -180,13 +178,13 @@ public class FirewallPlugin extends AbstractACLPlugin @Override public AuthzResult authoriseConnect(AMQProtocolSession session, VirtualHost virtualHost) { - if (!(session instanceof AMQMinaProtocolSession)) + SocketAddress sockAddr = session.getRemoteAddress(); + if (!(sockAddr instanceof InetSocketAddress)) { - return AuthzResult.ABSTAIN; // We only deal with tcp sessions, which - // mean MINA right now + return AuthzResult.ABSTAIN; // We only deal with tcp sessions } - InetAddress addr = getInetAdressFromMinaSession((AMQMinaProtocolSession) session); + InetAddress addr = ((InetSocketAddress) sockAddr).getAddress(); if (addr == null) { @@ -213,19 +211,6 @@ public class FirewallPlugin extends AbstractACLPlugin } - private InetAddress getInetAdressFromMinaSession(AMQMinaProtocolSession session) - { - SocketAddress remote = session.getIOSession().getRemoteAddress(); - if (remote instanceof InetSocketAddress) - { - return ((InetSocketAddress) remote).getAddress(); - } - else - { - return null; - } - } - @Override public void setConfiguration(Configuration config) throws ConfigurationException { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/QpidAcceptor.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/QpidAcceptor.java index 61cc7cdeb6..3ca22b60c8 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/QpidAcceptor.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/QpidAcceptor.java @@ -20,21 +20,21 @@ */ package org.apache.qpid.server.transport; -import org.apache.mina.common.IoAcceptor; +import org.apache.qpid.transport.NetworkDriver; public class QpidAcceptor { - IoAcceptor _acceptor; + NetworkDriver _driver; String _protocol; - public QpidAcceptor(IoAcceptor acceptor, String protocol) + public QpidAcceptor(NetworkDriver driver, String protocol) { - _acceptor = acceptor; + _driver = driver; _protocol = protocol; } - public IoAcceptor getIoAcceptor() + public NetworkDriver getNetworkDriver() { - return _acceptor; + return _driver; } public String toString() diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java index 8cb0837b39..1162687741 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java @@ -20,27 +20,27 @@ */ package org.apache.qpid.server.configuration; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; + import junit.framework.TestCase; + import org.apache.commons.configuration.Configuration; import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.XMLConfiguration; -import org.apache.qpid.codec.AMQCodecFactory; -import org.apache.qpid.server.protocol.AMQMinaProtocolSession; +import org.apache.qpid.server.protocol.AMQProtocolEngine; import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.protocol.TestIoSession; +import org.apache.qpid.server.protocol.TestNetworkDriver; import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.registry.ConfigurationFileApplicationRegistry; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.server.virtualhost.VirtualHostRegistry; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; - public class ServerConfigurationTest extends TestCase { @@ -589,12 +589,12 @@ public class ServerConfigurationTest extends TestCase { // Check default ServerConfiguration serverConfig = new ServerConfiguration(_config); - assertEquals(true, serverConfig.getSSLOnly()); + assertEquals(false, serverConfig.getSSLOnly()); // Check value we set - _config.setProperty("connector.ssl.sslOnly", false); + _config.setProperty("connector.ssl.sslOnly", true); serverConfig = new ServerConfiguration(_config); - assertEquals(false, serverConfig.getSSLOnly()); + assertEquals(true, serverConfig.getSSLOnly()); } public void testGetSSLPort() throws ConfigurationException @@ -791,16 +791,15 @@ public class ServerConfigurationTest extends TestCase // Test config VirtualHostRegistry virtualHostRegistry = reg.getVirtualHostRegistry(); VirtualHost virtualHost = virtualHostRegistry.getVirtualHost("test"); - AMQCodecFactory codecFactory = new AMQCodecFactory(true); - - TestIoSession iosession = new TestIoSession(); - iosession.setAddress("127.0.0.1"); - AMQProtocolSession session = new AMQMinaProtocolSession(iosession, virtualHostRegistry, codecFactory); + TestNetworkDriver testDriver = new TestNetworkDriver(); + testDriver.setAddress("127.0.0.1"); + + AMQProtocolEngine session = new AMQProtocolEngine(virtualHostRegistry, testDriver); assertFalse(reg.getAccessManager().authoriseConnect(session, virtualHost)); - iosession.setAddress("127.1.2.3"); - session = new AMQMinaProtocolSession(iosession, virtualHostRegistry, codecFactory); + testDriver.setAddress("127.1.2.3"); + session = new AMQProtocolEngine(virtualHostRegistry, testDriver); assertTrue(reg.getAccessManager().authoriseConnect(session, virtualHost)); } @@ -866,12 +865,12 @@ public class ServerConfigurationTest extends TestCase // Test config VirtualHostRegistry virtualHostRegistry = reg.getVirtualHostRegistry(); VirtualHost virtualHost = virtualHostRegistry.getVirtualHost("test"); - AMQCodecFactory codecFactory = new AMQCodecFactory(true); - TestIoSession iosession = new TestIoSession(); - iosession.setAddress("127.0.0.1"); + TestNetworkDriver testDriver = new TestNetworkDriver(); + testDriver.setAddress("127.0.0.1"); - AMQProtocolSession session = new AMQMinaProtocolSession(iosession, virtualHostRegistry, codecFactory); + AMQProtocolEngine session = new AMQProtocolEngine(virtualHostRegistry, testDriver); + session.setNetworkDriver(testDriver); assertFalse(reg.getAccessManager().authoriseConnect(session, virtualHost)); } @@ -935,12 +934,11 @@ public class ServerConfigurationTest extends TestCase ApplicationRegistry.initialise(reg, 1); // Test config - TestIoSession iosession = new TestIoSession(); - iosession.setAddress("127.0.0.1"); + TestNetworkDriver testDriver = new TestNetworkDriver(); + testDriver.setAddress("127.0.0.1"); VirtualHostRegistry virtualHostRegistry = reg.getVirtualHostRegistry(); VirtualHost virtualHost = virtualHostRegistry.getVirtualHost("test"); - AMQCodecFactory codecFactory = new AMQCodecFactory(true); - AMQProtocolSession session = new AMQMinaProtocolSession(iosession, virtualHostRegistry, codecFactory); + AMQProtocolSession session = new AMQProtocolEngine(virtualHostRegistry, testDriver); assertFalse(reg.getAccessManager().authoriseConnect(session, virtualHost)); RandomAccessFile fileBRandom = new RandomAccessFile(fileB, "rw"); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBeanTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBeanTest.java index e199255f50..bc36c61382 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBeanTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBeanTest.java @@ -44,7 +44,7 @@ public class AMQProtocolSessionMBeanTest extends TestCase private static final Logger log = Logger.getLogger(AMQProtocolSessionMBeanTest.class); private MessageStore _messageStore = new SkeletonMessageStore(); - private AMQMinaProtocolSession _protocolSession; + private AMQProtocolEngine _protocolSession; private AMQChannel _channel; private AMQProtocolSessionMBean _mbean; diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/InternalTestProtocolSession.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/InternalTestProtocolSession.java index 37dfead2e5..c4362f2c60 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/InternalTestProtocolSession.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/InternalTestProtocolSession.java @@ -20,23 +20,22 @@ */ package org.apache.qpid.server.protocol; -import org.apache.qpid.AMQException; -import org.apache.qpid.codec.AMQCodecFactory; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.server.output.ProtocolOutputConverter; -import org.apache.qpid.server.queue.AMQMessage; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.virtualhost.VirtualHost; - +import java.security.Principal; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; -import java.security.Principal; -public class InternalTestProtocolSession extends AMQMinaProtocolSession implements ProtocolOutputConverter +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.server.output.ProtocolOutputConverter; +import org.apache.qpid.server.queue.AMQMessage; +import org.apache.qpid.server.registry.ApplicationRegistry; +import org.apache.qpid.server.virtualhost.VirtualHost; + +public class InternalTestProtocolSession extends AMQProtocolEngine implements ProtocolOutputConverter { // ChannelID(LIST) -> LinkedList final Map>> _channelDelivers; @@ -44,9 +43,7 @@ public class InternalTestProtocolSession extends AMQMinaProtocolSession implemen public InternalTestProtocolSession(VirtualHost virtualHost) throws AMQException { - super(new TestIoSession(), - ApplicationRegistry.getInstance().getVirtualHostRegistry(), - new AMQCodecFactory(true)); + super(ApplicationRegistry.getInstance().getVirtualHostRegistry(), new TestNetworkDriver()); _channelDelivers = new HashMap>>(); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/MaxChannelsTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/MaxChannelsTest.java index 8597fc5863..e37492bcb0 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/MaxChannelsTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/MaxChannelsTest.java @@ -37,7 +37,7 @@ import java.security.Principal; /** Test class to test MBean operations for AMQMinaProtocolSession. */ public class MaxChannelsTest extends TestCase { - private AMQMinaProtocolSession _session; + private AMQProtocolEngine _session; public void testChannels() throws Exception { diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/TestIoSession.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/TestIoSession.java deleted file mode 100644 index 211f491867..0000000000 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/TestIoSession.java +++ /dev/null @@ -1,328 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.protocol; - -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -import org.apache.mina.common.CloseFuture; -import org.apache.mina.common.IdleStatus; -import org.apache.mina.common.IoFilterChain; -import org.apache.mina.common.IoHandler; -import org.apache.mina.common.IoService; -import org.apache.mina.common.IoServiceConfig; -import org.apache.mina.common.IoSession; -import org.apache.mina.common.IoSessionConfig; -import org.apache.mina.common.ThreadModel; -import org.apache.mina.common.TrafficMask; -import org.apache.mina.common.TransportType; -import org.apache.mina.common.WriteFuture; -import org.apache.mina.transport.socket.nio.SocketAcceptorConfig; -import org.apache.qpid.pool.ReadWriteThreadModel; - -/** - * Test implementation of IoSession, which is required for some tests. Methods not being used are not implemented, - * so if this class is being used and some methods are to be used, then please update those. - */ -public class TestIoSession implements IoSession -{ - private final ConcurrentMap attributes = new ConcurrentHashMap(); - private String _address = "127.0.0.1"; - private int _port = 1; - - public TestIoSession() - { - } - - public IoService getService() - { - return null; - } - - public IoServiceConfig getServiceConfig() - { - return new TestIoConfig(); - } - - public IoHandler getHandler() - { - return null; - } - - public IoSessionConfig getConfig() - { - return null; - } - - public IoFilterChain getFilterChain() - { - return null; - } - - public WriteFuture write(Object message) - { - return null; - } - - public CloseFuture close() - { - return null; - } - - public Object getAttachment() - { - return getAttribute(""); - } - - public Object setAttachment(Object attachment) - { - return setAttribute("",attachment); - } - - public Object getAttribute(String key) - { - return attributes.get(key); - } - - public Object setAttribute(String key, Object value) - { - return attributes.put(key,value); - } - - public Object setAttribute(String key) - { - return attributes.put(key, Boolean.TRUE); - } - - public Object removeAttribute(String key) - { - return attributes.remove(key); - } - - public boolean containsAttribute(String key) - { - return attributes.containsKey(key); - } - - public Set getAttributeKeys() - { - return attributes.keySet(); - } - - public TransportType getTransportType() - { - return null; - } - - public boolean isConnected() - { - return false; - } - - public boolean isClosing() - { - return false; - } - - public CloseFuture getCloseFuture() - { - return null; - } - - public SocketAddress getRemoteAddress() - { - return new InetSocketAddress(getAddress(), getPort()); - } - - public SocketAddress getLocalAddress() - { - return null; - } - - public SocketAddress getServiceAddress() - { - return null; - } - - public int getIdleTime(IdleStatus status) - { - return 0; - } - - public long getIdleTimeInMillis(IdleStatus status) - { - return 0; - } - - public void setIdleTime(IdleStatus status, int idleTime) - { - - } - - public int getWriteTimeout() - { - return 0; - } - - public long getWriteTimeoutInMillis() - { - return 0; - } - - public void setWriteTimeout(int writeTimeout) - { - - } - - public TrafficMask getTrafficMask() - { - return null; - } - - public void setTrafficMask(TrafficMask trafficMask) - { - - } - - public void suspendRead() - { - - } - - public void suspendWrite() - { - - } - - public void resumeRead() - { - - } - - public void resumeWrite() - { - - } - - public long getReadBytes() - { - return 0; - } - - public long getWrittenBytes() - { - return 0; - } - - public long getReadMessages() - { - return 0; - } - - public long getWrittenMessages() - { - return 0; - } - - public long getWrittenWriteRequests() - { - return 0; - } - - public int getScheduledWriteRequests() - { - return 0; - } - - public int getScheduledWriteBytes() - { - return 0; - } - - public long getCreationTime() - { - return 0; - } - - public long getLastIoTime() - { - return 0; - } - - public long getLastReadTime() - { - return 0; - } - - public long getLastWriteTime() - { - return 0; - } - - public boolean isIdle(IdleStatus status) - { - return false; - } - - public int getIdleCount(IdleStatus status) - { - return 0; - } - - public long getLastIdleTime(IdleStatus status) - { - return 0; - } - - public void setAddress(String string) - { - this._address = string; - } - - public String getAddress() - { - return _address; - } - - public void setPort(int _port) - { - this._port = _port; - } - - public int getPort() - { - return _port; - } - - /** - * Test implementation of IoServiceConfig - */ - private class TestIoConfig extends SocketAcceptorConfig - { - public ThreadModel getThreadModel() - { - return ReadWriteThreadModel.getInstance(); - } - } -} diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/TestNetworkDriver.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/TestNetworkDriver.java new file mode 100644 index 0000000000..098843d315 --- /dev/null +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/TestNetworkDriver.java @@ -0,0 +1,126 @@ +/* + * + * 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.protocol; + +import java.net.BindException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.nio.ByteBuffer; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import javax.net.ssl.SSLEngine; + +import org.apache.qpid.protocol.ProtocolEngine; +import org.apache.qpid.protocol.ProtocolEngineFactory; +import org.apache.qpid.ssl.SSLContextFactory; +import org.apache.qpid.transport.NetworkDriver; +import org.apache.qpid.transport.NetworkDriverConfiguration; +import org.apache.qpid.transport.OpenException; + +/** + * Test implementation of IoSession, which is required for some tests. Methods not being used are not implemented, + * so if this class is being used and some methods are to be used, then please update those. + */ +public class TestNetworkDriver implements NetworkDriver +{ + private final ConcurrentMap attributes = new ConcurrentHashMap(); + private String _address = "127.0.0.1"; + private int _port = 1; + + public TestNetworkDriver() + { + } + + public void setAddress(String string) + { + this._address = string; + } + + public String getAddress() + { + return _address; + } + + public void setPort(int _port) + { + this._port = _port; + } + + public int getPort() + { + return _port; + } + + public void bind(int port, InetAddress[] addresses, ProtocolEngineFactory protocolFactory, + NetworkDriverConfiguration config, SSLContextFactory sslFactory) throws BindException + { + + } + + public SocketAddress getLocalAddress() + { + return new InetSocketAddress(_address, _port); + } + + public SocketAddress getRemoteAddress() + { + return new InetSocketAddress(_address, _port); + } + + public void open(int port, InetAddress destination, ProtocolEngine engine, NetworkDriverConfiguration config, + SSLEngine sslEngine) throws OpenException + { + + } + + public void setMaxReadIdle(int idleTime) + { + + } + + public void setMaxWriteIdle(int idleTime) + { + + } + + public void close() + { + + } + + public void flush() + { + + } + + public void send(ByteBuffer msg) + { + + } + + public void setIdleTimeout(long l) + { + + } + +} diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java index 8c6260ca9e..19470e6226 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java @@ -20,37 +20,34 @@ */ package org.apache.qpid.server.queue; +import java.util.ArrayList; +import java.util.LinkedList; + +import javax.management.Notification; + import junit.framework.TestCase; + +import org.apache.mina.common.ByteBuffer; import org.apache.qpid.AMQException; -import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.MemoryMessageStore; -import org.apache.qpid.server.store.StoreContext; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.server.registry.IApplicationRegistry; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.txn.TransactionalContext; -import org.apache.qpid.server.txn.NonTransactionalContext; -import org.apache.qpid.server.RequiredDeliveryException; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.ContentHeaderBody; +import org.apache.qpid.framing.abstraction.ContentChunk; +import org.apache.qpid.framing.abstraction.MessagePublishInfo; import org.apache.qpid.server.AMQChannel; +import org.apache.qpid.server.RequiredDeliveryException; import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.server.protocol.AMQProtocolEngine; +import org.apache.qpid.server.protocol.InternalTestProtocolSession; +import org.apache.qpid.server.registry.ApplicationRegistry; +import org.apache.qpid.server.registry.IApplicationRegistry; +import org.apache.qpid.server.store.MemoryMessageStore; +import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.StoreContext; import org.apache.qpid.server.subscription.Subscription; import org.apache.qpid.server.subscription.SubscriptionFactoryImpl; -import org.apache.qpid.server.protocol.AMQMinaProtocolSession; -import org.apache.qpid.server.protocol.InternalTestProtocolSession; -import org.apache.qpid.framing.ContentHeaderBody; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.abstraction.MessagePublishInfo; -import org.apache.qpid.framing.abstraction.ContentChunk; -import org.apache.commons.configuration.CompositeConfiguration; -import org.apache.mina.common.ByteBuffer; - -import javax.management.Notification; - -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.Collections; -import java.util.Set; -import java.security.Principal; +import org.apache.qpid.server.txn.NonTransactionalContext; +import org.apache.qpid.server.txn.TransactionalContext; +import org.apache.qpid.server.virtualhost.VirtualHost; /** This class tests all the alerts an AMQQueue can throw based on threshold values of different parameters */ public class AMQQueueAlertTest extends TestCase @@ -62,7 +59,7 @@ public class AMQQueueAlertTest extends TestCase private AMQQueue _queue; private AMQQueueMBean _queueMBean; private VirtualHost _virtualHost; - private AMQMinaProtocolSession _protocolSession; + private AMQProtocolEngine _protocolSession; private MessageStore _messageStore = new MemoryMessageStore(); private StoreContext _storeContext = new StoreContext(); private TransactionalContext _transactionalContext = new NonTransactionalContext(_messageStore, _storeContext, diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/plugins/network/FirewallPluginTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/plugins/network/FirewallPluginTest.java index a497365b06..bda816f5ab 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/plugins/network/FirewallPluginTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/plugins/network/FirewallPluginTest.java @@ -30,17 +30,14 @@ import java.net.InetSocketAddress; import junit.framework.TestCase; import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.PropertiesConfiguration; import org.apache.commons.configuration.XMLConfiguration; -import org.apache.qpid.codec.AMQCodecFactory; -import org.apache.qpid.server.configuration.VirtualHostConfiguration; -import org.apache.qpid.server.protocol.AMQMinaProtocolSession; -import org.apache.qpid.server.protocol.TestIoSession; +import org.apache.qpid.server.protocol.AMQProtocolEngine; +import org.apache.qpid.server.protocol.TestNetworkDriver; +import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.security.access.ACLPlugin.AuthzResult; import org.apache.qpid.server.store.TestableMemoryMessageStore; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.server.virtualhost.VirtualHostRegistry; -import org.apache.qpid.server.registry.ApplicationRegistry; public class FirewallPluginTest extends TestCase { @@ -84,22 +81,22 @@ public class FirewallPluginTest extends TestCase private TestableMemoryMessageStore _store; private VirtualHost _virtualHost; - private AMQMinaProtocolSession _session; + private AMQProtocolEngine _session; + private TestNetworkDriver _testDriver; @Override public void setUp() throws Exception { super.setUp(); _store = new TestableMemoryMessageStore(); - TestIoSession iosession = new TestIoSession(); - iosession.setAddress("127.0.0.1"); + _testDriver = new TestNetworkDriver(); + _testDriver.setAddress("127.0.0.1"); // Retreive VirtualHost from the Registry VirtualHostRegistry virtualHostRegistry = ApplicationRegistry.getInstance().getVirtualHostRegistry(); _virtualHost = virtualHostRegistry.getVirtualHost("test"); - AMQCodecFactory codecFactory = new AMQCodecFactory(true); - _session = new AMQMinaProtocolSession(iosession, virtualHostRegistry, codecFactory); + _session = new AMQProtocolEngine(virtualHostRegistry, _testDriver); } public void tearDown() throws Exception @@ -170,7 +167,7 @@ public class FirewallPluginTest extends TestCase assertEquals(AuthzResult.DENIED, plugin.authoriseConnect(_session, _virtualHost)); // Set session IP so that we're connected from the right address - ((TestIoSession) _session.getIOSession()).setAddress("192.168.23.23"); + _testDriver.setAddress("192.168.23.23"); assertEquals(AuthzResult.ALLOWED, plugin.authoriseConnect(_session, _virtualHost)); } @@ -185,7 +182,7 @@ public class FirewallPluginTest extends TestCase assertEquals(AuthzResult.DENIED, plugin.authoriseConnect(_session, _virtualHost)); // Set session IP so that we're connected from the right address - ((TestIoSession) _session.getIOSession()).setAddress("192.168.23.23"); + _testDriver.setAddress("192.168.23.23"); assertEquals(AuthzResult.ALLOWED, plugin.authoriseConnect(_session, _virtualHost)); } @@ -198,7 +195,7 @@ public class FirewallPluginTest extends TestCase FirewallPlugin plugin = initialisePlugin("deny", new RuleInfo[]{rule}); // Set session IP so that we're connected from the right address - ((TestIoSession) _session.getIOSession()).setAddress("127.0.0.1"); + _testDriver.setAddress("127.0.0.1"); assertEquals(AuthzResult.ALLOWED, plugin.authoriseConnect(_session, _virtualHost)); } @@ -211,7 +208,7 @@ public class FirewallPluginTest extends TestCase FirewallPlugin plugin = initialisePlugin("deny", new RuleInfo[]{rule}); // Set session IP so that we're connected from the right address - ((TestIoSession) _session.getIOSession()).setAddress("127.0.0.1"); + _testDriver.setAddress("127.0.0.1"); assertEquals(AuthzResult.ALLOWED, plugin.authoriseConnect(_session, _virtualHost)); } @@ -234,7 +231,7 @@ public class FirewallPluginTest extends TestCase assertEquals(AuthzResult.DENIED, plugin.authoriseConnect(_session, _virtualHost)); // Set session IP so that we're connected from the right address - ((TestIoSession) _session.getIOSession()).setAddress("192.168.23.23"); + _testDriver.setAddress("192.168.23.23"); assertEquals(AuthzResult.ALLOWED, plugin.authoriseConnect(_session, _virtualHost)); } @@ -257,7 +254,7 @@ public class FirewallPluginTest extends TestCase assertEquals(AuthzResult.DENIED, plugin.authoriseConnect(_session, _virtualHost)); // Set session IP so that we're connected from the right address - ((TestIoSession) _session.getIOSession()).setAddress("192.168.23.23"); + _testDriver.setAddress("192.168.23.23"); assertEquals(AuthzResult.ALLOWED, plugin.authoriseConnect(_session, _virtualHost)); } @@ -271,7 +268,7 @@ public class FirewallPluginTest extends TestCase assertEquals(AuthzResult.DENIED, plugin.authoriseConnect(_session, _virtualHost)); // Set session IP so that we're connected from the right address - ((TestIoSession) _session.getIOSession()).setAddress("192.168.23.23"); + _testDriver.setAddress("192.168.23.23"); assertEquals(AuthzResult.ALLOWED, plugin.authoriseConnect(_session, _virtualHost)); } @@ -285,7 +282,7 @@ public class FirewallPluginTest extends TestCase assertEquals(AuthzResult.DENIED, plugin.authoriseConnect(_session, _virtualHost)); // Set session IP so that we're connected from the right address - ((TestIoSession) _session.getIOSession()).setAddress("192.168.23.23"); + _testDriver.setAddress("192.168.23.23"); assertEquals(AuthzResult.ALLOWED, plugin.authoriseConnect(_session, _virtualHost)); } @@ -295,11 +292,11 @@ public class FirewallPluginTest extends TestCase firstRule.setAccess("allow"); firstRule.setHostname("foo, bar, "+new InetSocketAddress("127.0.0.1", 5672).getHostName()); FirewallPlugin plugin = initialisePlugin("deny", new RuleInfo[]{firstRule}); - ((TestIoSession) _session.getIOSession()).setAddress("10.0.0.1"); + _testDriver.setAddress("10.0.0.1"); assertEquals(AuthzResult.DENIED, plugin.authoriseConnect(_session, _virtualHost)); // Set session IP so that we're connected from the right address - ((TestIoSession) _session.getIOSession()).setAddress("127.0.0.1"); + _testDriver.setAddress("127.0.0.1"); assertEquals(AuthzResult.ALLOWED, plugin.authoriseConnect(_session, _virtualHost)); } diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java b/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java index 2389c9e2da..e3a1a82dc4 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java @@ -191,7 +191,7 @@ public class AMQProtocolHandler extends IoHandlerAdapter _logger.debug("Protocol session created for session " + System.identityHashCode(session)); _failoverHandler = new FailoverHandler(this, session); - final ProtocolCodecFilter pcf = new ProtocolCodecFilter(new AMQCodecFactory(false)); + final ProtocolCodecFilter pcf = new ProtocolCodecFilter(new AMQCodecFactory(false, _protocolSession)); if (Boolean.getBoolean("amqj.shared_read_write_pool")) { diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/transport/TransportConnection.java b/qpid/java/client/src/main/java/org/apache/qpid/client/transport/TransportConnection.java index 32cc8c4cb5..4ff24c3607 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/transport/TransportConnection.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/transport/TransportConnection.java @@ -31,7 +31,10 @@ import org.apache.mina.transport.vmpipe.VmPipeAddress; import org.apache.qpid.client.vmbroker.AMQVMBrokerCreationException; import org.apache.qpid.jms.BrokerDetails; import org.apache.qpid.pool.ReadWriteThreadModel; +import org.apache.qpid.protocol.ProtocolEngine; +import org.apache.qpid.protocol.ProtocolEngineFactory; import org.apache.qpid.thread.QpidThreadExecutor; +import org.apache.qpid.transport.network.mina.MINANetworkDriver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -62,7 +65,7 @@ public class TransportConnection private static Logger _logger = LoggerFactory.getLogger(TransportConnection.class); - private static final String DEFAULT_QPID_SERVER = "org.apache.qpid.server.protocol.AMQPFastProtocolHandler"; + private static final String DEFAULT_QPID_SERVER = "org.apache.qpid.server.protocol.AMQProtocolEngineFactory"; private static Map _openSocketRegister = new ConcurrentHashMap(); @@ -190,8 +193,6 @@ public class TransportConnection _acceptor = new VmPipeAcceptor(); IoServiceConfig config = _acceptor.getDefaultConfig(); - - config.setThreadModel(ReadWriteThreadModel.getInstance()); } synchronized (_inVmPipeAddress) { @@ -276,7 +277,10 @@ public class TransportConnection { Class[] cnstr = {Integer.class}; Object[] params = {port}; - provider = (IoHandlerAdapter) Class.forName(protocolProviderClass).getConstructor(cnstr).newInstance(params); + + provider = new MINANetworkDriver(); + ProtocolEngineFactory engineFactory = (ProtocolEngineFactory) Class.forName(protocolProviderClass).getConstructor(cnstr).newInstance(params); + ((MINANetworkDriver) provider).setProtocolEngineFactory(engineFactory, true); // Give the broker a second to create _logger.info("Created VMBroker Instance:" + port); } diff --git a/qpid/java/common/src/main/java/org/apache/qpid/codec/AMQCodecFactory.java b/qpid/java/common/src/main/java/org/apache/qpid/codec/AMQCodecFactory.java index fa890d0ebb..591dbd085b 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/codec/AMQCodecFactory.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/codec/AMQCodecFactory.java @@ -23,6 +23,7 @@ package org.apache.qpid.codec; import org.apache.mina.filter.codec.ProtocolCodecFactory; import org.apache.mina.filter.codec.ProtocolDecoder; import org.apache.mina.filter.codec.ProtocolEncoder; +import org.apache.qpid.protocol.AMQVersionAwareProtocolSession; /** * AMQCodecFactory is a Mina codec factory. It supplies the encoders and decoders need to read and write the bytes to @@ -50,9 +51,9 @@ public class AMQCodecFactory implements ProtocolCodecFactory * @param expectProtocolInitiation true if the first frame received is going to be a protocol initiation * frame, false if it is going to be a standard AMQ data block. */ - public AMQCodecFactory(boolean expectProtocolInitiation) + public AMQCodecFactory(boolean expectProtocolInitiation, AMQVersionAwareProtocolSession session) { - _frameDecoder = new AMQDecoder(expectProtocolInitiation); + _frameDecoder = new AMQDecoder(expectProtocolInitiation, session); } /** @@ -70,7 +71,7 @@ public class AMQCodecFactory implements ProtocolCodecFactory * * @return The AMQP decoder. */ - public ProtocolDecoder getDecoder() + public AMQDecoder getDecoder() { return _frameDecoder; } diff --git a/qpid/java/common/src/main/java/org/apache/qpid/codec/AMQDecoder.java b/qpid/java/common/src/main/java/org/apache/qpid/codec/AMQDecoder.java index 7eef73f337..281c0761d9 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/codec/AMQDecoder.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/codec/AMQDecoder.java @@ -20,14 +20,21 @@ */ package org.apache.qpid.codec; +import java.util.ArrayList; + import org.apache.mina.common.ByteBuffer; import org.apache.mina.common.IoSession; import org.apache.mina.common.SimpleByteBufferAllocator; import org.apache.mina.filter.codec.CumulativeProtocolDecoder; import org.apache.mina.filter.codec.ProtocolDecoderOutput; +import org.apache.qpid.framing.AMQDataBlock; import org.apache.qpid.framing.AMQDataBlockDecoder; +import org.apache.qpid.framing.AMQFrameDecodingException; +import org.apache.qpid.framing.AMQMethodBodyFactory; +import org.apache.qpid.framing.AMQProtocolVersionException; import org.apache.qpid.framing.ProtocolInitiation; +import org.apache.qpid.protocol.AMQVersionAwareProtocolSession; /** * AMQDecoder delegates the decoding of AMQP either to a data block decoder, or in the case of new connections, to a @@ -62,14 +69,19 @@ public class AMQDecoder extends CumulativeProtocolDecoder private boolean _expectProtocolInitiation; private boolean firstDecode = true; + private AMQMethodBodyFactory _bodyFactory; + + private ByteBuffer _remainingBuf; + /** * Creates a new AMQP decoder. * * @param expectProtocolInitiation true if this decoder needs to handle protocol initiation. */ - public AMQDecoder(boolean expectProtocolInitiation) + public AMQDecoder(boolean expectProtocolInitiation, AMQVersionAwareProtocolSession session) { _expectProtocolInitiation = expectProtocolInitiation; + _bodyFactory = new AMQMethodBodyFactory(session); } /** @@ -120,7 +132,7 @@ public class AMQDecoder extends CumulativeProtocolDecoder protected boolean doDecodeDataBlock(IoSession session, ByteBuffer in, ProtocolDecoderOutput out) throws Exception { int pos = in.position(); - boolean enoughData = _dataBlockDecoder.decodable(session, in); + boolean enoughData = _dataBlockDecoder.decodable(in.buf()); in.position(pos); if (!enoughData) { @@ -149,7 +161,7 @@ public class AMQDecoder extends CumulativeProtocolDecoder */ private boolean doDecodePI(IoSession session, ByteBuffer in, ProtocolDecoderOutput out) throws Exception { - boolean enoughData = _piDecoder.decodable(session, in); + boolean enoughData = _piDecoder.decodable(in.buf()); if (!enoughData) { // returning false means it will leave the contents in the buffer and @@ -158,7 +170,8 @@ public class AMQDecoder extends CumulativeProtocolDecoder } else { - _piDecoder.decode(session, in, out); + ProtocolInitiation pi = new ProtocolInitiation(in.buf()); + out.write(pi); return true; } @@ -177,7 +190,7 @@ public class AMQDecoder extends CumulativeProtocolDecoder } - /** + /** * Cumulates content of in into internal buffer and forwards * decoding request to {@link #doDecode(IoSession, ByteBuffer, ProtocolDecoderOutput)}. * doDecode() is invoked repeatedly until it returns false @@ -268,4 +281,60 @@ public class AMQDecoder extends CumulativeProtocolDecoder session.setAttribute( BUFFER, remainingBuf ); } + public ArrayList decodeBuffer(java.nio.ByteBuffer buf) throws AMQFrameDecodingException, AMQProtocolVersionException + { + + // get prior remaining data from accumulator + ArrayList dataBlocks = new ArrayList(); + ByteBuffer msg; + // if we have a session buffer, append data to that otherwise + // use the buffer read from the network directly + if( _remainingBuf != null ) + { + _remainingBuf.put(buf); + _remainingBuf.flip(); + msg = _remainingBuf; + } + else + { + msg = ByteBuffer.wrap(buf); + } + + if (_expectProtocolInitiation + || (firstDecode + && (msg.remaining() > 0) + && (msg.get(msg.position()) == (byte)'A'))) + { + if (_piDecoder.decodable(msg.buf())) + { + dataBlocks.add(new ProtocolInitiation(msg.buf())); + } + } + else + { + boolean enoughData = true; + while (enoughData) + { + int pos = msg.position(); + + enoughData = _dataBlockDecoder.decodable(msg); + msg.position(pos); + if (enoughData) + { + dataBlocks.add(_dataBlockDecoder.createAndPopulateFrame(_bodyFactory, msg)); + } + else + { + _remainingBuf = SIMPLE_BYTE_BUFFER_ALLOCATOR.allocate(msg.remaining(), false); + _remainingBuf.setAutoExpand(true); + _remainingBuf.put(msg); + } + } + } + if(firstDecode && dataBlocks.size() > 0) + { + firstDecode = false; + } + return dataBlocks; + } } diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlockDecoder.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlockDecoder.java index 82ffc60802..228867b2b0 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlockDecoder.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlockDecoder.java @@ -47,7 +47,7 @@ public class AMQDataBlockDecoder public AMQDataBlockDecoder() { } - public boolean decodable(IoSession session, ByteBuffer in) throws AMQFrameDecodingException + public boolean decodable(java.nio.ByteBuffer in) throws AMQFrameDecodingException { final int remainingAfterAttributes = in.remaining() - (1 + 2 + 4 + 1); // type, channel, body length and end byte @@ -56,14 +56,15 @@ public class AMQDataBlockDecoder return false; } - in.skip(1 + 2); - final long bodySize = in.getUnsignedInt(); + in.position(in.position() + 1 + 2); + // Get an unsigned int, lifted from MINA ByteBuffer getUnsignedInt() + final long bodySize = in.getInt() & 0xffffffffL; return (remainingAfterAttributes >= bodySize); } - protected Object createAndPopulateFrame(IoSession session, ByteBuffer in) + public AMQFrame createAndPopulateFrame(AMQMethodBodyFactory methodBodyFactory, ByteBuffer in) throws AMQFrameDecodingException, AMQProtocolVersionException { final byte type = in.get(); @@ -71,15 +72,7 @@ public class AMQDataBlockDecoder BodyFactory bodyFactory; if (type == AMQMethodBody.TYPE) { - bodyFactory = (BodyFactory) session.getAttribute(SESSION_METHOD_BODY_FACTORY); - if (bodyFactory == null) - { - AMQVersionAwareProtocolSession protocolSession = (AMQVersionAwareProtocolSession) session.getAttachment(); - bodyFactory = new AMQMethodBodyFactory(protocolSession); - session.setAttribute(SESSION_METHOD_BODY_FACTORY, bodyFactory); - - } - + bodyFactory = methodBodyFactory; } else { @@ -115,6 +108,24 @@ public class AMQDataBlockDecoder public void decode(IoSession session, ByteBuffer in, ProtocolDecoderOutput out) throws Exception { - out.write(createAndPopulateFrame(session, in)); + AMQMethodBodyFactory bodyFactory = (AMQMethodBodyFactory) session.getAttribute(SESSION_METHOD_BODY_FACTORY); + if (bodyFactory == null) + { + AMQVersionAwareProtocolSession protocolSession = (AMQVersionAwareProtocolSession) session.getAttachment(); + bodyFactory = new AMQMethodBodyFactory(protocolSession); + session.setAttribute(SESSION_METHOD_BODY_FACTORY, bodyFactory); + } + + out.write(createAndPopulateFrame(bodyFactory, in)); + } + + public boolean decodable(ByteBuffer msg) throws AMQFrameDecodingException + { + return decodable(msg.buf()); + } + + public AMQDataBlock createAndPopulateFrame(AMQMethodBodyFactory factory, java.nio.ByteBuffer msg) throws AMQProtocolVersionException, AMQFrameDecodingException + { + return createAndPopulateFrame(factory, ByteBuffer.wrap(msg)); } } diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlockEncoder.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlockEncoder.java index 05fd2bb480..374644b4f2 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlockEncoder.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlockEncoder.java @@ -50,7 +50,7 @@ public final class AMQDataBlockEncoder implements MessageEncoder { _logger.debug("Encoded frame byte-buffer is '" + EncodingUtils.convertToHexString(buffer) + "'"); } - + out.write(buffer); } diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/ProtocolInitiation.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/ProtocolInitiation.java index 3ac17e9204..cf8a866e47 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/framing/ProtocolInitiation.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/ProtocolInitiation.java @@ -20,12 +20,10 @@ */ package org.apache.qpid.framing; -import org.apache.mina.common.ByteBuffer; -import org.apache.mina.common.IoSession; -import org.apache.mina.filter.codec.ProtocolDecoderOutput; import org.apache.qpid.AMQException; import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; public class ProtocolInitiation extends AMQDataBlock implements EncodableAMQDataBlock { @@ -53,13 +51,12 @@ public class ProtocolInitiation extends AMQDataBlock implements EncodableAMQData _protocolMajor = protocolMajor; _protocolMinor = protocolMinor; } - + public ProtocolInitiation(ProtocolVersion pv) { this(AMQP_HEADER, CURRENT_PROTOCOL_CLASS, TCP_PROTOCOL_INSTANCE, pv.getMajorVersion(), pv.getMinorVersion()); } - public ProtocolInitiation(ByteBuffer in) { _protocolHeader = new byte[4]; @@ -71,6 +68,11 @@ public class ProtocolInitiation extends AMQDataBlock implements EncodableAMQData _protocolMinor = in.get(); } + public void writePayload(org.apache.mina.common.ByteBuffer buffer) + { + writePayload(buffer.buf()); + } + public long getSize() { return 4 + 1 + 1 + 1 + 1; @@ -127,16 +129,11 @@ public class ProtocolInitiation extends AMQDataBlock implements EncodableAMQData * @return true if we have enough data to decode the PI frame fully, false if more * data is required */ - public boolean decodable(IoSession session, ByteBuffer in) + public boolean decodable(ByteBuffer in) { return (in.remaining() >= 8); } - public void decode(IoSession session, ByteBuffer in, ProtocolDecoderOutput out) - { - ProtocolInitiation pi = new ProtocolInitiation(in); - out.write(pi); - } } public ProtocolVersion checkVersion() throws AMQException @@ -192,4 +189,5 @@ public class ProtocolInitiation extends AMQDataBlock implements EncodableAMQData buffer.append(Integer.toHexString(_protocolMinor)); return buffer.toString(); } + } diff --git a/qpid/java/common/src/main/java/org/apache/qpid/pool/Event.java b/qpid/java/common/src/main/java/org/apache/qpid/pool/Event.java index 5996cbf89c..49bce9f2f9 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/pool/Event.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/pool/Event.java @@ -45,21 +45,31 @@ import org.apache.mina.common.IoSession; * a continuation. Job is also a continuation, as is the job completion handler. Or, as Event is totally abstract, * it is really an interface, so could just drop it and use the continuation interface instead. */ -public abstract class Event +public class Event { + private Runnable _runner; + + public Event() + { + + } + /** * Creates a continuation. */ - public Event() - { } + public Event(Runnable runner) + { + _runner = runner; + } /** - * Processes the continuation in the context of a Mina session. - * - * @param session The Mina session. + * Processes the continuation */ - public abstract void process(IoSession session); - + public void process() + { + _runner.run(); + } + /** * A continuation ({@link Event}) that takes a Mina messageReceived event, and passes it to a NextFilter. * @@ -68,22 +78,22 @@ public abstract class Event * Pass a Mina messageReceived event to a NextFilter. {@link IoFilter.NextFilter}, {@link IoSession} * */ - public static final class ReceivedEvent extends Event + public static final class MinaReceivedEvent extends Event { private final Object _data; - private final IoFilter.NextFilter _nextFilter; + private final IoSession _session; - public ReceivedEvent(final IoFilter.NextFilter nextFilter, final Object data) + public MinaReceivedEvent(final IoFilter.NextFilter nextFilter, final Object data, final IoSession session) { - super(); _nextFilter = nextFilter; _data = data; + _session = session; } - public void process(IoSession session) + public void process() { - _nextFilter.messageReceived(session, _data); + _nextFilter.messageReceived(_session, _data); } public IoFilter.NextFilter getNextFilter() @@ -101,21 +111,22 @@ public abstract class Event * {@link IoFilter.NextFilter}, {@link IoFilter.WriteRequest}, {@link IoSession} * */ - public static final class WriteEvent extends Event + public static final class MinaWriteEvent extends Event { private final IoFilter.WriteRequest _data; private final IoFilter.NextFilter _nextFilter; + private IoSession _session; - public WriteEvent(final IoFilter.NextFilter nextFilter, final IoFilter.WriteRequest data) + public MinaWriteEvent(final IoFilter.NextFilter nextFilter, final IoFilter.WriteRequest data, final IoSession session) { - super(); _nextFilter = nextFilter; _data = data; + _session = session; } - public void process(IoSession session) + public void process() { - _nextFilter.filterWrite(session, _data); + _nextFilter.filterWrite(_session, _data); } public IoFilter.NextFilter getNextFilter() @@ -135,16 +146,17 @@ public abstract class Event public static final class CloseEvent extends Event { private final IoFilter.NextFilter _nextFilter; + private final IoSession _session; - public CloseEvent(final IoFilter.NextFilter nextFilter) + public CloseEvent(final IoFilter.NextFilter nextFilter, final IoSession session) { - super(); _nextFilter = nextFilter; + _session = session; } - public void process(IoSession session) + public void process() { - _nextFilter.sessionClosed(session); + _nextFilter.sessionClosed(_session); } public IoFilter.NextFilter getNextFilter() diff --git a/qpid/java/common/src/main/java/org/apache/qpid/pool/Job.java b/qpid/java/common/src/main/java/org/apache/qpid/pool/Job.java index 00da005515..4e4192dbe3 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/pool/Job.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/pool/Job.java @@ -55,9 +55,6 @@ public class Job implements ReadWriteRunnable /** The maximum number of events to process per run of the job. More events than this may be queued in the job. */ private final int _maxEvents; - /** The Mina session. */ - private final IoSession _session; - /** Holds the queue of events that make up the job. */ private final java.util.Queue _eventQueue = new ConcurrentLinkedQueue(); @@ -79,7 +76,13 @@ public class Job implements ReadWriteRunnable */ Job(IoSession session, JobCompletionHandler completionHandler, int maxEvents, final boolean readJob) { - _session = session; + _completionHandler = completionHandler; + _maxEvents = maxEvents; + _readJob = readJob; + } + + public Job(JobCompletionHandler completionHandler, int maxEvents, boolean readJob) + { _completionHandler = completionHandler; _maxEvents = maxEvents; _readJob = readJob; @@ -90,7 +93,7 @@ public class Job implements ReadWriteRunnable * * @param evt The continuation to enqueue. */ - void add(Event evt) + public void add(Event evt) { _eventQueue.add(evt); } @@ -111,7 +114,7 @@ public class Job implements ReadWriteRunnable } else { - e.process(_session); + e.process(); } } return false; @@ -153,30 +156,19 @@ public class Job implements ReadWriteRunnable if(processAll()) { deactivate(); - _completionHandler.completed(_session, this); + _completionHandler.completed(this); } else { - _completionHandler.notCompleted(_session, this); + _completionHandler.notCompleted(this); } } - public boolean isReadJob() - { - return _readJob; - } - public boolean isRead() { return _readJob; } - public boolean isWrite() - { - return !_readJob; - } - - /** * Another interface for a continuation. * @@ -185,8 +177,8 @@ public class Job implements ReadWriteRunnable */ static interface JobCompletionHandler { - public void completed(IoSession session, Job job); + public void completed(Job job); - public void notCompleted(final IoSession session, final Job job); + public void notCompleted(final Job job); } } diff --git a/qpid/java/common/src/main/java/org/apache/qpid/pool/PoolingFilter.java b/qpid/java/common/src/main/java/org/apache/qpid/pool/PoolingFilter.java index a080cc7e04..4863611c42 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/pool/PoolingFilter.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/pool/PoolingFilter.java @@ -20,19 +20,17 @@ */ package org.apache.qpid.pool; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.RejectedExecutionException; + import org.apache.mina.common.IdleStatus; import org.apache.mina.common.IoFilterAdapter; import org.apache.mina.common.IoSession; import org.apache.qpid.pool.Event.CloseEvent; - +import org.apache.qpid.pool.Event.MinaReceivedEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.concurrent.RejectedExecutionException; -import java.util.concurrent.ExecutorService; - /** * PoolingFilter, is a no-op pass through filter that hands all events down the Mina filter chain by default. As it * adds no behaviour by default to the filter chain, it is abstract. @@ -74,7 +72,7 @@ public abstract class PoolingFilter extends IoFilterAdapter implements Job.JobCo private final String _name; /** Defines the maximum number of events that will be batched into a single job. */ - static final int MAX_JOB_EVENTS = Integer.getInteger("amqj.server.read_write_pool.max_events", 10); + public static final int MAX_JOB_EVENTS = Integer.getInteger("amqj.server.read_write_pool.max_events", 10); private final int _maxEvents; @@ -188,7 +186,7 @@ public abstract class PoolingFilter extends IoFilterAdapter implements Job.JobCo Job job = new Job(session, this, MAX_JOB_EVENTS,_readFilter); session.setAttribute(_name, job); } - + /** * Retrieves this filters Job, by this filters name, from the Mina session. * @@ -208,7 +206,7 @@ public abstract class PoolingFilter extends IoFilterAdapter implements Job.JobCo * @param session The Mina session to work in. * @param job The job that completed. */ - public void completed(IoSession session, Job job) + public void completed(Job job) { @@ -239,7 +237,7 @@ public abstract class PoolingFilter extends IoFilterAdapter implements Job.JobCo } } - public void notCompleted(IoSession session, Job job) + public void notCompleted(Job job) { final ExecutorService pool = _poolReference.getPool(); @@ -430,7 +428,7 @@ public abstract class PoolingFilter extends IoFilterAdapter implements Job.JobCo public void messageReceived(NextFilter nextFilter, final IoSession session, Object message) { Job job = getJobForSession(session); - fireAsynchEvent(job, new Event.ReceivedEvent(nextFilter, message)); + fireAsynchEvent(job, new MinaReceivedEvent(nextFilter, message, session)); } /** @@ -442,7 +440,7 @@ public abstract class PoolingFilter extends IoFilterAdapter implements Job.JobCo public void sessionClosed(final NextFilter nextFilter, final IoSession session) { Job job = getJobForSession(session); - fireAsynchEvent(job, new CloseEvent(nextFilter)); + fireAsynchEvent(job, new CloseEvent(nextFilter, session)); } } @@ -473,7 +471,7 @@ public abstract class PoolingFilter extends IoFilterAdapter implements Job.JobCo public void filterWrite(final NextFilter nextFilter, final IoSession session, final WriteRequest writeRequest) { Job job = getJobForSession(session); - fireAsynchEvent(job, new Event.WriteEvent(nextFilter, writeRequest)); + fireAsynchEvent(job, new Event.MinaWriteEvent(nextFilter, writeRequest, session)); } /** @@ -485,7 +483,8 @@ public abstract class PoolingFilter extends IoFilterAdapter implements Job.JobCo public void sessionClosed(final NextFilter nextFilter, final IoSession session) { Job job = getJobForSession(session); - fireAsynchEvent(job, new CloseEvent(nextFilter)); + fireAsynchEvent(job, new CloseEvent(nextFilter, session)); } } + } diff --git a/qpid/java/common/src/main/java/org/apache/qpid/pool/ReadWriteRunnable.java b/qpid/java/common/src/main/java/org/apache/qpid/pool/ReadWriteRunnable.java index ad04a923e1..140c93ca8d 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/pool/ReadWriteRunnable.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/pool/ReadWriteRunnable.java @@ -23,5 +23,4 @@ package org.apache.qpid.pool; public interface ReadWriteRunnable extends Runnable { boolean isRead(); - boolean isWrite(); } diff --git a/qpid/java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngineFactory.java b/qpid/java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngineFactory.java index d8c0f2c916..9df84eef90 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngineFactory.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngineFactory.java @@ -20,10 +20,12 @@ */ package org.apache.qpid.protocol; +import org.apache.qpid.transport.NetworkDriver; + public interface ProtocolEngineFactory { // Returns a new instance of a ProtocolEngine - ProtocolEngine newProtocolEngine(); + ProtocolEngine newProtocolEngine(NetworkDriver networkDriver); } \ No newline at end of file diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/NetworkDriverConfiguration.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/NetworkDriverConfiguration.java index 18cae6bf85..c38afe5dd5 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/transport/NetworkDriverConfiguration.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/NetworkDriverConfiguration.java @@ -28,17 +28,17 @@ package org.apache.qpid.transport; public interface NetworkDriverConfiguration { // Taken from Socket - boolean getKeepAlive(); - boolean getOOBInline(); - boolean getReuseAddress(); + Boolean getKeepAlive(); + Boolean getOOBInline(); + Boolean getReuseAddress(); Integer getSoLinger(); // null means off - int getSoTimeout(); - boolean getTcpNoDelay(); - int getTrafficClass(); + Integer getSoTimeout(); + Boolean getTcpNoDelay(); + Integer getTrafficClass(); // The amount of memory in bytes to allocate to the incoming buffer - int getReceiveBufferSize(); + Integer getReceiveBufferSize(); // The amount of memory in bytes to allocate to the outgoing buffer - int getSendBufferSize(); + Integer getSendBufferSize(); } diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java index 7330a042df..477e2cd5af 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java @@ -181,6 +181,7 @@ public class MINANetworkDriver extends IoHandlerAdapter implements NetworkDriver { return _ioSession.getLocalAddress(); } + public void open(int port, InetAddress destination, ProtocolEngine engine, NetworkDriverConfiguration config, SSLEngine sslEngine) throws OpenException @@ -251,6 +252,10 @@ public class MINANetworkDriver extends IoHandlerAdapter implements NetworkDriver public void close() { + if (_lastWriteFuture != null) + { + _lastWriteFuture.join(); + } if (_acceptor != null) { _acceptor.unbindAll(); @@ -359,9 +364,14 @@ public class MINANetworkDriver extends IoHandlerAdapter implements NetworkDriver protocolSession.getFilterChain().remove("tempExecutorFilterForFilterBuilder"); } - + + if (_ioSession == null) + { + _ioSession = protocolSession; + } + // Set up the protocol engine - ProtocolEngine protocolEngine = _factory.newProtocolEngine(); + ProtocolEngine protocolEngine = _factory.newProtocolEngine(this); MINANetworkDriver newDriver = new MINANetworkDriver(_useNIO, _processors, _executorPool, _protectIO, protocolEngine, protocolSession); protocolEngine.setNetworkDriver(newDriver); protocolSession.setAttachment(protocolEngine); @@ -385,4 +395,10 @@ public class MINANetworkDriver extends IoHandlerAdapter implements NetworkDriver return _protocolEngine; } + public void setProtocolEngineFactory(ProtocolEngineFactory engineFactory, boolean acceptingConnections) + { + _factory = engineFactory; + _acceptingConnections = acceptingConnections; + } + } diff --git a/qpid/java/common/src/test/java/org/apache/qpid/codec/AMQDecoderTest.java b/qpid/java/common/src/test/java/org/apache/qpid/codec/AMQDecoderTest.java new file mode 100644 index 0000000000..46c812e265 --- /dev/null +++ b/qpid/java/common/src/test/java/org/apache/qpid/codec/AMQDecoderTest.java @@ -0,0 +1,130 @@ +package org.apache.qpid.codec; + +import java.nio.ByteBuffer; +import java.util.ArrayList; + +import junit.framework.TestCase; + +import org.apache.qpid.framing.AMQDataBlock; +import org.apache.qpid.framing.AMQFrame; +import org.apache.qpid.framing.AMQFrameDecodingException; +import org.apache.qpid.framing.AMQProtocolVersionException; +import org.apache.qpid.framing.HeartbeatBody; + +public class AMQDecoderTest extends TestCase +{ + + private AMQCodecFactory _factory; + private AMQDecoder _decoder; + + + public void setUp() + { + _factory = new AMQCodecFactory(false, null); + _decoder = _factory.getDecoder(); + } + + + public void testSingleFrameDecode() throws AMQProtocolVersionException, AMQFrameDecodingException + { + ByteBuffer msg = HeartbeatBody.FRAME.toNioByteBuffer(); + ArrayList frames = _decoder.decodeBuffer(msg); + if (frames.get(0) instanceof AMQFrame) + { + assertEquals(HeartbeatBody.FRAME.getBodyFrame().getFrameType(), ((AMQFrame) frames.get(0)).getBodyFrame().getFrameType()); + } + else + { + fail("decode was not a frame"); + } + } + + public void testPartialFrameDecode() throws AMQProtocolVersionException, AMQFrameDecodingException + { + ByteBuffer msg = HeartbeatBody.FRAME.toNioByteBuffer(); + ByteBuffer msgA = msg.slice(); + int msgbPos = msg.remaining() / 2; + int msgaLimit = msg.remaining() - msgbPos; + msgA.limit(msgaLimit); + msg.position(msgbPos); + ByteBuffer msgB = msg.slice(); + ArrayList frames = _decoder.decodeBuffer(msgA); + assertEquals(0, frames.size()); + frames = _decoder.decodeBuffer(msgB); + assertEquals(1, frames.size()); + if (frames.get(0) instanceof AMQFrame) + { + assertEquals(HeartbeatBody.FRAME.getBodyFrame().getFrameType(), ((AMQFrame) frames.get(0)).getBodyFrame().getFrameType()); + } + else + { + fail("decode was not a frame"); + } + } + + public void testMultipleFrameDecode() throws AMQProtocolVersionException, AMQFrameDecodingException + { + ByteBuffer msgA = HeartbeatBody.FRAME.toNioByteBuffer(); + ByteBuffer msgB = HeartbeatBody.FRAME.toNioByteBuffer(); + ByteBuffer msg = ByteBuffer.allocate(msgA.remaining() + msgB.remaining()); + msg.put(msgA); + msg.put(msgB); + msg.flip(); + ArrayList frames = _decoder.decodeBuffer(msg); + assertEquals(2, frames.size()); + for (AMQDataBlock frame : frames) + { + if (frame instanceof AMQFrame) + { + assertEquals(HeartbeatBody.FRAME.getBodyFrame().getFrameType(), ((AMQFrame) frame).getBodyFrame().getFrameType()); + } + else + { + fail("decode was not a frame"); + } + } + } + + public void testMultiplePartialFrameDecode() throws AMQProtocolVersionException, AMQFrameDecodingException + { + ByteBuffer msgA = HeartbeatBody.FRAME.toNioByteBuffer(); + ByteBuffer msgB = HeartbeatBody.FRAME.toNioByteBuffer(); + ByteBuffer msgC = HeartbeatBody.FRAME.toNioByteBuffer(); + + ByteBuffer sliceA = ByteBuffer.allocate(msgA.remaining() + msgB.remaining() / 2); + sliceA.put(msgA); + int limit = msgB.limit(); + int pos = msgB.remaining() / 2; + msgB.limit(pos); + sliceA.put(msgB); + sliceA.flip(); + msgB.limit(limit); + msgB.position(pos); + + ByteBuffer sliceB = ByteBuffer.allocate(msgB.remaining() + pos); + sliceB.put(msgB); + msgC.limit(pos); + sliceB.put(msgC); + sliceB.flip(); + msgC.limit(limit); + + ArrayList frames = _decoder.decodeBuffer(sliceA); + assertEquals(1, frames.size()); + frames = _decoder.decodeBuffer(sliceB); + assertEquals(1, frames.size()); + frames = _decoder.decodeBuffer(msgC); + assertEquals(1, frames.size()); + for (AMQDataBlock frame : frames) + { + if (frame instanceof AMQFrame) + { + assertEquals(HeartbeatBody.FRAME.getBodyFrame().getFrameType(), ((AMQFrame) frame).getBodyFrame().getFrameType()); + } + else + { + fail("decode was not a frame"); + } + } + } + +} diff --git a/qpid/java/common/src/test/java/org/apache/qpid/codec/MockAMQVersionAwareProtocolSession.java b/qpid/java/common/src/test/java/org/apache/qpid/codec/MockAMQVersionAwareProtocolSession.java new file mode 100644 index 0000000000..bd7fb68d93 --- /dev/null +++ b/qpid/java/common/src/test/java/org/apache/qpid/codec/MockAMQVersionAwareProtocolSession.java @@ -0,0 +1,95 @@ +package org.apache.qpid.codec; + +import java.nio.ByteBuffer; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.AMQDataBlock; +import org.apache.qpid.framing.AMQMethodBody; +import org.apache.qpid.framing.ContentBody; +import org.apache.qpid.framing.ContentHeaderBody; +import org.apache.qpid.framing.HeartbeatBody; +import org.apache.qpid.framing.MethodRegistry; +import org.apache.qpid.framing.ProtocolVersion; +import org.apache.qpid.protocol.AMQVersionAwareProtocolSession; +import org.apache.qpid.transport.Sender; + +public class MockAMQVersionAwareProtocolSession implements AMQVersionAwareProtocolSession +{ + + @Override + public void contentBodyReceived(int channelId, ContentBody body) throws AMQException + { + // TODO Auto-generated method stub + + } + + @Override + public void contentHeaderReceived(int channelId, ContentHeaderBody body) throws AMQException + { + // TODO Auto-generated method stub + + } + + @Override + public MethodRegistry getMethodRegistry() + { + return MethodRegistry.getMethodRegistry(ProtocolVersion.v0_9); + } + + @Override + public void heartbeatBodyReceived(int channelId, HeartbeatBody body) throws AMQException + { + // TODO Auto-generated method stub + + } + + @Override + public void init() + { + // TODO Auto-generated method stub + + } + + @Override + public void methodFrameReceived(int channelId, AMQMethodBody body) throws AMQException + { + // TODO Auto-generated method stub + + } + + @Override + public void setSender(Sender sender) + { + // TODO Auto-generated method stub + + } + + @Override + public void writeFrame(AMQDataBlock frame) + { + // TODO Auto-generated method stub + + } + + @Override + public byte getProtocolMajorVersion() + { + // TODO Auto-generated method stub + return 0; + } + + @Override + public byte getProtocolMinorVersion() + { + // TODO Auto-generated method stub + return 0; + } + + @Override + public ProtocolVersion getProtocolVersion() + { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/qpid/java/common/src/test/java/org/apache/qpid/transport/network/mina/MINANetworkDriverTest.java b/qpid/java/common/src/test/java/org/apache/qpid/transport/network/mina/MINANetworkDriverTest.java index 7901f6a99d..6024875cf5 100644 --- a/qpid/java/common/src/test/java/org/apache/qpid/transport/network/mina/MINANetworkDriverTest.java +++ b/qpid/java/common/src/test/java/org/apache/qpid/transport/network/mina/MINANetworkDriverTest.java @@ -299,7 +299,7 @@ public class MINANetworkDriverTest extends TestCase _countingEngine.setNewLatch(TEST_DATA.getBytes().length); _client.send(ByteBuffer.wrap(TEST_DATA.getBytes())); _countingEngine.getExceptionLatch().await(2, TimeUnit.SECONDS); - assertEquals("Exception should not been thrown", 0, + assertEquals("Exception should have been thrown", 0, _countingEngine.getExceptionLatch().getCount()); } @@ -321,11 +321,12 @@ public class MINANetworkDriverTest extends TestCase { EchoProtocolEngine _engine = null; - public ProtocolEngine newProtocolEngine() + public ProtocolEngine newProtocolEngine(NetworkDriver driver) { if (_engine == null) { _engine = new EchoProtocolEngine(); + _engine.setNetworkDriver(driver); } return getEngine(); } -- cgit v1.2.1 From 6e7380bc8c31f5bc1709fe77a14b829575f59e08 Mon Sep 17 00:00:00 2001 From: Aidan Skinner Date: Thu, 3 Sep 2009 14:09:09 +0000 Subject: QPID-2025: remove dead classes git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/java-network-refactor@810953 13f79535-47bb-0310-9956-ffa450edef68 --- .../server/protocol/AMQPFastProtocolHandler.java | 290 --------------------- .../qpid/server/protocol/AMQPProtocolProvider.java | 52 ---- 2 files changed, 342 deletions(-) delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQPFastProtocolHandler.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQPProtocolProvider.java (limited to 'qpid/java') diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQPFastProtocolHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQPFastProtocolHandler.java deleted file mode 100644 index 16b85e67b3..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQPFastProtocolHandler.java +++ /dev/null @@ -1,290 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.protocol; - -import java.io.IOException; -import java.net.InetSocketAddress; - -import org.apache.log4j.Logger; -import org.apache.mina.common.ByteBuffer; -import org.apache.mina.common.IdleStatus; -import org.apache.mina.common.IoFilterChain; -import org.apache.mina.common.IoHandlerAdapter; -import org.apache.mina.common.IoSession; -import org.apache.mina.filter.ReadThrottleFilterBuilder; -import org.apache.mina.filter.SSLFilter; -import org.apache.mina.filter.WriteBufferLimitFilterBuilder; -import org.apache.mina.filter.codec.QpidProtocolCodecFilter; -import org.apache.mina.filter.executor.ExecutorFilter; -import org.apache.mina.util.SessionUtil; -import org.apache.qpid.AMQException; -import org.apache.qpid.codec.AMQCodecFactory; -import org.apache.qpid.framing.AMQDataBlock; -import org.apache.qpid.framing.AMQProtocolHeaderException; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.ConnectionCloseBody; -import org.apache.qpid.framing.HeartbeatBody; -import org.apache.qpid.framing.MethodRegistry; -import org.apache.qpid.framing.ProtocolInitiation; -import org.apache.qpid.framing.ProtocolVersion; -import org.apache.qpid.server.configuration.ServerConfiguration; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.registry.IApplicationRegistry; -import org.apache.qpid.server.logging.actors.CurrentActor; -import org.apache.qpid.ssl.SSLContextFactory; - -/** - * The protocol handler handles "protocol events" for all connections. The state - * associated with an individual connection is accessed through the protocol session. - * - * We delegate all frame (message) processing to the AMQProtocolSession which wraps - * the state for the connection. - */ -public class AMQPFastProtocolHandler extends IoHandlerAdapter -{ - private static final Logger _logger = Logger.getLogger(AMQPFastProtocolHandler.class); - - private final IApplicationRegistry _applicationRegistry; - - private final int BUFFER_READ_LIMIT_SIZE; - private final int BUFFER_WRITE_LIMIT_SIZE; - - public AMQPFastProtocolHandler(Integer applicationRegistryInstance) - { - this(ApplicationRegistry.getInstance(applicationRegistryInstance)); - } - - public AMQPFastProtocolHandler(IApplicationRegistry applicationRegistry) - { - _applicationRegistry = applicationRegistry; - - // Read the configuration from the application registry - BUFFER_READ_LIMIT_SIZE = _applicationRegistry.getConfiguration().getBufferReadLimit(); - BUFFER_WRITE_LIMIT_SIZE = _applicationRegistry.getConfiguration().getBufferWriteLimit(); - - _logger.debug("AMQPFastProtocolHandler created"); - } - - protected AMQPFastProtocolHandler(AMQPFastProtocolHandler handler) - { - this(handler._applicationRegistry); - } - - public void sessionCreated(IoSession protocolSession) throws Exception - { - SessionUtil.initialize(protocolSession); - final AMQCodecFactory codecFactory = new AMQCodecFactory(true); - - createSession(protocolSession, _applicationRegistry, codecFactory); - _logger.info("Protocol session created for:" + protocolSession.getRemoteAddress()); - - final QpidProtocolCodecFilter pcf = new QpidProtocolCodecFilter(codecFactory); - final ServerConfiguration config = _applicationRegistry.getConfiguration(); - - String keystorePath = config.getKeystorePath(); - String keystorePassword = config.getKeystorePassword(); - String certType = config.getCertType(); - SSLContextFactory sslContextFactory = null; - boolean isSsl = false; - if (config.getEnableSSL() && isSSLClient(config, protocolSession)) - { - sslContextFactory = new SSLContextFactory(keystorePath, keystorePassword, certType); - isSsl = true; - } - if (config.getEnableExecutorPool()) - { - if (isSsl) - { - protocolSession.getFilterChain().addAfter("AsynchronousReadFilter", "sslFilter", - new SSLFilter(sslContextFactory.buildServerContext())); - } - protocolSession.getFilterChain().addBefore("AsynchronousWriteFilter", "protocolFilter", pcf); - } - else - { - protocolSession.getFilterChain().addLast("protocolFilter", pcf); - if (isSsl) - { - protocolSession.getFilterChain().addBefore("protocolFilter", "sslFilter", - new SSLFilter(sslContextFactory.buildServerContext())); - } - } - - if (ApplicationRegistry.getInstance().getConfiguration().getProtectIOEnabled()) - { - try - { -// //Add IO Protection Filters - IoFilterChain chain = protocolSession.getFilterChain(); - - - protocolSession.getFilterChain().addLast("tempExecutorFilterForFilterBuilder", new ExecutorFilter()); - - ReadThrottleFilterBuilder readfilter = new ReadThrottleFilterBuilder(); - readfilter.setMaximumConnectionBufferSize(BUFFER_READ_LIMIT_SIZE); - readfilter.attach(chain); - - WriteBufferLimitFilterBuilder writefilter = new WriteBufferLimitFilterBuilder(); - writefilter.setMaximumConnectionBufferSize(BUFFER_WRITE_LIMIT_SIZE); - writefilter.attach(chain); - - protocolSession.getFilterChain().remove("tempExecutorFilterForFilterBuilder"); - _logger.info("Using IO Read/Write Filter Protection"); - } - catch (Exception e) - { - _logger.error("Unable to attach IO Read/Write Filter Protection :" + e.getMessage()); - } - } - } - - /** Separated into its own, protected, method to allow easier reuse */ - protected void createSession(IoSession session, IApplicationRegistry applicationRegistry, AMQCodecFactory codec) throws AMQException - { - new AMQMinaProtocolSession(session, applicationRegistry.getVirtualHostRegistry(), codec); - } - - public void sessionOpened(IoSession protocolSession) throws Exception - { - _logger.info("Session opened for:" + protocolSession.getRemoteAddress()); - } - - public void sessionClosed(IoSession protocolSession) throws Exception - { - _logger.info("Protocol Session closed for:" + protocolSession.getRemoteAddress()); - final AMQProtocolSession amqProtocolSession = AMQMinaProtocolSession.getAMQProtocolSession(protocolSession); - //fixme -- this can be null - if (amqProtocolSession != null) - { - try - { - CurrentActor.set(amqProtocolSession.getLogActor()); - amqProtocolSession.closeSession(); - } - catch (AMQException e) - { - _logger.error("Caught AMQException whilst closingSession:" + e); - } - finally - { - CurrentActor.remove(); - } - } - } - - public void sessionIdle(IoSession session, IdleStatus status) throws Exception - { - _logger.debug("Protocol Session [" + this + "] idle: " + status + " :for:" + session.getRemoteAddress()); - if (IdleStatus.WRITER_IDLE.equals(status)) - { - //write heartbeat frame: - session.write(HeartbeatBody.FRAME); - } - else if (IdleStatus.READER_IDLE.equals(status)) - { - //failover: - throw new IOException("Timed out while waiting for heartbeat from peer."); - } - - } - - public void exceptionCaught(IoSession protocolSession, Throwable throwable) throws Exception - { - AMQProtocolSession session = AMQMinaProtocolSession.getAMQProtocolSession(protocolSession); - if (throwable instanceof AMQProtocolHeaderException) - { - - protocolSession.write(new ProtocolInitiation(ProtocolVersion.getLatestSupportedVersion())); - - protocolSession.close(); - - _logger.error("Error in protocol initiation " + session + ":" + protocolSession.getRemoteAddress() + " :" + throwable.getMessage(), throwable); - } - else if (throwable instanceof IOException) - { - _logger.error("IOException caught in" + session + ", session closed implictly: " + throwable); - } - else - { - _logger.error("Exception caught in" + session + ", closing session explictly: " + throwable, throwable); - - - MethodRegistry methodRegistry = MethodRegistry.getMethodRegistry(session.getProtocolVersion()); - ConnectionCloseBody closeBody = methodRegistry.createConnectionCloseBody(200,new AMQShortString(throwable.getMessage()),0,0); - - protocolSession.write(closeBody.generateFrame(0)); - - protocolSession.close(); - } - } - - /** - * Invoked when a message is received on a particular protocol session. Note that a - * protocol session is directly tied to a particular physical connection. - * - * @param protocolSession the protocol session that received the message - * @param message the message itself (i.e. a decoded frame) - * - * @throws Exception if the message cannot be processed - */ - public void messageReceived(IoSession protocolSession, Object message) throws Exception - { - final AMQProtocolSession amqProtocolSession = AMQMinaProtocolSession.getAMQProtocolSession(protocolSession); - - if (message instanceof AMQDataBlock) - { - amqProtocolSession.dataBlockReceived((AMQDataBlock) message); - - } - else if (message instanceof ByteBuffer) - { - throw new IllegalStateException("Handed undecoded ByteBuffer buf = " + message); - } - else - { - throw new IllegalStateException("Handed unhandled message. message.class = " + message.getClass() + " message = " + message); - } - } - - /** - * Called after a message has been sent out on a particular protocol session - * - * @param protocolSession the protocol session (i.e. connection) on which this - * message was sent - * @param object the message (frame) that was encoded and sent - * - * @throws Exception if we want to indicate an error - */ - public void messageSent(IoSession protocolSession, Object object) throws Exception - { - if (_logger.isDebugEnabled()) - { - _logger.debug("Message sent: " + object); - } - } - - protected boolean isSSLClient(ServerConfiguration connectionConfig, - IoSession protocolSession) - { - InetSocketAddress addr = (InetSocketAddress) protocolSession.getLocalAddress(); - return addr.getPort() == connectionConfig.getSSLPort(); - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQPProtocolProvider.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQPProtocolProvider.java deleted file mode 100644 index 07c153bfe8..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQPProtocolProvider.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.protocol; - -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.registry.IApplicationRegistry; - -/** - * The protocol provide's role is to encapsulate the initialisation of the protocol handler. - * - * The protocol handler (see AMQPFastProtocolHandler class) handles protocol events - * such as connection closing or a frame being received. It can either do this directly - * or pass off to the protocol session in the cases where state information is required to - * deal with the event. - * - */ -public class AMQPProtocolProvider -{ - /** - * Handler for protocol events - */ - private AMQPFastProtocolHandler _handler; - - public AMQPProtocolProvider() - { - IApplicationRegistry registry = ApplicationRegistry.getInstance(); - _handler = new AMQPFastProtocolHandler(registry); - } - - public AMQPFastProtocolHandler getHandler() - { - return _handler; - } -} -- cgit v1.2.1 From 7b28732091473d93ce7546c70fa1d2dbd685161a Mon Sep 17 00:00:00 2001 From: Aidan Skinner Date: Fri, 4 Sep 2009 09:40:32 +0000 Subject: QPID-2025: Log errors instead of printStackTracing() git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/java-network-refactor@811326 13f79535-47bb-0310-9956-ffa450edef68 --- .../java/org/apache/qpid/server/protocol/AMQProtocolEngine.java | 4 ++-- .../org/apache/qpid/transport/network/mina/MINANetworkDriver.java | 8 +++++++- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'qpid/java') diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java index 49bdffb584..19d98161c6 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java @@ -227,7 +227,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol } catch (Exception e) { - e.printStackTrace(); + _logger.error("Unexpected exception when processing datablock", e); closeProtocolSession(); } } @@ -236,7 +236,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol } catch (Exception e) { - e.printStackTrace(); + _logger.error("Unexpected exception when processing datablock", e); closeProtocolSession(); } } diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java index 477e2cd5af..8df3644929 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java @@ -30,13 +30,13 @@ import java.nio.ByteBuffer; import javax.net.ssl.SSLEngine; +import org.apache.log4j.Logger; import org.apache.mina.common.ConnectFuture; import org.apache.mina.common.IdleStatus; import org.apache.mina.common.IoAcceptor; import org.apache.mina.common.IoFilterChain; import org.apache.mina.common.IoHandlerAdapter; import org.apache.mina.common.IoSession; -import org.apache.mina.common.IoSessionConfig; import org.apache.mina.common.SimpleByteBufferAllocator; import org.apache.mina.common.WriteFuture; import org.apache.mina.filter.ReadThrottleFilterBuilder; @@ -80,6 +80,8 @@ public class MINANetworkDriver extends IoHandlerAdapter implements NetworkDriver private WriteFuture _lastWriteFuture; + private static final Logger _logger = Logger.getLogger(MINANetworkDriver.class); + public MINANetworkDriver(boolean useNIO, int processors, boolean executorPool, boolean protectIO) { _useNIO = useNIO; @@ -289,6 +291,10 @@ public class MINANetworkDriver extends IoHandlerAdapter implements NetworkDriver if (_protocolEngine != null) { _protocolEngine.exception(throwable); + } + else + { + _logger.error("Exception thrown and no ProtocolEngine to handle it", throwable); } _lastException = throwable; } -- cgit v1.2.1 From c1ebe66bfab328c5192a35c21ea290b5c45f40f5 Mon Sep 17 00:00:00 2001 From: Aidan Skinner Date: Wed, 9 Sep 2009 13:05:43 +0000 Subject: Merge from trunk git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/java-network-refactor@812936 13f79535-47bb-0310-9956-ffa450edef68 --- qpid/java/broker/bin/qpid-server | 9 +- qpid/java/broker/etc/log4j.xml | 2 +- .../qpid/server/exchange/HeadersExchange.java | 14 +- .../server/logging/StartupRootMessageLogger.java | 7 + .../management/JMXManagedObjectRegistry.java | 2 + .../security/access/plugins/BasicACLPlugin.java | 6 - .../access/plugins/network/FirewallFactory.java | 45 ------- .../qpid/server/subscription/SubscriptionImpl.java | 3 +- .../server/security/access/ExchangeDenier.java | 13 -- .../qpid/client/AMQAuthenticationException.java | 5 - .../java/org/apache/qpid/client/AMQSession.java | 51 +++++--- .../org/apache/qpid/client/AMQSession_0_8.java | 24 +++- .../client/handler/ChannelCloseMethodHandler.java | 91 +++++++------ .../handler/ConnectionOpenOkMethodHandler.java | 1 - .../handler/ConnectionTuneMethodHandler.java | 1 - .../protocol/AMQIoTransportProtocolSession.java | 2 +- .../qpid/client/protocol/AMQProtocolHandler.java | 54 ++++---- .../qpid/client/protocol/AMQProtocolSession.java | 4 +- .../apache/qpid/client/state/AMQStateManager.java | 19 ++- .../client/util/FlowControllingBlockingQueue.java | 18 ++- .../org/apache/qpid/client/MockAMQConnection.java | 2 +- .../client/protocol/AMQProtocolHandlerTest.java | 11 +- .../transport/network/mina/MINANetworkDriver.java | 6 +- .../doc/broker-priority-queue-subscription.dia | Bin 0 -> 2991 bytes qpid/java/doc/broker-queue-subscription.dia | Bin 0 -> 2129 bytes .../qpid/management/ui/jmx/ClientListener.java | 7 +- .../qpid/management/ui/jmx/JMXServerRegistry.java | 41 +++++- .../management/ui/views/AttributesTabControl.java | 2 +- .../qpid/management/ui/views/NavigationView.java | 4 +- .../connection/ConnectionOperationsTabControl.java | 60 +++++++++ .../exchange/ExchangeOperationsTabControl.java | 4 + .../HeadersExchangeOperationsTabControl.java | 144 +++++++++++++++++---- .../views/logging/ConfigurationFileTabControl.java | 4 +- .../ui/views/queue/QueueOperationsTabControl.java | 22 +++- .../management/ui/views/vhost/VHostTabControl.java | 4 + .../src/main/resources/win32-win32-x86/qpidmc.ini | 22 ++-- .../management/jmx/ManagementActorLoggingTest.java | 28 +++- .../server/logging/SubscriptionLoggingTest.java | 65 ++++++---- .../client/DynamicQueueExchangeCreateTest.java | 88 +++++++++++++ .../close/JavaServerCloseRaceConditionTest.java | 119 +++++++++++++++++ .../test/unit/topic/DurableSubscriptionTest.java | 59 +++++---- .../test/unit/transacted/CommitRollbackTest.java | 2 +- .../apache/qpid/test/utils/FailoverBaseCase.java | 4 +- .../main/java/org/apache/qpid/util/LogMonitor.java | 20 ++- .../java/org/apache/qpid/util/LogMonitorTest.java | 73 ++++------- qpid/java/test-profiles/010Excludes | 7 + 46 files changed, 816 insertions(+), 353 deletions(-) delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/network/FirewallFactory.java create mode 100644 qpid/java/doc/broker-priority-queue-subscription.dia create mode 100644 qpid/java/doc/broker-queue-subscription.dia create mode 100644 qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/DynamicQueueExchangeCreateTest.java create mode 100644 qpid/java/systests/src/main/java/org/apache/qpid/test/unit/close/JavaServerCloseRaceConditionTest.java (limited to 'qpid/java') diff --git a/qpid/java/broker/bin/qpid-server b/qpid/java/broker/bin/qpid-server index e5a9e998e2..738fc6e084 100755 --- a/qpid/java/broker/bin/qpid-server +++ b/qpid/java/broker/bin/qpid-server @@ -26,14 +26,19 @@ fi # Set classpath to include Qpid jar with all required jars in manifest QPID_LIBS=$QPID_HOME/lib/qpid-all.jar:$QPID_HOME/lib/bdbstore-launch.jar +# Default Log4j to append to its log file +if [ -z "$QPID_LOG_APPEND" ]; then + export QPID_LOG_APPEND="true" +fi + # Set other variables used by the qpid-run script before calling export JAVA=java \ JAVA_VM=-server \ JAVA_MEM=-Xmx1024m \ JAVA_GC="-XX:+UseConcMarkSweepGC -XX:+HeapDumpOnOutOfMemoryError" \ QPID_CLASSPATH=$QPID_LIBS \ - QPID_RUN_LOG=2 + QPID_RUN_LOG=2 -QPID_OPTS="$QPID_OPTS -Damqj.read_write_pool_size=32" +QPID_OPTS="$QPID_OPTS -Damqj.read_write_pool_size=32 -DQPID_LOG_APPEND=$QPID_LOG_APPEND" . qpid-run org.apache.qpid.server.Main "$@" diff --git a/qpid/java/broker/etc/log4j.xml b/qpid/java/broker/etc/log4j.xml index a395d0fd56..8ca43ededd 100644 --- a/qpid/java/broker/etc/log4j.xml +++ b/qpid/java/broker/etc/log4j.xml @@ -50,7 +50,7 @@ - + diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java index fc667db17b..c5f5cd05e1 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java @@ -204,11 +204,21 @@ public class HeadersExchange extends AbstractExchange for (int i = 0; i < bindings.length; i++) { String[] keyAndValue = bindings[i].split("="); - if (keyAndValue == null || keyAndValue.length < 2) + if (keyAndValue == null || keyAndValue.length == 0 || keyAndValue.length > 2) { throw new JMException("Format for headers binding should be \"=,=\" "); } - bindingMap.setString(keyAndValue[0], keyAndValue[1]); + + if(keyAndValue.length ==1) + { + //no value was given, only a key. Use an empty value + //to signal match on key presence alone + bindingMap.setString(keyAndValue[0], ""); + } + else + { + bindingMap.setString(keyAndValue[0], keyAndValue[1]); + } } _bindings.add(new Registration(new HeadersBinding(bindingMap), queue)); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/StartupRootMessageLogger.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/StartupRootMessageLogger.java index 0dffde50fa..bfb122985b 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/StartupRootMessageLogger.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/StartupRootMessageLogger.java @@ -39,4 +39,11 @@ public class StartupRootMessageLogger extends RootMessageLoggerImpl return true; } + @Override + public boolean isMessageEnabled(LogActor actor) + { + return true; + } + + } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java index 42b3b05ac5..aea9ab43ea 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java @@ -379,6 +379,8 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry try { _cs.stop(); + CurrentActor.get().message(ManagementConsoleMessages.MNG_1003("RMI Registry", _cs.getAddress().getPort() - PORT_EXPORT_OFFSET)); + CurrentActor.get().message(ManagementConsoleMessages.MNG_1003("RMI ConnectorServer", _cs.getAddress().getPort())); } catch (IOException e) { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/BasicACLPlugin.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/BasicACLPlugin.java index f7e537b02b..a6fae053c2 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/BasicACLPlugin.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/BasicACLPlugin.java @@ -120,10 +120,4 @@ public abstract class BasicACLPlugin implements ACLPlugin // no-op } - public boolean supportsTag(String name) - { - // This plugin doesn't support any tags - return false; - } - } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/network/FirewallFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/network/FirewallFactory.java deleted file mode 100644 index a1a399e5bf..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/network/FirewallFactory.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.security.access.plugins.network; - -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.qpid.server.security.access.ACLPlugin; -import org.apache.qpid.server.security.access.ACLPluginFactory; - -public class FirewallFactory implements ACLPluginFactory -{ - - @Override - public ACLPlugin newInstance(Configuration config) throws ConfigurationException - { - FirewallPlugin plugin = new FirewallPlugin(); - plugin.setConfiguration(config); - return plugin; - } - - @Override - public boolean supportsTag(String name) - { - return name.equals("firewall"); - } - -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java index b34ef1c382..72d6afc65c 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java @@ -599,7 +599,6 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage if(_state.compareAndSet(State.SUSPENDED, State.ACTIVE)) { _stateListener.stateChange(this, State.SUSPENDED, State.ACTIVE); - CurrentActor.get().message(_logSubject,SubscriptionMessages.SUB_1003(_state.get().toString())); } else { @@ -612,9 +611,9 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage if(_state.compareAndSet(State.ACTIVE, State.SUSPENDED)) { _stateListener.stateChange(this, State.ACTIVE, State.SUSPENDED); - CurrentActor.get().message(_logSubject,SubscriptionMessages.SUB_1003(_state.get().toString())); } } + CurrentActor.get().message(_logSubject,SubscriptionMessages.SUB_1003(_state.get().toString())); } public State getState() diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/ExchangeDenier.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/ExchangeDenier.java index f62b0c6241..317dee2b47 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/ExchangeDenier.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/ExchangeDenier.java @@ -46,17 +46,4 @@ public class ExchangeDenier extends AllowAll { return AuthzResult.DENIED; } - - @Override - public String getPluginName() - { - return getClass().getSimpleName(); - } - - @Override - public boolean supportsTag(String name) - { - return name.equals("exchangeDenier"); - } - } diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQAuthenticationException.java b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQAuthenticationException.java index 05ac3dca9e..6bae0166d1 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQAuthenticationException.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQAuthenticationException.java @@ -39,9 +39,4 @@ public class AMQAuthenticationException extends AMQException { super(error, msg, cause); } - public boolean isHardError() - { - return true; - } - } diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession.java b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession.java index 118be75705..2e3e417c95 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession.java @@ -65,6 +65,7 @@ import org.apache.qpid.AMQDisconnectedException; import org.apache.qpid.AMQException; import org.apache.qpid.AMQInvalidArgumentException; import org.apache.qpid.AMQInvalidRoutingKeyException; +import org.apache.qpid.AMQChannelClosedException; import org.apache.qpid.client.failover.FailoverException; import org.apache.qpid.client.failover.FailoverNoopSupport; import org.apache.qpid.client.failover.FailoverProtectedOperation; @@ -205,9 +206,9 @@ public abstract class AMQSession @@ -86,7 +87,7 @@ public class AMQStateManager implements AMQMethodListener return _currentState; } - public void changeState(AMQState newState) throws AMQException + public void changeState(AMQState newState) { _logger.debug("State changing to " + newState + " from old state " + _currentState); @@ -136,6 +137,22 @@ public class AMQStateManager implements AMQMethodListener */ public void error(Exception error) { + if (error instanceof AMQException) + { + // AMQException should be being notified before closing the + // ProtocolSession. Which will change the State to CLOSED. + // if we have a hard error. + if (((AMQException)error).isHardError()) + { + changeState(AMQState.CONNECTION_CLOSING); + } + } + else + { + // Be on the safe side here and mark the connection closed + changeState(AMQState.CONNECTION_CLOSED); + } + if (_waiters.size() == 0) { _logger.error("No Waiters for error saving as last error:" + error.getMessage()); diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/util/FlowControllingBlockingQueue.java b/qpid/java/client/src/main/java/org/apache/qpid/client/util/FlowControllingBlockingQueue.java index bddbc329ab..ee7fc533a3 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/util/FlowControllingBlockingQueue.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/util/FlowControllingBlockingQueue.java @@ -22,10 +22,11 @@ package org.apache.qpid.client.util; import java.util.Iterator; import java.util.Queue; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ConcurrentLinkedQueue; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * A blocking queue that emits events above a user specified threshold allowing the caller to take action (e.g. flow * control) to try to prevent the queue growing (much) further. The underlying queue itself is not bounded therefore the @@ -36,6 +37,8 @@ import java.util.concurrent.ConcurrentLinkedQueue; */ public class FlowControllingBlockingQueue { + private static final Logger _logger = LoggerFactory.getLogger(FlowControllingBlockingQueue.class); + /** This queue is bounded and is used to store messages before being dispatched to the consumer */ private final Queue _queue = new ConcurrentLinkedQueue(); @@ -46,6 +49,8 @@ public class FlowControllingBlockingQueue /** We require a separate count so we can track whether we have reached the threshold */ private int _count; + + private boolean disableFlowControl; public boolean isEmpty() { @@ -69,6 +74,10 @@ public class FlowControllingBlockingQueue _flowControlHighThreshold = highThreshold; _flowControlLowThreshold = lowThreshold; _listener = listener; + if (highThreshold == 0) + { + disableFlowControl = true; + } } public Object take() throws InterruptedException @@ -84,7 +93,7 @@ public class FlowControllingBlockingQueue } } } - if (_listener != null) + if (!disableFlowControl && _listener != null) { synchronized (_listener) { @@ -93,6 +102,7 @@ public class FlowControllingBlockingQueue _listener.underThreshold(_count); } } + } return o; @@ -106,7 +116,7 @@ public class FlowControllingBlockingQueue notifyAll(); } - if (_listener != null) + if (!disableFlowControl && _listener != null) { synchronized (_listener) { diff --git a/qpid/java/client/src/test/java/org/apache/qpid/client/MockAMQConnection.java b/qpid/java/client/src/test/java/org/apache/qpid/client/MockAMQConnection.java index ce79080e97..da44822ec3 100644 --- a/qpid/java/client/src/test/java/org/apache/qpid/client/MockAMQConnection.java +++ b/qpid/java/client/src/test/java/org/apache/qpid/client/MockAMQConnection.java @@ -85,7 +85,7 @@ public class MockAMQConnection extends AMQConnection } @Override - public ProtocolVersion makeBrokerConnection(BrokerDetails brokerDetail) throws IOException, AMQException + public ProtocolVersion makeBrokerConnection(BrokerDetails brokerDetail) throws IOException { _connected = true; _protocolHandler.getStateManager().changeState(AMQState.CONNECTION_OPEN); diff --git a/qpid/java/client/src/test/java/org/apache/qpid/client/protocol/AMQProtocolHandlerTest.java b/qpid/java/client/src/test/java/org/apache/qpid/client/protocol/AMQProtocolHandlerTest.java index 10ec220d9e..fc7f8148f0 100644 --- a/qpid/java/client/src/test/java/org/apache/qpid/client/protocol/AMQProtocolHandlerTest.java +++ b/qpid/java/client/src/test/java/org/apache/qpid/client/protocol/AMQProtocolHandlerTest.java @@ -200,15 +200,8 @@ public class AMQProtocolHandlerTest extends TestCase _handler.getStateManager().error(trigger); _logger.info("Setting state to be CONNECTION_CLOSED."); - try - { - _handler.getStateManager().changeState(AMQState.CONNECTION_CLOSED); - } - catch (AMQException e) - { - _logger.error("Unable to change the state to closed.", e); - fail("Unable to change the state to closed due to :"+e.getMessage()); - } + + _handler.getStateManager().changeState(AMQState.CONNECTION_CLOSED); _logger.info("Firing exception"); _handler.propagateExceptionToFrameListeners(trigger); diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java index 8df3644929..e34103a944 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java @@ -30,7 +30,6 @@ import java.nio.ByteBuffer; import javax.net.ssl.SSLEngine; -import org.apache.log4j.Logger; import org.apache.mina.common.ConnectFuture; import org.apache.mina.common.IdleStatus; import org.apache.mina.common.IoAcceptor; @@ -59,6 +58,9 @@ import org.apache.qpid.transport.NetworkDriver; import org.apache.qpid.transport.NetworkDriverConfiguration; import org.apache.qpid.transport.OpenException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + public class MINANetworkDriver extends IoHandlerAdapter implements NetworkDriver { @@ -80,7 +82,7 @@ public class MINANetworkDriver extends IoHandlerAdapter implements NetworkDriver private WriteFuture _lastWriteFuture; - private static final Logger _logger = Logger.getLogger(MINANetworkDriver.class); + private static final Logger _logger = LoggerFactory.getLogger(MINANetworkDriver.class); public MINANetworkDriver(boolean useNIO, int processors, boolean executorPool, boolean protectIO) { diff --git a/qpid/java/doc/broker-priority-queue-subscription.dia b/qpid/java/doc/broker-priority-queue-subscription.dia new file mode 100644 index 0000000000..2289899435 Binary files /dev/null and b/qpid/java/doc/broker-priority-queue-subscription.dia differ diff --git a/qpid/java/doc/broker-queue-subscription.dia b/qpid/java/doc/broker-queue-subscription.dia new file mode 100644 index 0000000000..d146ad136d Binary files /dev/null and b/qpid/java/doc/broker-queue-subscription.dia differ diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/ClientListener.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/ClientListener.java index c3348b32f0..d88e0f38bb 100644 --- a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/ClientListener.java +++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/ClientListener.java @@ -59,7 +59,12 @@ public class ClientListener implements NotificationListener else if (JMXConnectionNotification.FAILED.equals(type)) { ApplicationRegistry.serverConnectionClosed(server); - MBeanUtility.printOutput("Recieved notification from " + server.getName() + ": " + type ); + MBeanUtility.printOutput("JMX Connection to " + server.getName() + " failed."); + } + else if (JMXConnectionNotification.CLOSED.equals(type)) + { + ApplicationRegistry.serverConnectionClosed(server); + MBeanUtility.printOutput("JMX Connection to " + server.getName() + " was closed."); } } diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/JMXServerRegistry.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/JMXServerRegistry.java index 2b459c858f..ca07e6acf4 100644 --- a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/JMXServerRegistry.java +++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/JMXServerRegistry.java @@ -22,6 +22,7 @@ package org.apache.qpid.management.ui.jmx; import static org.apache.qpid.management.ui.Constants.ALL; +import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.Date; @@ -29,7 +30,6 @@ import java.util.HashMap; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; -import javax.management.ListenerNotFoundException; import javax.management.MBeanInfo; import javax.management.MBeanServerConnection; import javax.management.Notification; @@ -116,25 +116,54 @@ public class JMXServerRegistry extends ServerRegistry * removes all listeners from the mbean server. This is required when user * disconnects the Qpid server connection */ - public void closeServerConnection() throws Exception + public void closeServerConnection() throws IOException { try { + //remove the listener from the JMXConnector if (_jmxc != null && _clientListener != null) + { _jmxc.removeConnectionNotificationListener(_clientListener); + } + } + catch (Exception e) + { + //ignore + } + try + { + //remove the listener from the MBeanServerDelegate MBean if (_mbsc != null && _clientListener != null) + { _mbsc.removeNotificationListener(_serverObjectName, _clientListener); + } + } + catch (Exception e) + { + //ignore + } - // remove mbean notification listeners + if (_mbsc != null && _clientListener != null) + { + //remove any listeners from the Qpid MBeans for (String mbeanName : _subscribedNotificationMap.keySet()) { - _mbsc.removeNotificationListener(new ObjectName(mbeanName), _notificationListener); + try + { + _mbsc.removeNotificationListener(new ObjectName(mbeanName), _notificationListener); + } + catch (Exception e) + { + //ignore + } } } - catch (ListenerNotFoundException ex) + + //close the JMXConnector + if (_jmxc != null) { - MBeanUtility.printOutput(ex.toString()); + _jmxc.close(); } } diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/AttributesTabControl.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/AttributesTabControl.java index 2408faae3a..f21647b2d2 100644 --- a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/AttributesTabControl.java +++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/AttributesTabControl.java @@ -882,7 +882,7 @@ public class AttributesTabControl extends TabControl { attribute = (AttributeData) element; if (attribute.isWritable()) - return Display.getCurrent().getSystemColor(SWT.COLOR_DARK_BLUE); + return Display.getCurrent().getSystemColor(SWT.COLOR_BLUE); else return Display.getCurrent().getSystemColor(SWT.COLOR_BLACK); } diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NavigationView.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NavigationView.java index 0d290ab1c4..056d365f8e 100644 --- a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NavigationView.java +++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NavigationView.java @@ -790,9 +790,11 @@ public class NavigationView extends ViewPart return; } - serverRegistry.closeServerConnection(); // Add server to the closed server list and the worker thread will remove the server from required places. ApplicationRegistry.serverConnectionClosed(managedServer); + + //close the connection + serverRegistry.closeServerConnection(); } /** diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/connection/ConnectionOperationsTabControl.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/connection/ConnectionOperationsTabControl.java index e981ec1c3c..f82d37dcd1 100644 --- a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/connection/ConnectionOperationsTabControl.java +++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/connection/ConnectionOperationsTabControl.java @@ -28,10 +28,13 @@ import javax.management.openmbean.CompositeData; import javax.management.openmbean.CompositeDataSupport; import javax.management.openmbean.TabularDataSupport; +import org.apache.qpid.management.ui.ApplicationRegistry; import org.apache.qpid.management.ui.ManagedBean; +import org.apache.qpid.management.ui.ServerRegistry; import org.apache.qpid.management.common.mbeans.ManagedConnection; import org.apache.qpid.management.ui.jmx.JMXManagedObject; import org.apache.qpid.management.ui.jmx.MBeanUtility; +import org.apache.qpid.management.ui.views.MBeanView; import org.apache.qpid.management.ui.views.TabControl; import org.apache.qpid.management.ui.views.ViewUtility; import org.eclipse.jface.viewers.ISelectionChangedListener; @@ -43,6 +46,8 @@ import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerSorter; import org.eclipse.swt.SWT; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Image; @@ -55,6 +60,8 @@ import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.TabFolder; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; import org.eclipse.ui.forms.widgets.Form; import org.eclipse.ui.forms.widgets.FormToolkit; @@ -199,6 +206,8 @@ public class ConnectionOperationsTabControl extends TabControl _tableViewer.setContentProvider(new ContentProviderImpl()); _tableViewer.setLabelProvider(new LabelProviderImpl()); _tableViewer.setSorter(tableSorter); + _table.setSortColumn(_table.getColumn(0)); + _table.setSortDirection(SWT.UP); Composite buttonsComposite = _toolkit.createComposite(viewChannelsGroup); gridData = new GridData(SWT.RIGHT, SWT.BOTTOM, false, false); @@ -278,6 +287,19 @@ public class ConnectionOperationsTabControl extends TabControl } }); + //listener for double clicking to open the selection mbean + _table.addMouseListener(new MouseListener() + { + // MouseListener implementation + public void mouseDoubleClick(MouseEvent event) + { + openMBean(_table); + } + + public void mouseDown(MouseEvent e){} + public void mouseUp(MouseEvent e){} + }); + _tableViewer.addSelectionChangedListener(new ISelectionChangedListener(){ public void selectionChanged(SelectionChangedEvent evt) { @@ -465,5 +487,43 @@ public class ConnectionOperationsTabControl extends TabControl return comparison; } } + + private void openMBean(Table table) + { + int selectionIndex = table.getSelectionIndex(); + + if (selectionIndex == -1) + { + return; + } + + CompositeData channelResult = (CompositeData) table.getItem(selectionIndex).getData(); + String queueName = (String) channelResult.get(DEFAULT_QUEUE); + + if(queueName == null) + { + return; + } + + ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(_mbean); + ManagedBean selectedMBean = serverRegistry.getQueue(queueName, _mbean.getVirtualHostName()); + + if(selectedMBean == null) + { + ViewUtility.popupErrorMessage("Error", "Unable to retrieve the selected MBean to open it"); + return; + } + + IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + MBeanView view = (MBeanView) window.getActivePage().findView(MBeanView.ID); + try + { + view.openMBean(selectedMBean); + } + catch (Exception ex) + { + MBeanUtility.handleException(selectedMBean, ex); + } + } } diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/exchange/ExchangeOperationsTabControl.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/exchange/ExchangeOperationsTabControl.java index 35b3e8150c..e3dea6e96b 100644 --- a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/exchange/ExchangeOperationsTabControl.java +++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/exchange/ExchangeOperationsTabControl.java @@ -237,6 +237,8 @@ public class ExchangeOperationsTabControl extends TabControl _keysTableViewer.setContentProvider(new ContentProviderImpl(BINDING_KEY)); _keysTableViewer.setLabelProvider(new LabelProviderImpl(BINDING_KEY)); _keysTableViewer.setSorter(tableSorter); + _keysTable.setSortColumn(_keysTable.getColumn(0)); + _keysTable.setSortDirection(SWT.UP); _queuesTable = new Table (tablesComposite, SWT.SINGLE | SWT.SCROLL_LINE | SWT.BORDER | SWT.FULL_SELECTION); @@ -287,6 +289,8 @@ public class ExchangeOperationsTabControl extends TabControl _queuesTableViewer.setContentProvider(new ContentProviderImpl(QUEUES)); _queuesTableViewer.setLabelProvider(new LabelProviderImpl(QUEUES)); _queuesTableViewer.setSorter(queuesTableSorter); + _queuesTable.setSortColumn(_queuesTable.getColumn(0)); + _queuesTable.setSortDirection(SWT.UP); _queuesTableViewer.setInput(new String[]{"Select a binding key to view queues"}); //listener for double clicking to open the selection mbean diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/exchange/HeadersExchangeOperationsTabControl.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/exchange/HeadersExchangeOperationsTabControl.java index 5146bab74c..fcce0e67b6 100644 --- a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/exchange/HeadersExchangeOperationsTabControl.java +++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/exchange/HeadersExchangeOperationsTabControl.java @@ -22,6 +22,7 @@ package org.apache.qpid.management.ui.views.exchange; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.List; import javax.management.MBeanServerConnection; @@ -48,6 +49,7 @@ import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerSorter; import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.ScrolledComposite; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseListener; import org.eclipse.swt.events.SelectionAdapter; @@ -60,6 +62,7 @@ import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.TabFolder; import org.eclipse.swt.widgets.Table; @@ -182,7 +185,7 @@ public class HeadersExchangeOperationsTabControl extends TabControl final TableSorter tableSorter = new TableSorter(BINDING_NUM); String[] titles = {"Binding Number", "Queue Name"}; - int[] bounds = {125, 175}; + int[] bounds = {135, 175}; for (int i = 0; i < titles.length; i++) { final int index = i; @@ -220,6 +223,8 @@ public class HeadersExchangeOperationsTabControl extends TabControl _bindingNumberTableViewer.setContentProvider(new ContentProviderImpl(BINDING_NUM)); _bindingNumberTableViewer.setLabelProvider(new LabelProviderImpl(BINDING_NUM)); _bindingNumberTableViewer.setSorter(tableSorter); + _bindingNumberTable.setSortColumn(_bindingNumberTable.getColumn(0)); + _bindingNumberTable.setSortDirection(SWT.UP); //table of header bindings _headersTable = new Table (tablesComposite, SWT.SINGLE | SWT.SCROLL_LINE | SWT.BORDER | SWT.FULL_SELECTION); @@ -272,6 +277,8 @@ public class HeadersExchangeOperationsTabControl extends TabControl _headersTableViewer.setContentProvider(new ContentProviderImpl(HEADER_BINDINGS)); _headersTableViewer.setLabelProvider(new LabelProviderImpl(HEADER_BINDINGS)); _headersTableViewer.setSorter(queuesTableSorter); + _headersTable.setSortColumn(_headersTable.getColumn(0)); + _headersTable.setSortDirection(SWT.UP); _headersTableViewer.setInput(new String[]{"Select a binding to view key-value pairs"}); _bindingNumberTableViewer.addSelectionChangedListener(new ISelectionChangedListener(){ @@ -490,25 +497,38 @@ public class HeadersExchangeOperationsTabControl extends TabControl private void createNewBinding(Shell parent) { final Shell shell = ViewUtility.createModalDialogShell(parent, "Create New Binding"); - - Composite destinationComposite = _toolkit.createComposite(shell, SWT.NONE); - destinationComposite.setBackground(shell.getBackground()); - destinationComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); - destinationComposite.setLayout(new GridLayout(2,false)); + + Composite queueNameComposite = _toolkit.createComposite(shell, SWT.NONE); + queueNameComposite.setBackground(shell.getBackground()); + GridData layoutData = new GridData(SWT.CENTER, SWT.TOP, true, false); + layoutData.minimumWidth = 300; + queueNameComposite.setLayoutData(layoutData); + queueNameComposite.setLayout(new GridLayout(2,false)); - _toolkit.createLabel(destinationComposite,"Queue:").setBackground(shell.getBackground()); - final Combo destinationCombo = new Combo(destinationComposite,SWT.NONE | SWT.READ_ONLY); + _toolkit.createLabel(queueNameComposite,"Queue:").setBackground(shell.getBackground()); + final Combo destinationCombo = new Combo(queueNameComposite,SWT.NONE | SWT.READ_ONLY); destinationCombo.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); - Composite bindingComposite = _toolkit.createComposite(shell, SWT.NONE); - bindingComposite.setBackground(shell.getBackground()); - bindingComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); - bindingComposite.setLayout(new GridLayout(2,false)); + final ScrolledComposite scrolledComposite = new ScrolledComposite(shell, SWT.V_SCROLL); + scrolledComposite.setExpandHorizontal(true); + scrolledComposite.setLayout(new GridLayout()); + scrolledComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); + scrolledComposite.setBackground(shell.getBackground()); + + final Composite bindingComposite = _toolkit.createComposite(scrolledComposite, SWT.NONE); + bindingComposite.setBackground(scrolledComposite.getBackground()); + bindingComposite.setLayout(new GridLayout(2,true)); + layoutData = new GridData(SWT.FILL, SWT.TOP, true, false); + bindingComposite.setLayoutData(layoutData); + scrolledComposite.setContent(bindingComposite); + + Composite addMoreButtonComp = _toolkit.createComposite(shell); + addMoreButtonComp.setBackground(shell.getBackground()); + addMoreButtonComp.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, true, true)); + addMoreButtonComp.setLayout(new GridLayout()); + + final Button addMoreButton = _toolkit.createButton(addMoreButtonComp, "Add additional field", SWT.PUSH); - _toolkit.createLabel(bindingComposite,"Binding:").setBackground(shell.getBackground()); - final Text bindingText = new Text(bindingComposite, SWT.BORDER); - bindingText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); - Composite okCancelButtonsComp = _toolkit.createComposite(shell); okCancelButtonsComp.setBackground(shell.getBackground()); okCancelButtonsComp.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, true, true)); @@ -532,26 +552,106 @@ public class HeadersExchangeOperationsTabControl extends TabControl destinationCombo.setItems(queueList.toArray(new String[0])); } destinationCombo.select(0); + + final HashMap headerBindingHashMap = new HashMap(); + + //add headings + Label keyLabel = _toolkit.createLabel(bindingComposite,"Key:"); + keyLabel.setBackground(bindingComposite.getBackground()); + keyLabel.setLayoutData(new GridData(SWT.CENTER, SWT.TOP, true, false)); + + Label valueLabel = _toolkit.createLabel(bindingComposite,"Value:"); + valueLabel.setBackground(bindingComposite.getBackground()); + valueLabel.setLayoutData(new GridData(SWT.CENTER, SWT.TOP, true, false)); + + //add the x-match key by default and offer a comobo to select its value + final Text xmatchKeyText = new Text(bindingComposite, SWT.BORDER); + xmatchKeyText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); + xmatchKeyText.setText("x-match"); + xmatchKeyText.setEditable(false); + + final Combo xmatchValueCombo = new Combo(bindingComposite,SWT.NONE | SWT.READ_ONLY); + xmatchValueCombo.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); + xmatchValueCombo.setItems(new String[]{"any", "all"}); + xmatchValueCombo.select(0); + + //make some empty key-value fields + for(int i=0; i < 4; i++) + { + Text keyText = new Text(bindingComposite, SWT.BORDER); + Text valueText = new Text(bindingComposite, SWT.BORDER); + keyText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); + valueText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); + + headerBindingHashMap.put(keyText, valueText); + } + bindingComposite.setSize(bindingComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT)); + + //allow adding more fields for additional key-value pairs + addMoreButton.addSelectionListener(new SelectionAdapter() + { + public void widgetSelected(SelectionEvent e) + { + Text keyText = new Text(bindingComposite, SWT.BORDER); + Text valueText = new Text(bindingComposite, SWT.BORDER); + keyText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); + valueText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); + + headerBindingHashMap.put(keyText, valueText); + + bindingComposite.setSize(bindingComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT)); + bindingComposite.layout(true); + scrolledComposite.layout(true); + } + }); okButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { - String binding = bindingText.getText(); + String xMatchString = xmatchValueCombo.getText(); - if (binding == null || binding.length() == 0) + String destQueue = destinationCombo.getItem(destinationCombo.getSelectionIndex()).toString(); + + StringBuffer bindingValue = new StringBuffer(); + + //insert the x-match key-value pair + if (xMatchString.equalsIgnoreCase("any")) { - ViewUtility.popupErrorMessage("Create New Binding", "Please enter a valid binding"); - return; + bindingValue.append("x-match=any"); + } + else + { + bindingValue.append("x-match=all"); } - String destQueue = destinationCombo.getItem(destinationCombo.getSelectionIndex()).toString(); + //insert the other key-value pairs + for (Text keyText : headerBindingHashMap.keySet()) + { + + String key = keyText.getText(); + if(key == null || key.length() == 0) + { + continue; + } + + Text valueText = headerBindingHashMap.get(keyText); + String value = valueText.getText(); + + bindingValue.append(","); + bindingValue.append(key + "="); + //empty values are permitted, signalling only key-presence is required + if(value != null && value.length() > 0) + { + bindingValue.append(value); + } + } shell.dispose(); try { - _emb.createNewBinding(destQueue, binding); + _emb.createNewBinding(destQueue, bindingValue.toString()); ViewUtility.operationResultFeedback(null, "Created new Binding", null); } catch (Exception e4) diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/ConfigurationFileTabControl.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/ConfigurationFileTabControl.java index 3e8a5da5b5..1b1d08aa67 100644 --- a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/ConfigurationFileTabControl.java +++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/ConfigurationFileTabControl.java @@ -197,8 +197,8 @@ public class ConfigurationFileTabControl extends TabControl "NOTE: These options modify the configuration file. " + "Changes only take effect automatically if LogWatch is enabled."); Label noteLabel2 = _toolkit.createLabel(_headerComposite, - "A Logger set to a non-inherited Level in the Runtime tab " + - "will retain that value after the configuration is reloaded."); + "A child Logger set to a non-inherited Level in the Runtime tab " + + "will retain that value after the file is reloaded."); GridData gridData = new GridData(SWT.FILL, SWT.FILL, false, true); noteLabel.setLayoutData(gridData); gridData = new GridData(SWT.FILL, SWT.FILL, false, true); diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/queue/QueueOperationsTabControl.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/queue/QueueOperationsTabControl.java index c7c7a1791a..43d2cfe204 100644 --- a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/queue/QueueOperationsTabControl.java +++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/queue/QueueOperationsTabControl.java @@ -299,8 +299,8 @@ public class QueueOperationsTabControl extends TabControl //message table Composite tableAndButtonsComposite = _toolkit.createComposite(messagesGroup); gridData = new GridData(SWT.FILL, SWT.FILL, true, true); - gridData.minimumHeight = 220; - gridData.heightHint = 220; + gridData.minimumHeight = 180; + gridData.heightHint = 180; tableAndButtonsComposite.setLayoutData(gridData); tableAndButtonsComposite.setLayout(new GridLayout(2,false)); @@ -358,6 +358,8 @@ public class QueueOperationsTabControl extends TabControl _tableViewer.setContentProvider(new ContentProviderImpl()); _tableViewer.setLabelProvider(new LabelProviderImpl()); _tableViewer.setSorter(tableSorter); + _table.setSortColumn(_table.getColumn(0)); + _table.setSortDirection(SWT.UP); //Side Buttons Composite buttonsComposite = _toolkit.createComposite(tableAndButtonsComposite); @@ -492,12 +494,12 @@ public class QueueOperationsTabControl extends TabControl headerEtcComposite.setLayoutData(gridData); headerEtcComposite.setLayout(new GridLayout()); - final Text headerText = new Text(headerEtcComposite, SWT.WRAP | SWT.BORDER ); + final Text headerText = new Text(headerEtcComposite, SWT.WRAP | SWT.BORDER | SWT.V_SCROLL); headerText.setText("Select a message to view its header."); headerText.setEditable(false); data = new GridData(SWT.LEFT, SWT.TOP, false, false); - data.minimumHeight = 230; - data.heightHint = 230; + data.minimumHeight = 210; + data.heightHint = 210; data.minimumWidth = 500; data.widthHint = 500; headerText.setLayoutData(data); @@ -570,10 +572,16 @@ public class QueueOperationsTabControl extends TabControl String[] msgHeader = (String[]) selectedMsg.get(MSG_HEADER); headerText.setText(""); String lineSeperator = System.getProperty("line.separator"); - for(String s: msgHeader) + int size = msgHeader.length; + for(int i=0; i < size; i++) { - headerText.append(s + lineSeperator); + headerText.append(msgHeader[i]); + if(!(i == size - 1)) + { + headerText.append(lineSeperator); + } } + headerText.setSelection(0); } if (_table.getSelectionCount() > 1) diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/vhost/VHostTabControl.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/vhost/VHostTabControl.java index fef1e9f887..3b03aeaff1 100644 --- a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/vhost/VHostTabControl.java +++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/vhost/VHostTabControl.java @@ -205,6 +205,8 @@ public class VHostTabControl extends TabControl _queueTableViewer.setContentProvider(new ContentProviderImpl()); _queueTableViewer.setLabelProvider(new LabelProviderImpl()); _queueTableViewer.setSorter(tableSorter); + _queueTable.setSortColumn(_queueTable.getColumn(0)); + _queueTable.setSortDirection(SWT.UP); Composite queuesRightComposite = _toolkit.createComposite(queuesGroup); gridData = new GridData(SWT.FILL, SWT.FILL, false, true); @@ -314,6 +316,8 @@ public class VHostTabControl extends TabControl _exchangeTableViewer.setContentProvider(new ContentProviderImpl()); _exchangeTableViewer.setLabelProvider(new LabelProviderImpl()); _exchangeTableViewer.setSorter(exchangeTableSorter); + _exchangeTable.setSortColumn(_exchangeTable.getColumn(0)); + _exchangeTable.setSortDirection(SWT.UP); Composite exchangesRightComposite = _toolkit.createComposite(exchangesGroup); gridData = new GridData(SWT.FILL, SWT.FILL, false, true); diff --git a/qpid/java/management/eclipse-plugin/src/main/resources/win32-win32-x86/qpidmc.ini b/qpid/java/management/eclipse-plugin/src/main/resources/win32-win32-x86/qpidmc.ini index 9e3de042d5..312580769e 100644 --- a/qpid/java/management/eclipse-plugin/src/main/resources/win32-win32-x86/qpidmc.ini +++ b/qpid/java/management/eclipse-plugin/src/main/resources/win32-win32-x86/qpidmc.ini @@ -23,14 +23,14 @@ -XX:MaxPermSize=256m -Dosgi.requiredJavaVersion=1.5 -Declipse.consoleLog=true - -#=============================================== -# SSL trust store configuration options. -#=============================================== - -# Uncomment lines below to specify custom truststore for server SSL -# certificate verification, eg when using self-signed server certs. -# -#-Djavax.net.ssl.trustStore= -#-Djavax.net.ssl.trustStorePassword= - + +#=============================================== +# SSL trust store configuration options. +#=============================================== + +# Uncomment lines below to specify custom truststore for server SSL +# certificate verification, eg when using self-signed server certs. +# +#-Djavax.net.ssl.trustStore= +#-Djavax.net.ssl.trustStorePassword= + diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagementActorLoggingTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagementActorLoggingTest.java index 7a2266902b..b4ba6e8156 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagementActorLoggingTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagementActorLoggingTest.java @@ -29,6 +29,8 @@ import org.apache.qpid.server.logging.AbstractTestLogging; import org.apache.qpid.server.logging.subjects.AbstractTestLogSubject; import javax.jms.Connection; +import javax.jms.ExceptionListener; +import javax.jms.JMSException; import javax.management.JMException; import javax.management.MBeanException; import javax.management.MBeanServerConnection; @@ -38,6 +40,8 @@ import javax.management.remote.JMXConnector; import java.io.IOException; import java.util.List; import java.util.Set; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; /** * Test class to test if any change in the broker JMX code is affesting the management console @@ -161,6 +165,23 @@ public class ManagementActorLoggingTest extends AbstractTestLogging //Create a connection to the broker Connection connection = getConnection(); + // Monitor the connection for an exception being thrown + // this should be a DisconnectionException but it is not this tests + // job to valiate that. Only use the exception as a synchronisation + // to check the log file for the Close message + final CountDownLatch exceptionReceived = new CountDownLatch(1); + connection.setExceptionListener(new ExceptionListener() + { + public void onException(JMSException e) + { + //Failover being attempted. + exceptionReceived.countDown(); + } + }); + + //Remove the connection close from any 0-10 connections + _monitor.reset(); + // Get all active AMQP connections AllObjects allObject = new AllObjects(_mbsc); allObject.querystring = "org.apache.qpid:type=VirtualHost.Connection,*"; @@ -175,16 +196,17 @@ public class ManagementActorLoggingTest extends AbstractTestLogging newProxyInstance(_mbsc, connectionName, ManagedConnection.class, false); - //Remove the connection close from any 0-10 connections - _monitor.reset(); //Close the connection mangedConnection.closeConnection(); + //Wait for the connection to close + assertTrue("Timed out waiting for conneciton to report close", + exceptionReceived.await(2, TimeUnit.SECONDS)); + //Validate results List results = _monitor.findMatches("CON-1002"); - assertEquals("Unexpected Connection Close count", 1, results.size()); } } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/SubscriptionLoggingTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/SubscriptionLoggingTest.java index d7209c5660..5dd56fb0f9 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/SubscriptionLoggingTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/SubscriptionLoggingTest.java @@ -29,6 +29,7 @@ import javax.jms.MessageConsumer; import javax.jms.Queue; import javax.jms.Session; import javax.jms.Topic; +import javax.jms.Message; import java.io.IOException; import java.util.List; @@ -327,22 +328,45 @@ public class SubscriptionLoggingTest extends AbstractTestLogging int PREFETCH = 15; //Create new session with small prefetch - _session = ((AMQConnection) _connection).createSession(true, Session.AUTO_ACKNOWLEDGE, PREFETCH); + _session = ((AMQConnection) _connection).createSession(true, Session.SESSION_TRANSACTED, PREFETCH); MessageConsumer consumer = _session.createConsumer(_queue); _connection.start(); + //Start the dispatcher & Unflow the channel. + consumer.receiveNoWait(); + //Fill the prefetch and two extra so that our receive bellow allows the - // subscription to become active then return to a suspended state. - sendMessage(_session, _queue, 17); + // subscription to become active + // Previously we set this to 17 so that it would return to a suspended + // state. However, testing has shown that the state change can occur + // sufficiently quickly that logging does not occur consistently enough + // for testing. + int SEND_COUNT = 16; + sendMessage(_session, _queue, SEND_COUNT); _session.commit(); // Retreive the first message, and start the flow of messages - assertNotNull("First message not retreived", consumer.receive(1000)); + Message msg = consumer.receive(1000); + assertNotNull("First message not retreived", msg); _session.commit(); - - _connection.close(); + // Drain the queue to ensure there is time for the ACTIVE log message + // Check that we can received all the messages + int receivedCount = 0; + while (msg != null) + { + receivedCount++; + msg = consumer.receive(1000); + _session.commit(); + } + + //Validate we received all the messages + assertEquals("Not all sent messages received.", SEND_COUNT, receivedCount); + + // Fill the queue again to suspend the consumer + sendMessage(_session, _queue, SEND_COUNT); + _session.commit(); //Validate List results = _monitor.findMatches("SUB-1003"); @@ -350,15 +374,13 @@ public class SubscriptionLoggingTest extends AbstractTestLogging try { // Validation expects three messages. - // The first will be logged by the QueueActor as part of the processQueue thread -// INFO - MESSAGE [vh(/test)/qu(example.queue)] [sub:6(qu(example.queue))] SUB-1003 : State : SUSPENDED - // The second will be by the connnection as it acknowledges and activates the subscription -// INFO - MESSAGE [con:6(guest@anonymous(26562441)/test)/ch:3] [sub:6(qu(example.queue))] SUB-1003 : State : ACTIVE - // The final one can be the subscription suspending as part of the SubFlushRunner or the processQueue thread - // As a result validating the actor is more complicated and doesn't add anything. The goal of this test is - // to ensure the State is correct not that a particular Actor performs the logging. -// INFO - MESSAGE [sub:6(vh(test)/qu(example.queue))] [sub:6(qu(example.queue))] SUB-1003 : State : SUSPENDED -// INFO - MESSAGE [vh(/test)/qu(example.queue)] [sub:6(qu(example.queue))] SUB-1003 : State : SUSPENDED + // The Actor can be any one of the following depending on the exactly what is going on on the broker. + // Ideally we would test that we can get all of them but setting up + // the timing to do this in a consistent way is not benefitial. + // Ensuring the State is as expected is sufficient. +// INFO - MESSAGE [vh(/test)/qu(example.queue)] [sub:6(qu(example.queue))] SUB-1003 : State : +// INFO - MESSAGE [con:6(guest@anonymous(26562441)/test)/ch:3] [sub:6(qu(example.queue))] SUB-1003 : State : +// INFO - MESSAGE [sub:6(vh(test)/qu(example.queue))] [sub:6(qu(example.queue))] SUB-1003 : State : assertEquals("Result set not expected size:", 3, results.size()); @@ -367,19 +389,10 @@ public class SubscriptionLoggingTest extends AbstractTestLogging String log = getLog(results.get(0)); validateSubscriptionState(log, expectedState); - // Validate that the logActor is the the queue - String actor = fromActor(log); - assertTrue("Actor string does not contain expected queue(" - + _queue.getQueueName() + ") name." + actor, - actor.contains("qu(" + _queue.getQueueName() + ")")); - // After being suspended the subscription should become active. expectedState = "ACTIVE"; log = getLog(results.get(1)); validateSubscriptionState(log, expectedState); - // Validate we have a connection Actor - actor = fromActor(log); - assertTrue("The actor is not a connection actor:" + actor, actor.startsWith("con:")); // Validate that it was re-suspended expectedState = "SUSPENDED"; @@ -396,6 +409,10 @@ public class SubscriptionLoggingTest extends AbstractTestLogging } throw afe; } + _connection.close(); + + //Ensure the queue is drained before the test ends + drainQueue(_queue); } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/DynamicQueueExchangeCreateTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/DynamicQueueExchangeCreateTest.java new file mode 100644 index 0000000000..c9810e7304 --- /dev/null +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/DynamicQueueExchangeCreateTest.java @@ -0,0 +1,88 @@ +/* + * + * 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.test.unit.client; + +import org.apache.qpid.test.utils.QpidTestCase; + +import javax.jms.Connection; +import javax.jms.JMSException; +import javax.jms.Queue; +import javax.jms.Session; + +/** + * QPID-155 + * + * Test to validate that setting the respective qpid.declare_queues, + * qpid.declare_exchanges system properties functions as expected. + * + */ +public class DynamicQueueExchangeCreateTest extends QpidTestCase +{ + + public void testQueueDeclare() throws Exception + { + setSystemProperty("qpid.declare_queues", "false"); + + Connection connection = getConnection(); + + Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + + Queue queue = session.createQueue(getTestQueueName()); + + try + { + session.createConsumer(queue); + fail("JMSException should be thrown as the queue does not exist"); + } + catch (JMSException e) + { + assertTrue("Exception should be that the queue does not exist :" + + e.getMessage(), + e.getMessage().contains("does not exist")); + + } + } + + public void testExchangeDeclare() throws Exception + { + setSystemProperty("qpid.declare_exchanges", "false"); + + Connection connection = getConnection(); + + Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + + String EXCHANGE_TYPE = "test.direct"; + Queue queue = session.createQueue("direct://" + EXCHANGE_TYPE + "/queue/queue"); + + try + { + session.createConsumer(queue); + fail("JMSException should be thrown as the exchange does not exist"); + } + catch (JMSException e) + { + assertTrue("Exception should be that the exchange does not exist :" + + e.getMessage(), + e.getMessage().contains("Exchange " + EXCHANGE_TYPE + " does not exist")); + } + } + +} diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/close/JavaServerCloseRaceConditionTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/close/JavaServerCloseRaceConditionTest.java new file mode 100644 index 0000000000..3fb6cd3526 --- /dev/null +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/close/JavaServerCloseRaceConditionTest.java @@ -0,0 +1,119 @@ +/* + * + * 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.test.unit.close; + +import org.apache.qpid.client.AMQConnection; +import org.apache.qpid.client.AMQDestination; +import org.apache.qpid.client.AMQSession; +import org.apache.qpid.framing.AMQFrame; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.ExchangeDeclareBody; +import org.apache.qpid.framing.ExchangeDeclareOkBody; +import org.apache.qpid.test.utils.QpidTestCase; + +import javax.jms.Session; + +/** QPID-1809 + * + * Race condition on error handling and close logic. + * + * See most often with SimpleACLTest as this test is the expects the server to + * shut the connection/channels. This sort of testing is not performed by many, + * if any, of the other system tests. + * + * The problem is that we have two threads + * + * MainThread Exception(Mina)Thread + * | | + * Performs | + * ACtion | + * | Receives Server + * | Close + * Blocks for | + * Response | + * | Starts To Notify + * | client + * | | + * | <----- Notify Main Thread + * Notification | + * wakes client | + * | | + * Client then | + * processes Error. | + * | | + * Potentially Attempting Close Channel/Connection + * Connection Close + * + * The two threads both attempt to close the connection but the main thread does + * so assuming that the connection is open and valid. + * + * The Exception thread must modify the connection so that no furter syncWait + * commands are performed. + * + * This test sends an ExchangeDeclare that is Asynchronous and will fail and + * so cause a ChannelClose error but we perform a syncWait so that we can be + * sure to test that the BlockingWaiter is correctly awoken. + * + */ +public class JavaServerCloseRaceConditionTest extends QpidTestCase +{ + private static final String EXCHANGE_NAME = "NewExchangeNametoFailLookup"; + + public void test() throws Exception + { + + AMQConnection connection = (AMQConnection) getConnection(); + + AMQSession session = (AMQSession) connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + + // Set no wait true so that we block the connection + // Also set a different exchange class string so the attempt to declare + // the exchange causes an exchange. + ExchangeDeclareBody body = session.getMethodRegistry().createExchangeDeclareBody(session.getTicket(), new AMQShortString(EXCHANGE_NAME), null, + true, false, false, false, true, null); + + AMQFrame exchangeDeclare = body.generateFrame(session.getChannelId()); + + try + { + // block our thread so that can times out + connection.getProtocolHandler().syncWrite(exchangeDeclare, ExchangeDeclareOkBody.class); + } + catch (Exception e) + { + assertTrue("Exception should say the exchange is not known.", e.getMessage().contains("Unknown exchange: " + EXCHANGE_NAME)); + } + + try + { + // Depending on if the notification thread has closed the connection + // or not we may get an exception here when we attempt to close the + // connection. If we do get one then it should be the same as above + // an AMQAuthenticationException. + connection.close(); + } + catch (Exception e) + { + assertTrue("Exception should say the exchange is not known.", e.getMessage().contains("Unknown exchange: " + EXCHANGE_NAME)); + } + + } +} diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java index c5cdb83bbf..2a44413ac8 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java @@ -51,7 +51,13 @@ import javax.jms.TopicSubscriber; public class DurableSubscriptionTest extends QpidTestCase { private static final Logger _logger = LoggerFactory.getLogger(DurableSubscriptionTest.class); - + + /** Timeout for receive() if we are expecting a message */ + private static final long POSITIVE_RECEIVE_TIMEOUT = 2000; + + /** Timeout for receive() if we are not expecting a message */ + private static final long NEGATIVE_RECEIVE_TIMEOUT = 1000; + public void testUnsubscribe() throws Exception { AMQConnection con = (AMQConnection) getConnection("guest", "guest"); @@ -76,16 +82,18 @@ public class DurableSubscriptionTest extends QpidTestCase Message msg; _logger.info("Receive message on consumer 1:expecting A"); - msg = consumer1.receive(); + msg = consumer1.receive(POSITIVE_RECEIVE_TIMEOUT); + assertNotNull("Message should have been received",msg); assertEquals("A", ((TextMessage) msg).getText()); _logger.info("Receive message on consumer 1 :expecting null"); - msg = consumer1.receive(1000); + msg = consumer1.receive(NEGATIVE_RECEIVE_TIMEOUT); assertEquals(null, msg); - _logger.info("Receive message on consumer 1:expecting A"); - msg = consumer2.receive(); + _logger.info("Receive message on consumer 2:expecting A"); + msg = consumer2.receive(POSITIVE_RECEIVE_TIMEOUT); + assertNotNull("Message should have been received",msg); assertEquals("A", ((TextMessage) msg).getText()); - msg = consumer2.receive(1000); + msg = consumer2.receive(NEGATIVE_RECEIVE_TIMEOUT); _logger.info("Receive message on consumer 1 :expecting null"); assertEquals(null, msg); @@ -96,14 +104,15 @@ public class DurableSubscriptionTest extends QpidTestCase producer.send(session1.createTextMessage("B")); _logger.info("Receive message on consumer 1 :expecting B"); - msg = consumer1.receive(); + msg = consumer1.receive(POSITIVE_RECEIVE_TIMEOUT); + assertNotNull("Message should have been received",msg); assertEquals("B", ((TextMessage) msg).getText()); _logger.info("Receive message on consumer 1 :expecting null"); - msg = consumer1.receive(1000); + msg = consumer1.receive(NEGATIVE_RECEIVE_TIMEOUT); assertEquals(null, msg); _logger.info("Receive message on consumer 2 :expecting null"); - msg = consumer2.receive(1000); + msg = consumer2.receive(NEGATIVE_RECEIVE_TIMEOUT); assertEquals(null, msg); _logger.info("Close connection"); @@ -143,14 +152,16 @@ public class DurableSubscriptionTest extends QpidTestCase producer.send(session1.createTextMessage("A")); Message msg; - msg = consumer1.receive(); + msg = consumer1.receive(POSITIVE_RECEIVE_TIMEOUT); + assertNotNull("Message should have been received",msg); assertEquals("A", ((TextMessage) msg).getText()); - msg = consumer1.receive(1000); + msg = consumer1.receive(NEGATIVE_RECEIVE_TIMEOUT); assertEquals(null, msg); - msg = consumer2.receive(); + msg = consumer2.receive(POSITIVE_RECEIVE_TIMEOUT); + assertNotNull("Message should have been received",msg); assertEquals("A", ((TextMessage) msg).getText()); - msg = consumer2.receive(1000); + msg = consumer2.receive(NEGATIVE_RECEIVE_TIMEOUT); assertEquals(null, msg); consumer2.close(); @@ -220,8 +231,8 @@ public class DurableSubscriptionTest extends QpidTestCase msg = consumer1.receive(500); assertNull("There should be no more messages for consumption on consumer1.", msg); - msg = consumer2.receive(); - assertNotNull(msg); + msg = consumer2.receive(POSITIVE_RECEIVE_TIMEOUT); + assertNotNull("Message should have been received",msg); assertEquals("Consumer 2 should also received the first msg.", "A", ((TextMessage) msg).getText()); msg = consumer2.receive(500); assertNull("There should be no more messages for consumption on consumer2.", msg); @@ -235,10 +246,10 @@ public class DurableSubscriptionTest extends QpidTestCase producer.send(session0.createTextMessage("B")); _logger.info("Receive message on consumer 1 :expecting B"); - msg = consumer1.receive(1000); + msg = consumer1.receive(NEGATIVE_RECEIVE_TIMEOUT); assertEquals("B", ((TextMessage) msg).getText()); _logger.info("Receive message on consumer 1 :expecting null"); - msg = consumer1.receive(1000); + msg = consumer1.receive(NEGATIVE_RECEIVE_TIMEOUT); assertEquals(null, msg); // Re-attach a new consumer to the durable subscription, and check that it gets the message that it missed. @@ -296,7 +307,7 @@ public class DurableSubscriptionTest extends QpidTestCase producer.send(session.createTextMessage("testDurableWithInvalidSelector2")); - Message msg = liveSubscriber.receive(); + Message msg = liveSubscriber.receive(POSITIVE_RECEIVE_TIMEOUT); assertNotNull ("Message should have been received", msg); assertEquals ("testDurableWithInvalidSelector2", ((TextMessage) msg).getText()); assertNull("Should not receive subsequent message", liveSubscriber.receive(200)); @@ -331,7 +342,7 @@ public class DurableSubscriptionTest extends QpidTestCase assertNotNull("Subscriber should have been created", liveSubscriber); producer.send(session.createTextMessage("testDurableWithInvalidSelector2")); - Message msg = liveSubscriber.receive(); + Message msg = liveSubscriber.receive(POSITIVE_RECEIVE_TIMEOUT); assertNotNull ("Message should have been received", msg); assertEquals ("testDurableWithInvalidSelector2", ((TextMessage) msg).getText()); assertNull("Should not receive subsequent message", liveSubscriber.receive(200)); @@ -360,13 +371,13 @@ public class DurableSubscriptionTest extends QpidTestCase // Send 1 matching message and 1 non-matching message sendMatchingAndNonMatchingMessage(session, producer); - Message rMsg = subA.receive(1000); + Message rMsg = subA.receive(NEGATIVE_RECEIVE_TIMEOUT); assertNotNull(rMsg); assertEquals("Content was wrong", "testResubscribeWithChangedSelector1", ((TextMessage) rMsg).getText()); - rMsg = subA.receive(1000); + rMsg = subA.receive(NEGATIVE_RECEIVE_TIMEOUT); assertNull(rMsg); // Disconnect subscriber @@ -379,13 +390,13 @@ public class DurableSubscriptionTest extends QpidTestCase // Check messages are recieved properly sendMatchingAndNonMatchingMessage(session, producer); - rMsg = subB.receive(1000); + rMsg = subB.receive(NEGATIVE_RECEIVE_TIMEOUT); assertNotNull(rMsg); assertEquals("Content was wrong", "testResubscribeWithChangedSelector2", ((TextMessage) rMsg).getText()); - rMsg = subB.receive(1000); + rMsg = subB.receive(NEGATIVE_RECEIVE_TIMEOUT); assertNull(rMsg); session.unsubscribe("testResubscribeWithChangedSelector"); } @@ -429,5 +440,5 @@ public class DurableSubscriptionTest extends QpidTestCase public static junit.framework.Test suite() { return new junit.framework.TestSuite(DurableSubscriptionTest.class); - } + } } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/CommitRollbackTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/CommitRollbackTest.java index 9c755fcb41..b603455644 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/CommitRollbackTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/CommitRollbackTest.java @@ -479,7 +479,7 @@ public class CommitRollbackTest extends QpidTestCase _publisher.send(_pubSession.createTextMessage(MESSAGE_TEXT)); _pubSession.commit(); - assertNotNull(_consumer.receive(100)); + assertNotNull(_consumer.receive(1000)); _publisher.send(_pubSession.createTextMessage(MESSAGE_TEXT)); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/FailoverBaseCase.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/FailoverBaseCase.java index cc9cfce34b..1bef07fcd5 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/FailoverBaseCase.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/FailoverBaseCase.java @@ -55,7 +55,7 @@ public class FailoverBaseCase extends QpidTestCase { super.setUp(); setSystemProperty("QPID_WORK", System.getProperty("java.io.tmpdir")+"/"+getFailingPort()); - startBroker(FAILING_PORT); + startBroker(failingPort); } /** @@ -76,7 +76,7 @@ public class FailoverBaseCase extends QpidTestCase public void tearDown() throws Exception { - stopBroker(FAILING_PORT); + stopBroker(_broker.equals(VM)?FAILING_PORT:FAILING_PORT); super.tearDown(); FileUtils.deleteDirectory(System.getProperty("java.io.tmpdir")+"/"+getFailingPort()); } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/util/LogMonitor.java b/qpid/java/systests/src/main/java/org/apache/qpid/util/LogMonitor.java index df8dd0b85b..44ac5b4838 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/util/LogMonitor.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/util/LogMonitor.java @@ -31,6 +31,7 @@ import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.OutputStreamWriter; +import java.util.ArrayList; import java.util.List; /** @@ -118,7 +119,7 @@ public class LogMonitor * @throws java.io.FileNotFoundException if the Log file can nolonger be found * @throws IOException thrown when reading the log file */ - public boolean waitForMessage(String message, long wait) + public boolean waitForMessage(String message, long wait, boolean printFileOnFailure) throws FileNotFoundException, IOException { // Loop through alerts until we're done or wait ms seconds have passed, @@ -126,20 +127,35 @@ public class LogMonitor BufferedReader reader = new BufferedReader(new FileReader(_logfile)); boolean found = false; long endtime = System.currentTimeMillis() + wait; + ArrayList contents = new ArrayList(); while (!found && System.currentTimeMillis() < endtime) { while (reader.ready()) { String line = reader.readLine(); + contents.add(line); if (line.contains(message)) { found = true; } } } - + if (!found && printFileOnFailure) + { + for (String line : contents) + { + System.out.println(line); + } + } return found; } + + + public boolean waitForMessage(String messageCountAlert, long alertLogWaitPeriod) throws FileNotFoundException, IOException + { + return waitForMessage(messageCountAlert, alertLogWaitPeriod, true); + } + /** * Read the log file in to memory as a String diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/util/LogMonitorTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/util/LogMonitorTest.java index d1a0df30a9..2b9fe8e039 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/util/LogMonitorTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/util/LogMonitorTest.java @@ -30,25 +30,25 @@ import java.util.List; public class LogMonitorTest extends TestCase { + private LogMonitor _monitor; + + @Override + public void setUp() throws Exception + { + _monitor = new LogMonitor(); + _monitor.getMonitoredFile().deleteOnExit(); // Make sure we clean up + } + /** * Test that a new file is created when attempting to set up a monitor with * the default constructor. */ public void testMonitor() { - // Validate that a NPE is thrown with null input - try - { - LogMonitor montior = new LogMonitor(); - //Validte that the monitor is now running on a new file - assertTrue("New file does not have correct name:" + montior. - getMonitoredFile().getName(), - montior.getMonitoredFile().getName().contains("LogMonitor")); - } - catch (IOException ioe) - { - fail("IOE thrown:" + ioe); - } + //Validate that the monitor is now running on a new file + assertTrue("New file does not have correct name:" + _monitor. + getMonitoredFile().getName(), + _monitor.getMonitoredFile().getName().contains("LogMonitor")); } /** @@ -63,13 +63,11 @@ public class LogMonitorTest extends TestCase File testFile = File.createTempFile("testMonitorFile", ".log"); testFile.deleteOnExit(); - LogMonitor monitor; - //Ensure that we can create a monitor on a file try { - monitor = new LogMonitor(testFile); - assertEquals(testFile, monitor.getMonitoredFile()); + _monitor = new LogMonitor(testFile); + assertEquals(testFile, _monitor.getMonitoredFile()); } catch (IOException ioe) { @@ -136,13 +134,12 @@ public class LogMonitorTest extends TestCase */ public void testFindMatches_Match() throws IOException { - LogMonitor monitor = new LogMonitor(); String message = getName() + ": Test Message"; Logger.getRootLogger().warn(message); - validateLogContainsMessage(monitor, message); + validateLogContainsMessage(_monitor, message); } /** @@ -152,35 +149,17 @@ public class LogMonitorTest extends TestCase */ public void testFindMatches_NoMatch() throws IOException { - LogMonitor monitor = new LogMonitor(); - String message = getName() + ": Test Message"; Logger.getRootLogger().warn(message); String notLogged = "This text was not logged"; - validateLogDoesNotContainsMessage(monitor, notLogged); - } - - public void testWaitForMessage_Found() throws IOException - { - LogMonitor monitor = new LogMonitor(); - - String message = getName() + ": Test Message"; - - long TIME_OUT = 2000; - - logMessageWithDelay(message, TIME_OUT / 2); - - assertTrue("Message was not logged ", - monitor.waitForMessage(message, TIME_OUT)); + validateLogDoesNotContainsMessage(_monitor, notLogged); } public void testWaitForMessage_Timeout() throws IOException { - LogMonitor monitor = new LogMonitor(); - String message = getName() + ": Test Message"; long TIME_OUT = 2000; @@ -189,41 +168,37 @@ public class LogMonitorTest extends TestCase // Verify that we can time out waiting for a message assertFalse("Message was logged ", - monitor.waitForMessage(message, TIME_OUT / 2)); + _monitor.waitForMessage(message, TIME_OUT / 2, false)); // Verify that the message did eventually get logged. assertTrue("Message was never logged.", - monitor.waitForMessage(message, TIME_OUT)); + _monitor.waitForMessage(message, TIME_OUT)); } public void testReset() throws IOException { - LogMonitor monitor = new LogMonitor(); - String message = getName() + ": Test Message"; Logger.getRootLogger().warn(message); - validateLogContainsMessage(monitor, message); + validateLogContainsMessage(_monitor, message); String LOG_RESET_TEXT = "Log Monitor Reset"; - validateLogDoesNotContainsMessage(monitor, LOG_RESET_TEXT); + validateLogDoesNotContainsMessage(_monitor, LOG_RESET_TEXT); - monitor.reset(); + _monitor.reset(); - assertEquals("", monitor.readFile()); + assertEquals("", _monitor.readFile()); } public void testRead() throws IOException { - LogMonitor monitor = new LogMonitor(); - String message = getName() + ": Test Message"; Logger.getRootLogger().warn(message); - String fileContents = monitor.readFile(); + String fileContents = _monitor.readFile(); assertTrue("Logged message not found when reading file.", fileContents.contains(message)); diff --git a/qpid/java/test-profiles/010Excludes b/qpid/java/test-profiles/010Excludes index 7577ad8da1..36e7317e31 100644 --- a/qpid/java/test-profiles/010Excludes +++ b/qpid/java/test-profiles/010Excludes @@ -4,6 +4,7 @@ org.apache.qpid.client.ResetMessageListenerTest#* //These tests are for the java broker org.apache.qpid.server.security.acl.SimpleACLTest#* org.apache.qpid.server.plugins.PluginTest#* +org.apache.qpid.server.BrokerStartupTest#* // This test is not finished org.apache.qpid.test.testcases.TTLTest#* @@ -82,3 +83,9 @@ org.apache.qpid.server.logging.* // CPP Broker does not have a JMX interface to test org.apache.qpid.management.jmx.* + +// 0-10 is not supported by the MethodRegistry +org.apache.qpid.test.unit.close.JavaServerCloseRaceConditionTest#* + +// QPID-2084 : this test needs more work for 0-10 +org.apache.qpid.test.unit.client.DynamicQueueExchangeCreateTest#* -- cgit v1.2.1 From 9c4ecc45da929750ff7f0e0a5d7ada4e674b9105 Mon Sep 17 00:00:00 2001 From: Aidan Skinner Date: Wed, 16 Sep 2009 10:06:55 +0000 Subject: QPID-2105: Make NetworkDriver.open use a SSLContextFactory, not an SSLEngine. Allow an existing SocketConnector to be passed into a MINANetworkDriver, for use with the ExistingSocket bit of TransportConnection. Move the ExistingSocket stuff to one place, use MINANetworkDriver in TransportConnection and make AMQProtocolHandler implement ProtocolEngine. Remove MINA specific gubbins from AMQProtocolHandler and AMQProtocolSession. Move fireAsynchEvent to Job Add getLocalAddress to AMQProtocolEngine Move TestNetworkDriver to common Use correct class for logger in AMQProtocolEngine Check the exception is thrown properly in SimpleACLTest, make it a little less prone to obscure race conditions. git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/java-network-refactor@815704 13f79535-47bb-0310-9956-ffa450edef68 --- qpid/java/broker/build.xml | 1 + .../qpid/server/protocol/AMQProtocolEngine.java | 55 +--- .../configuration/ServerConfigurationTest.java | 10 +- .../protocol/InternalTestProtocolSession.java | 1 + .../qpid/server/protocol/TestNetworkDriver.java | 126 ------- .../access/plugins/network/FirewallPluginTest.java | 24 +- qpid/java/client/build.xml | 1 + .../qpid/client/AMQConnectionDelegate_8_0.java | 2 +- .../qpid/client/failover/FailoverHandler.java | 10 +- .../qpid/client/protocol/AMQProtocolHandler.java | 363 +++++++++++---------- .../qpid/client/protocol/AMQProtocolSession.java | 110 +------ .../transport/SocketTransportConnection.java | 62 ++-- .../qpid/client/transport/TransportConnection.java | 19 +- .../transport/VmPipeTransportConnection.java | 11 +- .../client/protocol/AMQProtocolHandlerTest.java | 5 +- .../src/main/java/org/apache/qpid/pool/Job.java | 40 +++ .../org/apache/qpid/protocol/ProtocolEngine.java | 3 + .../org/apache/qpid/transport/NetworkDriver.java | 9 +- .../org/apache/qpid/transport/OpenException.java | 4 +- .../transport/network/mina/MINANetworkDriver.java | 108 +++--- .../apache/qpid/transport/TestNetworkDriver.java | 122 +++++++ .../network/mina/MINANetworkDriverTest.java | 13 + qpid/java/systests/build.xml | 2 +- .../qpid/server/security/acl/SimpleACLTest.java | 54 +-- .../client/protocol/AMQProtocolSessionTest.java | 29 +- 25 files changed, 588 insertions(+), 596 deletions(-) delete mode 100644 qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/TestNetworkDriver.java create mode 100644 qpid/java/common/src/test/java/org/apache/qpid/transport/TestNetworkDriver.java (limited to 'qpid/java') diff --git a/qpid/java/broker/build.xml b/qpid/java/broker/build.xml index 3c63c459be..ae133d1a96 100644 --- a/qpid/java/broker/build.xml +++ b/qpid/java/broker/build.xml @@ -21,6 +21,7 @@ + diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java index 19d98161c6..16ebc76185 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java @@ -31,8 +31,6 @@ import java.util.List; import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArraySet; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.atomic.AtomicLong; import javax.management.JMException; @@ -51,7 +49,6 @@ import org.apache.qpid.framing.AMQDataBlock; import org.apache.qpid.framing.AMQFrame; import org.apache.qpid.framing.AMQMethodBody; import org.apache.qpid.framing.AMQProtocolHeaderException; -import org.apache.qpid.framing.AMQProtocolVersionException; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.ChannelCloseOkBody; import org.apache.qpid.framing.ConnectionCloseBody; @@ -94,7 +91,7 @@ import org.apache.qpid.transport.Sender; public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocolSession { - private static final Logger _logger = Logger.getLogger(AMQProtocolSession.class); + private static final Logger _logger = Logger.getLogger(AMQProtocolEngine.class); private static final String CLIENT_PROPERTIES_INSTANCE = ClientProperties.instance.toString(); @@ -180,6 +177,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol _actor = new AMQPConnectionActor(this, virtualHostRegistry.getApplicationRegistry().getRootMessageLogger()); _actor.message(ConnectionMessages.CON_1001(null, null, false, false)); + _poolReference.acquireExecutorService(); } private AMQProtocolSessionMBean createMBean() throws AMQException @@ -212,7 +210,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol try { final ArrayList dataBlocks = _codecFactory.getDecoder().decodeBuffer(msg); - fireAsynchEvent(_readJob, new Event(new Runnable() + Job.fireAsynchEvent(_poolReference.getPool(), _readJob, new Event(new Runnable() { @Override public void run() @@ -463,7 +461,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol final ByteBuffer buf = frame.toNioByteBuffer(); _lastIoTime = System.currentTimeMillis(); _writtenBytes += buf.remaining(); - fireAsynchEvent(_writeJob, new Event(new Runnable() + Job.fireAsynchEvent(_poolReference.getPool(), _writeJob, new Event(new Runnable() { @Override public void run() @@ -687,6 +685,10 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol /** This must be called when the session is _closed in order to free up any resources managed by the session. */ public void closeSession() throws AMQException { + if (CurrentActor.get() == null) + { + CurrentActor.set(_actor); + } if (!_closed) { if (_virtualHost != null) @@ -907,6 +909,11 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol public SocketAddress getRemoteAddress() { return _networkDriver.getRemoteAddress(); + } + + public SocketAddress getLocalAddress() + { + return _networkDriver.getLocalAddress(); } public MethodRegistry getMethodRegistry() @@ -990,7 +997,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol { // Do nothing } - + @Override public long getReadBytes() { @@ -1017,38 +1024,6 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol return (_clientVersion == null) ? null : _clientVersion.toString(); } - /** - * Adds an {@link Event} to a {@link Job}, triggering the execution of the job if it is not already running. - * - * @param job The job. - * @param event The event to hand off asynchronously. - */ - void fireAsynchEvent(Job job, Event event) - { - - job.add(event); - - final ExecutorService pool = _poolReference .getPool(); - - if(pool == null) - { - return; - } - - // rather than perform additional checks on pool to check that it hasn't shutdown. - // catch the RejectedExecutionException that will result from executing on a shutdown pool - if (job.activate()) - { - try - { - pool.execute(job); - } - catch(RejectedExecutionException e) - { - _logger.warn("Thread pool shutdown while tasks still outstanding"); - } - } - - } + } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java index 1162687741..2285f5256e 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java @@ -35,11 +35,11 @@ import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.XMLConfiguration; import org.apache.qpid.server.protocol.AMQProtocolEngine; import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.protocol.TestNetworkDriver; import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.registry.ConfigurationFileApplicationRegistry; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.server.virtualhost.VirtualHostRegistry; +import org.apache.qpid.transport.TestNetworkDriver; public class ServerConfigurationTest extends TestCase { @@ -793,12 +793,12 @@ public class ServerConfigurationTest extends TestCase VirtualHost virtualHost = virtualHostRegistry.getVirtualHost("test"); TestNetworkDriver testDriver = new TestNetworkDriver(); - testDriver.setAddress("127.0.0.1"); + testDriver.setRemoteAddress("127.0.0.1"); AMQProtocolEngine session = new AMQProtocolEngine(virtualHostRegistry, testDriver); assertFalse(reg.getAccessManager().authoriseConnect(session, virtualHost)); - testDriver.setAddress("127.1.2.3"); + testDriver.setRemoteAddress("127.1.2.3"); session = new AMQProtocolEngine(virtualHostRegistry, testDriver); assertTrue(reg.getAccessManager().authoriseConnect(session, virtualHost)); } @@ -867,7 +867,7 @@ public class ServerConfigurationTest extends TestCase VirtualHost virtualHost = virtualHostRegistry.getVirtualHost("test"); TestNetworkDriver testDriver = new TestNetworkDriver(); - testDriver.setAddress("127.0.0.1"); + testDriver.setRemoteAddress("127.0.0.1"); AMQProtocolEngine session = new AMQProtocolEngine(virtualHostRegistry, testDriver); session.setNetworkDriver(testDriver); @@ -935,7 +935,7 @@ public class ServerConfigurationTest extends TestCase // Test config TestNetworkDriver testDriver = new TestNetworkDriver(); - testDriver.setAddress("127.0.0.1"); + testDriver.setRemoteAddress("127.0.0.1"); VirtualHostRegistry virtualHostRegistry = reg.getVirtualHostRegistry(); VirtualHost virtualHost = virtualHostRegistry.getVirtualHost("test"); AMQProtocolSession session = new AMQProtocolEngine(virtualHostRegistry, testDriver); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/InternalTestProtocolSession.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/InternalTestProtocolSession.java index c4362f2c60..ec7bf1cb72 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/InternalTestProtocolSession.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/InternalTestProtocolSession.java @@ -34,6 +34,7 @@ import org.apache.qpid.server.output.ProtocolOutputConverter; import org.apache.qpid.server.queue.AMQMessage; import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.transport.TestNetworkDriver; public class InternalTestProtocolSession extends AMQProtocolEngine implements ProtocolOutputConverter { diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/TestNetworkDriver.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/TestNetworkDriver.java deleted file mode 100644 index 098843d315..0000000000 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/TestNetworkDriver.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.protocol; - -import java.net.BindException; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.nio.ByteBuffer; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -import javax.net.ssl.SSLEngine; - -import org.apache.qpid.protocol.ProtocolEngine; -import org.apache.qpid.protocol.ProtocolEngineFactory; -import org.apache.qpid.ssl.SSLContextFactory; -import org.apache.qpid.transport.NetworkDriver; -import org.apache.qpid.transport.NetworkDriverConfiguration; -import org.apache.qpid.transport.OpenException; - -/** - * Test implementation of IoSession, which is required for some tests. Methods not being used are not implemented, - * so if this class is being used and some methods are to be used, then please update those. - */ -public class TestNetworkDriver implements NetworkDriver -{ - private final ConcurrentMap attributes = new ConcurrentHashMap(); - private String _address = "127.0.0.1"; - private int _port = 1; - - public TestNetworkDriver() - { - } - - public void setAddress(String string) - { - this._address = string; - } - - public String getAddress() - { - return _address; - } - - public void setPort(int _port) - { - this._port = _port; - } - - public int getPort() - { - return _port; - } - - public void bind(int port, InetAddress[] addresses, ProtocolEngineFactory protocolFactory, - NetworkDriverConfiguration config, SSLContextFactory sslFactory) throws BindException - { - - } - - public SocketAddress getLocalAddress() - { - return new InetSocketAddress(_address, _port); - } - - public SocketAddress getRemoteAddress() - { - return new InetSocketAddress(_address, _port); - } - - public void open(int port, InetAddress destination, ProtocolEngine engine, NetworkDriverConfiguration config, - SSLEngine sslEngine) throws OpenException - { - - } - - public void setMaxReadIdle(int idleTime) - { - - } - - public void setMaxWriteIdle(int idleTime) - { - - } - - public void close() - { - - } - - public void flush() - { - - } - - public void send(ByteBuffer msg) - { - - } - - public void setIdleTimeout(long l) - { - - } - -} diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/plugins/network/FirewallPluginTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/plugins/network/FirewallPluginTest.java index bda816f5ab..5d3335c001 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/plugins/network/FirewallPluginTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/plugins/network/FirewallPluginTest.java @@ -32,12 +32,12 @@ import junit.framework.TestCase; import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.XMLConfiguration; import org.apache.qpid.server.protocol.AMQProtocolEngine; -import org.apache.qpid.server.protocol.TestNetworkDriver; import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.security.access.ACLPlugin.AuthzResult; import org.apache.qpid.server.store.TestableMemoryMessageStore; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.server.virtualhost.VirtualHostRegistry; +import org.apache.qpid.transport.TestNetworkDriver; public class FirewallPluginTest extends TestCase { @@ -90,7 +90,7 @@ public class FirewallPluginTest extends TestCase super.setUp(); _store = new TestableMemoryMessageStore(); _testDriver = new TestNetworkDriver(); - _testDriver.setAddress("127.0.0.1"); + _testDriver.setRemoteAddress("127.0.0.1"); // Retreive VirtualHost from the Registry VirtualHostRegistry virtualHostRegistry = ApplicationRegistry.getInstance().getVirtualHostRegistry(); @@ -167,7 +167,7 @@ public class FirewallPluginTest extends TestCase assertEquals(AuthzResult.DENIED, plugin.authoriseConnect(_session, _virtualHost)); // Set session IP so that we're connected from the right address - _testDriver.setAddress("192.168.23.23"); + _testDriver.setRemoteAddress("192.168.23.23"); assertEquals(AuthzResult.ALLOWED, plugin.authoriseConnect(_session, _virtualHost)); } @@ -182,7 +182,7 @@ public class FirewallPluginTest extends TestCase assertEquals(AuthzResult.DENIED, plugin.authoriseConnect(_session, _virtualHost)); // Set session IP so that we're connected from the right address - _testDriver.setAddress("192.168.23.23"); + _testDriver.setRemoteAddress("192.168.23.23"); assertEquals(AuthzResult.ALLOWED, plugin.authoriseConnect(_session, _virtualHost)); } @@ -195,7 +195,7 @@ public class FirewallPluginTest extends TestCase FirewallPlugin plugin = initialisePlugin("deny", new RuleInfo[]{rule}); // Set session IP so that we're connected from the right address - _testDriver.setAddress("127.0.0.1"); + _testDriver.setRemoteAddress("127.0.0.1"); assertEquals(AuthzResult.ALLOWED, plugin.authoriseConnect(_session, _virtualHost)); } @@ -208,7 +208,7 @@ public class FirewallPluginTest extends TestCase FirewallPlugin plugin = initialisePlugin("deny", new RuleInfo[]{rule}); // Set session IP so that we're connected from the right address - _testDriver.setAddress("127.0.0.1"); + _testDriver.setRemoteAddress("127.0.0.1"); assertEquals(AuthzResult.ALLOWED, plugin.authoriseConnect(_session, _virtualHost)); } @@ -231,7 +231,7 @@ public class FirewallPluginTest extends TestCase assertEquals(AuthzResult.DENIED, plugin.authoriseConnect(_session, _virtualHost)); // Set session IP so that we're connected from the right address - _testDriver.setAddress("192.168.23.23"); + _testDriver.setRemoteAddress("192.168.23.23"); assertEquals(AuthzResult.ALLOWED, plugin.authoriseConnect(_session, _virtualHost)); } @@ -254,7 +254,7 @@ public class FirewallPluginTest extends TestCase assertEquals(AuthzResult.DENIED, plugin.authoriseConnect(_session, _virtualHost)); // Set session IP so that we're connected from the right address - _testDriver.setAddress("192.168.23.23"); + _testDriver.setRemoteAddress("192.168.23.23"); assertEquals(AuthzResult.ALLOWED, plugin.authoriseConnect(_session, _virtualHost)); } @@ -268,7 +268,7 @@ public class FirewallPluginTest extends TestCase assertEquals(AuthzResult.DENIED, plugin.authoriseConnect(_session, _virtualHost)); // Set session IP so that we're connected from the right address - _testDriver.setAddress("192.168.23.23"); + _testDriver.setRemoteAddress("192.168.23.23"); assertEquals(AuthzResult.ALLOWED, plugin.authoriseConnect(_session, _virtualHost)); } @@ -282,7 +282,7 @@ public class FirewallPluginTest extends TestCase assertEquals(AuthzResult.DENIED, plugin.authoriseConnect(_session, _virtualHost)); // Set session IP so that we're connected from the right address - _testDriver.setAddress("192.168.23.23"); + _testDriver.setRemoteAddress("192.168.23.23"); assertEquals(AuthzResult.ALLOWED, plugin.authoriseConnect(_session, _virtualHost)); } @@ -292,11 +292,11 @@ public class FirewallPluginTest extends TestCase firstRule.setAccess("allow"); firstRule.setHostname("foo, bar, "+new InetSocketAddress("127.0.0.1", 5672).getHostName()); FirewallPlugin plugin = initialisePlugin("deny", new RuleInfo[]{firstRule}); - _testDriver.setAddress("10.0.0.1"); + _testDriver.setRemoteAddress("10.0.0.1"); assertEquals(AuthzResult.DENIED, plugin.authoriseConnect(_session, _virtualHost)); // Set session IP so that we're connected from the right address - _testDriver.setAddress("127.0.0.1"); + _testDriver.setRemoteAddress("127.0.0.1"); assertEquals(AuthzResult.ALLOWED, plugin.authoriseConnect(_session, _virtualHost)); } diff --git a/qpid/java/client/build.xml b/qpid/java/client/build.xml index 321e613d94..3c6132dc5b 100644 --- a/qpid/java/client/build.xml +++ b/qpid/java/client/build.xml @@ -21,6 +21,7 @@ + diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_8_0.java b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_8_0.java index a0b69b5493..9876393d4c 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_8_0.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_8_0.java @@ -97,7 +97,7 @@ public class AMQConnectionDelegate_8_0 implements AMQConnectionDelegate { _conn.getProtocolHandler().createIoTransportSession(brokerDetail); } - + _conn._protocolHandler.getProtocolSession().init(); // this blocks until the connection has been set up or when an error // has prevented the connection being set up diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/failover/FailoverHandler.java b/qpid/java/client/src/main/java/org/apache/qpid/client/failover/FailoverHandler.java index 927f660932..8223cd5394 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/failover/FailoverHandler.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/failover/FailoverHandler.java @@ -20,8 +20,6 @@ */ package org.apache.qpid.client.failover; -import org.apache.mina.common.IoSession; - import org.apache.qpid.AMQDisconnectedException; import org.apache.qpid.client.protocol.AMQProtocolHandler; import org.apache.qpid.client.state.AMQStateManager; @@ -81,9 +79,6 @@ public class FailoverHandler implements Runnable /** Used for debugging. */ private static final Logger _logger = LoggerFactory.getLogger(FailoverHandler.class); - /** Holds the MINA session for the connection that has failed, not the connection that is being failed onto. */ - private final IoSession _session; - /** Holds the protocol handler for the failed connection, upon which the new connection is to be set up. */ private AMQProtocolHandler _amqProtocolHandler; @@ -99,10 +94,9 @@ public class FailoverHandler implements Runnable * @param amqProtocolHandler The protocol handler that spans the failover. * @param session The MINA session, for the failing connection. */ - public FailoverHandler(AMQProtocolHandler amqProtocolHandler, IoSession session) + public FailoverHandler(AMQProtocolHandler amqProtocolHandler) { _amqProtocolHandler = amqProtocolHandler; - _session = session; } /** @@ -221,7 +215,7 @@ public class FailoverHandler implements Runnable _amqProtocolHandler.setFailoverState(FailoverState.FAILED); /*try {*/ - _amqProtocolHandler.exceptionCaught(_session, e); + _amqProtocolHandler.exception(e); /*} catch (Exception ex) { diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java b/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java index ab3ff8ecb0..c7e2493025 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java @@ -20,10 +20,6 @@ */ package org.apache.qpid.client.protocol; -import org.apache.mina.common.IdleStatus; -import org.apache.mina.common.IoFilterChain; -import org.apache.mina.common.IoHandlerAdapter; -import org.apache.mina.common.IoSession; import org.apache.mina.filter.ReadThrottleFilterBuilder; import org.apache.mina.filter.SSLFilter; import org.apache.mina.filter.WriteBufferLimitFilterBuilder; @@ -48,16 +44,25 @@ import org.apache.qpid.client.state.listener.SpecificMethodFrameListener; import org.apache.qpid.codec.AMQCodecFactory; import org.apache.qpid.framing.*; import org.apache.qpid.jms.BrokerDetails; +import org.apache.qpid.pool.Event; +import org.apache.qpid.pool.Job; +import org.apache.qpid.pool.PoolingFilter; import org.apache.qpid.pool.ReadWriteThreadModel; +import org.apache.qpid.pool.ReferenceCountingExecutorService; import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.protocol.AMQMethodEvent; import org.apache.qpid.protocol.AMQMethodListener; +import org.apache.qpid.protocol.ProtocolEngine; import org.apache.qpid.ssl.SSLContextFactory; +import org.apache.qpid.transport.NetworkDriver; import org.apache.qpid.transport.network.io.IoTransport; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; +import java.net.SocketAddress; +import java.nio.ByteBuffer; +import java.util.ArrayList; import java.util.Iterator; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; @@ -120,7 +125,7 @@ import java.util.concurrent.CountDownLatch; * held per protocol handler, per protocol session, per network connection, per channel, in seperate classes, so * that lifecycles of the fields match lifecycles of their containing objects. */ -public class AMQProtocolHandler extends IoHandlerAdapter +public class AMQProtocolHandler implements ProtocolEngine { /** Used for debugging. */ private static final Logger _logger = LoggerFactory.getLogger(AMQProtocolHandler.class); @@ -137,7 +142,7 @@ public class AMQProtocolHandler extends IoHandlerAdapter private volatile AMQProtocolSession _protocolSession; /** Holds the state of the protocol session. */ - private AMQStateManager _stateManager = new AMQStateManager(); + private AMQStateManager _stateManager; /** Holds the method listeners, */ private final CopyOnWriteArraySet _frameListeners = new CopyOnWriteArraySet(); @@ -166,7 +171,15 @@ public class AMQProtocolHandler extends IoHandlerAdapter /** Object to lock on when changing the latch */ private Object _failoverLatchChange = new Object(); - + private AMQCodecFactory _codecFactory; + private Job _readJob; + private Job _writeJob; + private ReferenceCountingExecutorService _poolReference = ReferenceCountingExecutorService.getInstance(); + private NetworkDriver _networkDriver; + + private long _writtenBytes; + private long _readBytes; + /** * Creates a new protocol handler, associated with the specified client connection instance. * @@ -175,86 +188,14 @@ public class AMQProtocolHandler extends IoHandlerAdapter public AMQProtocolHandler(AMQConnection con) { _connection = con; - } - - /** - * Invoked by MINA when a MINA session for a new connection is created. This method sets up the filter chain on the - * session, which filters the events handled by this handler. The filter chain consists of, handing off events - * to an asynchronous thread pool, optionally encoding/decoding ssl, encoding/decoding AMQP. - * - * @param session The MINA session. - * - * @throws Exception Any underlying exceptions are allowed to fall through to MINA. - */ - public void sessionCreated(IoSession session) throws Exception - { - _logger.debug("Protocol session created for session " + System.identityHashCode(session)); - _failoverHandler = new FailoverHandler(this, session); - - final ProtocolCodecFilter pcf = new ProtocolCodecFilter(new AMQCodecFactory(false, _protocolSession)); - - if (Boolean.getBoolean("amqj.shared_read_write_pool")) - { - session.getFilterChain().addBefore("AsynchronousWriteFilter", "protocolFilter", pcf); - } - else - { - session.getFilterChain().addLast("protocolFilter", pcf); - } - // we only add the SSL filter where we have an SSL connection - if (_connection.getSSLConfiguration() != null) - { - SSLConfiguration sslConfig = _connection.getSSLConfiguration(); - SSLContextFactory sslFactory = - new SSLContextFactory(sslConfig.getKeystorePath(), sslConfig.getKeystorePassword(), sslConfig.getCertType()); - SSLFilter sslFilter = new SSLFilter(sslFactory.buildClientContext()); - sslFilter.setUseClientMode(true); - session.getFilterChain().addBefore("protocolFilter", "ssl", sslFilter); - } - - try - { - ReadWriteThreadModel threadModel = ReadWriteThreadModel.getInstance(); - threadModel.getAsynchronousReadFilter().createNewJobForSession(session); - threadModel.getAsynchronousWriteFilter().createNewJobForSession(session); - } - catch (RuntimeException e) - { - _logger.error(e.getMessage(), e); - } - - if (Boolean.getBoolean(ClientProperties.PROTECTIO_PROP_NAME)) - { - try - { - //Add IO Protection Filters - IoFilterChain chain = session.getFilterChain(); - - session.getFilterChain().addLast("tempExecutorFilterForFilterBuilder", new ExecutorFilter()); - - ReadThrottleFilterBuilder readfilter = new ReadThrottleFilterBuilder(); - readfilter.setMaximumConnectionBufferSize(Integer.parseInt(System.getProperty( - ClientProperties.READ_BUFFER_LIMIT_PROP_NAME, ClientProperties.READ_BUFFER_LIMIT_DEFAULT))); - readfilter.attach(chain); - - WriteBufferLimitFilterBuilder writefilter = new WriteBufferLimitFilterBuilder(); - writefilter.setMaximumConnectionBufferSize(Integer.parseInt(System.getProperty( - ClientProperties.WRITE_BUFFER_LIMIT_PROP_NAME, ClientProperties.WRITE_BUFFER_LIMIT_DEFAULT))); - writefilter.attach(chain); - session.getFilterChain().remove("tempExecutorFilterForFilterBuilder"); - - _logger.info("Using IO Read/Write Filter Protection"); - } - catch (Exception e) - { - _logger.error("Unable to attach IO Read/Write Filter Protection :" + e.getMessage()); - } - } - _protocolSession = new AMQProtocolSession(this, session, _connection); - - _stateManager.setProtocolSession(_protocolSession); - - _protocolSession.init(); + _protocolSession = new AMQProtocolSession(this, _connection); + _stateManager = new AMQStateManager(_protocolSession); + _codecFactory = new AMQCodecFactory(false, _protocolSession); + ReadWriteThreadModel threadModel = ReadWriteThreadModel.getInstance(); + _readJob = new Job(threadModel.getAsynchronousReadFilter(), PoolingFilter.MAX_JOB_EVENTS, true); + _writeJob = new Job(threadModel.getAsynchronousWriteFilter(), PoolingFilter.MAX_JOB_EVENTS, false); + _poolReference.acquireExecutorService(); + _failoverHandler = new FailoverHandler(this); } /** @@ -283,12 +224,10 @@ public class AMQProtocolHandler extends IoHandlerAdapter * may be called first followed by this method. This depends on whether the client was trying to send data at the * time of the failure. * - * @param session The MINA session. - * * @todo Clarify: presumably exceptionCaught is called when the client is sending during a connection failure and * not otherwise? The above comment doesn't make that clear. */ - public void sessionClosed(IoSession session) + public void closed() { if (_connection.isClosed()) { @@ -327,7 +266,8 @@ public class AMQProtocolHandler extends IoHandlerAdapter { _logger.debug("sessionClose() not allowed to failover"); _connection.exceptionReceived(new AMQDisconnectedException( - "Server closed connection and reconnection " + "not permitted.", null)); + "Server closed connection and reconnection " + "not permitted.", + _stateManager.getLastException())); } else { @@ -350,43 +290,39 @@ public class AMQProtocolHandler extends IoHandlerAdapter failoverThread.start(); } - public void sessionIdle(IoSession session, IdleStatus status) throws Exception + @Override + public void readerIdle() { - _logger.debug("Protocol Session [" + this + ":" + session + "] idle: " + status); - if (IdleStatus.WRITER_IDLE.equals(status)) - { - // write heartbeat frame: - _logger.debug("Sent heartbeat"); - session.write(HeartbeatBody.FRAME); - HeartbeatDiagnostics.sent(); - } - else if (IdleStatus.READER_IDLE.equals(status)) - { - // failover: - HeartbeatDiagnostics.timeout(); - _logger.warn("Timed out while waiting for heartbeat from peer."); - session.close(); - } + _logger.debug("Protocol Session [" + this + "] idle: reader"); + // failover: + HeartbeatDiagnostics.timeout(); + _logger.warn("Timed out while waiting for heartbeat from peer."); + _networkDriver.close(); + } + + @Override + public void writerIdle() + { + _logger.debug("Protocol Session [" + this + "] idle: reader"); + writeFrame(HeartbeatBody.FRAME); + HeartbeatDiagnostics.sent(); } /** - * Invoked when any exception is thrown by a user IoHandler implementation or by MINA. If the cause is an - * IOException, MINA will close the connection automatically. - * - * @param session The MINA session. - * @param cause The exception that triggered this event. + * Invoked when any exception is thrown by the NetworkDriver */ - public void exceptionCaught(IoSession session, Throwable cause) + public void exception(Throwable cause) { + _logger.info("AS: HELLO"); if (_failoverState == FailoverState.NOT_STARTED) { // if (!(cause instanceof AMQUndeliveredException) && (!(cause instanceof AMQAuthenticationException))) if ((cause instanceof AMQConnectionClosedException) || cause instanceof IOException) { _logger.info("Exception caught therefore going to attempt failover: " + cause, cause); - // this will attemp failover - - sessionClosed(session); + // this will attempt failover + _networkDriver.close(); + closed(); } else { @@ -437,6 +373,7 @@ public class AMQProtocolHandler extends IoHandlerAdapter public void propagateExceptionToAllWaiters(Exception e) { getStateManager().error(e); + propagateExceptionToFrameListeners(e); } @@ -490,48 +427,84 @@ public class AMQProtocolHandler extends IoHandlerAdapter private static int _messageReceivedCount; - public void messageReceived(IoSession session, Object message) throws Exception - { - if (PROTOCOL_DEBUG) - { - _protocolLogger.info(String.format("RECV: [%s] %s", this, message)); - } - if(message instanceof AMQFrame) + @Override + public void received(ByteBuffer msg) + { + try { - final boolean debug = _logger.isDebugEnabled(); - final long msgNumber = ++_messageReceivedCount; + _readBytes += msg.remaining(); + final ArrayList dataBlocks = _codecFactory.getDecoder().decodeBuffer(msg); - if (debug && ((msgNumber % 1000) == 0)) + Job.fireAsynchEvent(_poolReference.getPool(), _readJob, new Event(new Runnable() { - _logger.debug("Received " + _messageReceivedCount + " protocol messages"); - } - - AMQFrame frame = (AMQFrame) message; - - final AMQBody bodyFrame = frame.getBodyFrame(); - - HeartbeatDiagnostics.received(bodyFrame instanceof HeartbeatBody); + @Override + public void run() + { + // Decode buffer - bodyFrame.handle(frame.getChannel(), _protocolSession); + for (AMQDataBlock message : dataBlocks) + { - _connection.bytesReceived(_protocolSession.getIoSession().getReadBytes()); + try + { + if (PROTOCOL_DEBUG) + { + _protocolLogger.info(String.format("RECV: [%s] %s", this, message)); + } + + if(message instanceof AMQFrame) + { + final boolean debug = _logger.isDebugEnabled(); + final long msgNumber = ++_messageReceivedCount; + + if (debug && ((msgNumber % 1000) == 0)) + { + _logger.debug("Received " + _messageReceivedCount + " protocol messages"); + } + + AMQFrame frame = (AMQFrame) message; + + final AMQBody bodyFrame = frame.getBodyFrame(); + + HeartbeatDiagnostics.received(bodyFrame instanceof HeartbeatBody); + + bodyFrame.handle(frame.getChannel(), _protocolSession); + + _connection.bytesReceived(_readBytes); + } + else if (message instanceof ProtocolInitiation) + { + // We get here if the server sends a response to our initial protocol header + // suggesting an alternate ProtocolVersion; the server will then close the + // connection. + ProtocolInitiation protocolInit = (ProtocolInitiation) message; + ProtocolVersion pv = protocolInit.checkVersion(); + getConnection().setProtocolVersion(pv); + + // get round a bug in old versions of qpid whereby the connection is not closed + _stateManager.changeState(AMQState.CONNECTION_CLOSED); + } + } + catch (Exception e) + { + e.printStackTrace(); + _logger.error("Exception processing frame", e); + propagateExceptionToFrameListeners(e); + exception(e); + } + } + } + })); } - else if (message instanceof ProtocolInitiation) + catch (Exception e) { - // We get here if the server sends a response to our initial protocol header - // suggesting an alternate ProtocolVersion; the server will then close the - // connection. - ProtocolInitiation protocolInit = (ProtocolInitiation) message; - ProtocolVersion pv = protocolInit.checkVersion(); - getConnection().setProtocolVersion(pv); - - // get round a bug in old versions of qpid whereby the connection is not closed - _stateManager.changeState(AMQState.CONNECTION_CLOSED); + propagateExceptionToFrameListeners(e); + exception(e); } } - public void methodBodyReceived(final int channelId, final AMQBody bodyFrame, IoSession session)//, final IoSession session) + public void methodBodyReceived(final int channelId, final AMQBody bodyFrame) throws AMQException { @@ -571,32 +544,13 @@ public class AMQProtocolHandler extends IoHandlerAdapter { propagateExceptionToFrameListeners(e); - exceptionCaught(session, e); + exception(e); } } private static int _messagesOut; - public void messageSent(IoSession session, Object message) throws Exception - { - if (PROTOCOL_DEBUG) - { - _protocolLogger.debug(String.format("SEND: [%s] %s", this, message)); - } - - final long sentMessages = _messagesOut++; - - final boolean debug = _logger.isDebugEnabled(); - - if (debug && ((sentMessages % 1000) == 0)) - { - _logger.debug("Sent " + _messagesOut + " protocol messages"); - } - - _connection.bytesSent(session.getWrittenBytes()); - } - public StateWaiter createWaiter(Set states) throws AMQException { return getStateManager().createWaiter(states); @@ -610,12 +564,34 @@ public class AMQProtocolHandler extends IoHandlerAdapter */ public void writeFrame(AMQDataBlock frame) { - _protocolSession.writeFrame(frame); + writeFrame(frame, false); } public void writeFrame(AMQDataBlock frame, boolean wait) { - _protocolSession.writeFrame(frame, wait); + ByteBuffer buf = frame.toNioByteBuffer(); + _writtenBytes += buf.remaining(); + _networkDriver.send(buf); + if (PROTOCOL_DEBUG) + { + _protocolLogger.debug(String.format("SEND: [%s] %s", this, frame)); + } + + final long sentMessages = _messagesOut++; + + final boolean debug = _logger.isDebugEnabled(); + + if (debug && ((sentMessages % 1000) == 0)) + { + _logger.debug("Sent " + _messagesOut + " protocol messages"); + } + + _connection.bytesSent(_writtenBytes); + + if (wait) + { + _networkDriver.flush(); + } } /** @@ -673,7 +649,7 @@ public class AMQProtocolHandler extends IoHandlerAdapter //FIXME: At this point here we should check or before add we should check _stateManager is in an open // state so as we don't check we are likely just to time out here as I believe is being seen in QPID-1255 } - _protocolSession.writeFrame(frame); + writeFrame(frame); return listener.blockForFrame(timeout); // When control resumes before this line, a reply will have been received @@ -723,20 +699,17 @@ public class AMQProtocolHandler extends IoHandlerAdapter final AMQFrame frame = body.generateFrame(0); //If the connection is already closed then don't do a syncWrite - if (getStateManager().getCurrentState().equals(AMQState.CONNECTION_CLOSED)) - { - _protocolSession.closeProtocolSession(false); - } - else + if (!getStateManager().getCurrentState().equals(AMQState.CONNECTION_CLOSED)) { try { syncWrite(frame, ConnectionCloseOkBody.class, timeout); - _protocolSession.closeProtocolSession(); + _networkDriver.close(); + closed(); } catch (AMQTimeoutException e) { - _protocolSession.closeProtocolSession(false); + closed(); } catch (FailoverException e) { @@ -748,13 +721,13 @@ public class AMQProtocolHandler extends IoHandlerAdapter /** @return the number of bytes read from this protocol session */ public long getReadBytes() { - return _protocolSession.getIoSession().getReadBytes(); + return _readBytes; } /** @return the number of bytes written to this protocol session */ public long getWrittenBytes() { - return _protocolSession.getIoSession().getWrittenBytes(); + return _writtenBytes; } public void failover(String host, int port) @@ -807,6 +780,7 @@ public class AMQProtocolHandler extends IoHandlerAdapter public void setStateManager(AMQStateManager stateManager) { _stateManager = stateManager; + _stateManager.setProtocolSession(_protocolSession); } public AMQProtocolSession getProtocolSession() @@ -843,4 +817,35 @@ public class AMQProtocolHandler extends IoHandlerAdapter { return _protocolSession.getProtocolVersion(); } + + public SocketAddress getRemoteAddress() + { + return _networkDriver.getRemoteAddress(); + } + + public SocketAddress getLocalAddress() + { + return _networkDriver.getLocalAddress(); + } + + public void setNetworkDriver(NetworkDriver driver) + { + _networkDriver = driver; + } + + /** @param delay delay in seconds (not ms) */ + void initHeartbeats(int delay) + { + if (delay > 0) + { + getNetworkDriver().setMaxWriteIdle(delay); + getNetworkDriver().setMaxReadIdle(HeartbeatConfig.CONFIG.getTimeout(delay)); + HeartbeatDiagnostics.init(delay, HeartbeatConfig.CONFIG.getTimeout(delay)); + } + } + + public NetworkDriver getNetworkDriver() + { + return _networkDriver; + } } diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolSession.java b/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolSession.java index 0e872170aa..cd049c24a1 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolSession.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolSession.java @@ -20,11 +20,6 @@ */ package org.apache.qpid.client.protocol; -import org.apache.commons.lang.StringUtils; -import org.apache.mina.common.CloseFuture; -import org.apache.mina.common.IdleStatus; -import org.apache.mina.common.IoSession; -import org.apache.mina.common.WriteFuture; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -33,6 +28,7 @@ import javax.security.sasl.SaslClient; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import org.apache.commons.lang.StringUtils; import org.apache.qpid.AMQException; import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.AMQSession; @@ -65,10 +61,6 @@ public class AMQProtocolSession implements AMQVersionAwareProtocolSession protected static final String SASL_CLIENT = "SASLClient"; - protected final IoSession _minaProtocolSession; - - protected WriteFuture _lastWriteFuture; - /** * The handler from which this session was created and which is used to handle protocol events. We send failover * events to the handler. @@ -102,28 +94,15 @@ public class AMQProtocolSession implements AMQVersionAwareProtocolSession protected final AMQConnection _connection; - private static final int FAST_CHANNEL_ACCESS_MASK = 0xFFFFFFF0; + private ConnectionTuneParameters _connectionTuneParameters; - public AMQProtocolSession(AMQProtocolHandler protocolHandler, IoSession protocolSession, AMQConnection connection) - { - _protocolHandler = protocolHandler; - _minaProtocolSession = protocolSession; - _minaProtocolSession.setAttachment(this); - // properties of the connection are made available to the event handlers - _minaProtocolSession.setAttribute(AMQ_CONNECTION, connection); - // fixme - real value needed - _minaProtocolSession.setWriteTimeout(LAST_WRITE_FUTURE_JOIN_TIMEOUT); - _protocolVersion = connection.getProtocolVersion(); - _methodDispatcher = ClientMethodDispatcherImpl.newMethodDispatcher(ProtocolVersion.getLatestSupportedVersion(), - this); - _connection = connection; + private SaslClient _saslClient; - } + private static final int FAST_CHANNEL_ACCESS_MASK = 0xFFFFFFF0; public AMQProtocolSession(AMQProtocolHandler protocolHandler, AMQConnection connection) { - _protocolHandler = protocolHandler; - _minaProtocolSession = null; + _protocolHandler = protocolHandler; _protocolVersion = connection.getProtocolVersion(); _methodDispatcher = ClientMethodDispatcherImpl.newMethodDispatcher(ProtocolVersion.getLatestSupportedVersion(), this); @@ -134,7 +113,7 @@ public class AMQProtocolSession implements AMQVersionAwareProtocolSession { // start the process of setting up the connection. This is the first place that // data is written to the server. - _minaProtocolSession.write(new ProtocolInitiation(_connection.getProtocolVersion())); + _protocolHandler.writeFrame(new ProtocolInitiation(_connection.getProtocolVersion())); } public String getClientID() @@ -175,14 +154,9 @@ public class AMQProtocolSession implements AMQVersionAwareProtocolSession return getAMQConnection().getPassword(); } - public IoSession getIoSession() - { - return _minaProtocolSession; - } - public SaslClient getSaslClient() { - return (SaslClient) _minaProtocolSession.getAttribute(SASL_CLIENT); + return _saslClient; } /** @@ -192,28 +166,21 @@ public class AMQProtocolSession implements AMQVersionAwareProtocolSession */ public void setSaslClient(SaslClient client) { - if (client == null) - { - _minaProtocolSession.removeAttribute(SASL_CLIENT); - } - else - { - _minaProtocolSession.setAttribute(SASL_CLIENT, client); - } + _saslClient = client; } public ConnectionTuneParameters getConnectionTuneParameters() { - return (ConnectionTuneParameters) _minaProtocolSession.getAttribute(CONNECTION_TUNE_PARAMETERS); + return _connectionTuneParameters; } public void setConnectionTuneParameters(ConnectionTuneParameters params) { - _minaProtocolSession.setAttribute(CONNECTION_TUNE_PARAMETERS, params); + _connectionTuneParameters = params; AMQConnection con = getAMQConnection(); con.setMaximumChannelCount(params.getChannelMax()); con.setMaximumFrameSize(params.getFrameMax()); - initHeartbeats((int) params.getHeartbeat()); + _protocolHandler.initHeartbeats((int) params.getHeartbeat()); } /** @@ -335,21 +302,12 @@ public class AMQProtocolSession implements AMQVersionAwareProtocolSession */ public void writeFrame(AMQDataBlock frame) { - writeFrame(frame, false); + _protocolHandler.writeFrame(frame); } public void writeFrame(AMQDataBlock frame, boolean wait) { - WriteFuture f = _minaProtocolSession.write(frame); - if (wait) - { - // fixme -- time out? - f.join(); - } - else - { - _lastWriteFuture = f; - } + _protocolHandler.writeFrame(frame, wait); } /** @@ -407,33 +365,12 @@ public class AMQProtocolSession implements AMQVersionAwareProtocolSession public AMQConnection getAMQConnection() { - return (AMQConnection) _minaProtocolSession.getAttribute(AMQ_CONNECTION); + return _connection; } - public void closeProtocolSession() + public void closeProtocolSession() throws AMQException { - closeProtocolSession(true); - } - - public void closeProtocolSession(boolean waitLast) - { - _logger.debug("Waiting for last write to join."); - if (waitLast && (_lastWriteFuture != null)) - { - _lastWriteFuture.join(LAST_WRITE_FUTURE_JOIN_TIMEOUT); - } - - _logger.debug("Closing protocol session"); - - final CloseFuture future = _minaProtocolSession.close(); - - // There is no recovery we can do if the join on the close failes so simply mark the connection CLOSED - // then wait for the connection to close. - // ritchiem: Could this release BlockingWaiters to early? The close has been done as much as possible so any - // error now shouldn't matter. - - _protocolHandler.getStateManager().changeState(AMQState.CONNECTION_CLOSED); - future.join(LAST_WRITE_FUTURE_JOIN_TIMEOUT); + _protocolHandler.closeConnection(0); } public void failover(String host, int port) @@ -449,22 +386,11 @@ public class AMQProtocolSession implements AMQVersionAwareProtocolSession id = _queueId++; } // get rid of / and : and ; from address for spec conformance - String localAddress = StringUtils.replaceChars(_minaProtocolSession.getLocalAddress().toString(), "/;:", ""); + String localAddress = StringUtils.replaceChars(_protocolHandler.getLocalAddress().toString(), "/;:", ""); return new AMQShortString("tmp_" + localAddress + "_" + id); } - /** @param delay delay in seconds (not ms) */ - void initHeartbeats(int delay) - { - if (delay > 0) - { - _minaProtocolSession.setIdleTime(IdleStatus.WRITER_IDLE, delay); - _minaProtocolSession.setIdleTime(IdleStatus.READER_IDLE, HeartbeatConfig.CONFIG.getTimeout(delay)); - HeartbeatDiagnostics.init(delay, HeartbeatConfig.CONFIG.getTimeout(delay)); - } - } - public void confirmConsumerCancelled(int channelId, AMQShortString consumerTag) { final AMQSession session = getSession(channelId); @@ -530,7 +456,7 @@ public class AMQProtocolSession implements AMQVersionAwareProtocolSession public void methodFrameReceived(final int channel, final AMQMethodBody amqMethodBody) throws AMQException { - _protocolHandler.methodBodyReceived(channel, amqMethodBody, _minaProtocolSession); + _protocolHandler.methodBodyReceived(channel, amqMethodBody); } public void notifyError(Exception error) diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/transport/SocketTransportConnection.java b/qpid/java/client/src/main/java/org/apache/qpid/client/transport/SocketTransportConnection.java index b2f7ae8395..77c9c40e82 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/transport/SocketTransportConnection.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/transport/SocketTransportConnection.java @@ -24,23 +24,33 @@ import org.apache.mina.common.ByteBuffer; import org.apache.mina.common.ConnectFuture; import org.apache.mina.common.IoConnector; import org.apache.mina.common.SimpleByteBufferAllocator; +import org.apache.mina.filter.SSLFilter; import org.apache.mina.transport.socket.nio.ExistingSocketConnector; import org.apache.mina.transport.socket.nio.SocketConnectorConfig; import org.apache.mina.transport.socket.nio.SocketSessionConfig; +import org.apache.qpid.client.SSLConfiguration; import org.apache.qpid.client.protocol.AMQProtocolHandler; import org.apache.qpid.jms.BrokerDetails; import org.apache.qpid.pool.ReadWriteThreadModel; +import org.apache.qpid.ssl.SSLContextFactory; +import org.apache.qpid.transport.network.mina.MINANetworkDriver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import sun.net.InetAddressCachePolicy; + import java.io.IOException; +import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; +import java.security.GeneralSecurityException; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import javax.net.ssl.SSLEngine; + public class SocketTransportConnection implements ITransportConnection { private static final Logger _logger = LoggerFactory.getLogger(SocketTransportConnection.class); @@ -71,61 +81,27 @@ public class SocketTransportConnection implements ITransportConnection } final IoConnector ioConnector = _socketConnectorFactory.newSocketConnector(); - SocketConnectorConfig cfg = (SocketConnectorConfig) ioConnector.getDefaultConfig(); - - // if we do not use our own thread model we get the MINA default which is to use - // its own leader-follower model - boolean readWriteThreading = Boolean.getBoolean("amqj.shared_read_write_pool"); - if (readWriteThreading) - { - cfg.setThreadModel(ReadWriteThreadModel.getInstance()); - } - - SocketSessionConfig scfg = (SocketSessionConfig) cfg.getSessionConfig(); - scfg.setTcpNoDelay("true".equalsIgnoreCase(System.getProperty("amqj.tcpNoDelay", "true"))); - scfg.setSendBufferSize(Integer.getInteger("amqj.sendBufferSize", DEFAULT_BUFFER_SIZE)); - _logger.info("send-buffer-size = " + scfg.getSendBufferSize()); - scfg.setReceiveBufferSize(Integer.getInteger("amqj.receiveBufferSize", DEFAULT_BUFFER_SIZE)); - _logger.info("recv-buffer-size = " + scfg.getReceiveBufferSize()); - final InetSocketAddress address; if (brokerDetail.getTransport().equals(BrokerDetails.SOCKET)) { address = null; - - Socket socket = TransportConnection.removeOpenSocket(brokerDetail.getHost()); - - if (socket != null) - { - _logger.info("Using existing Socket:" + socket); - - ((ExistingSocketConnector) ioConnector).setOpenSocket(socket); - } - else - { - throw new IllegalArgumentException("Active Socket must be provided for broker " + - "with 'socket://' transport:" + brokerDetail); - } } else { address = new InetSocketAddress(brokerDetail.getHost(), brokerDetail.getPort()); _logger.info("Attempting connection to " + address); } - - - ConnectFuture future = ioConnector.connect(address, protocolHandler); - - // wait for connection to complete - if (future.join(brokerDetail.getTimeout())) - { - // we call getSession which throws an IOException if there has been an error connecting - future.getSession(); - } - else + + SSLConfiguration sslConfig = protocolHandler.getConnection().getSSLConfiguration(); + SSLContextFactory sslFactory = null; + if (sslConfig != null) { - throw new IOException("Timeout waiting for connection."); + sslFactory = new SSLContextFactory(sslConfig.getKeystorePath(), sslConfig.getKeystorePassword(), sslConfig.getCertType()); } + + MINANetworkDriver driver = new MINANetworkDriver(ioConnector); + driver.open(brokerDetail.getPort(), address.getAddress(), protocolHandler, null, sslFactory); + protocolHandler.setNetworkDriver(driver); } } diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/transport/TransportConnection.java b/qpid/java/client/src/main/java/org/apache/qpid/client/transport/TransportConnection.java index 4ff24c3607..45194750dc 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/transport/TransportConnection.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/transport/TransportConnection.java @@ -79,7 +79,7 @@ public class TransportConnection return _openSocketRegister.remove(socketID); } - public static synchronized ITransportConnection getInstance(BrokerDetails details) throws AMQTransportConnectionException + public static synchronized ITransportConnection getInstance(final BrokerDetails details) throws AMQTransportConnectionException { int transport = getTransport(details.getTransport()); @@ -95,7 +95,22 @@ public class TransportConnection { public IoConnector newSocketConnector() { - return new ExistingSocketConnector(1,new QpidThreadExecutor()); + ExistingSocketConnector connector = new ExistingSocketConnector(1,new QpidThreadExecutor()); + + Socket socket = TransportConnection.removeOpenSocket(details.getHost()); + + if (socket != null) + { + _logger.info("Using existing Socket:" + socket); + + ((ExistingSocketConnector) connector).setOpenSocket(socket); + } + else + { + throw new IllegalArgumentException("Active Socket must be provided for broker " + + "with 'socket://' transport:" + details); + } + return connector; } }); case TCP: diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/transport/VmPipeTransportConnection.java b/qpid/java/client/src/main/java/org/apache/qpid/client/transport/VmPipeTransportConnection.java index dca6efba67..3de6f9b9ea 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/transport/VmPipeTransportConnection.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/transport/VmPipeTransportConnection.java @@ -28,6 +28,7 @@ import org.apache.mina.transport.vmpipe.VmPipeConnector; import org.apache.qpid.client.protocol.AMQProtocolHandler; import org.apache.qpid.jms.BrokerDetails; import org.apache.qpid.pool.ReadWriteThreadModel; +import org.apache.qpid.transport.network.mina.MINANetworkDriver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -39,6 +40,8 @@ public class VmPipeTransportConnection implements ITransportConnection private static int _port; + private MINANetworkDriver _networkDriver; + public VmPipeTransportConnection(int port) { _port = port; @@ -47,16 +50,16 @@ public class VmPipeTransportConnection implements ITransportConnection public void connect(AMQProtocolHandler protocolHandler, BrokerDetails brokerDetail) throws IOException { final VmPipeConnector ioConnector = new QpidVmPipeConnector(); - final IoServiceConfig cfg = ioConnector.getDefaultConfig(); - - cfg.setThreadModel(ReadWriteThreadModel.getInstance()); final VmPipeAddress address = new VmPipeAddress(_port); _logger.info("Attempting connection to " + address); - ConnectFuture future = ioConnector.connect(address, protocolHandler); + _networkDriver = new MINANetworkDriver(ioConnector, protocolHandler); + protocolHandler.setNetworkDriver(_networkDriver); + ConnectFuture future = ioConnector.connect(address, _networkDriver); // wait for connection to complete future.join(); // we call getSession which throws an IOException if there has been an error connecting future.getSession(); + _networkDriver.setProtocolEngine(protocolHandler); } } diff --git a/qpid/java/client/src/test/java/org/apache/qpid/client/protocol/AMQProtocolHandlerTest.java b/qpid/java/client/src/test/java/org/apache/qpid/client/protocol/AMQProtocolHandlerTest.java index fc7f8148f0..f520a21ba0 100644 --- a/qpid/java/client/src/test/java/org/apache/qpid/client/protocol/AMQProtocolHandlerTest.java +++ b/qpid/java/client/src/test/java/org/apache/qpid/client/protocol/AMQProtocolHandlerTest.java @@ -27,6 +27,7 @@ import org.apache.qpid.framing.AMQMethodBody; import org.apache.qpid.framing.amqp_8_0.BasicRecoverOkBodyImpl; import org.apache.qpid.AMQException; import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.transport.TestNetworkDriver; import org.apache.qpid.client.MockAMQConnection; import org.apache.qpid.client.AMQAuthenticationException; import org.apache.qpid.client.state.AMQState; @@ -72,9 +73,7 @@ public class AMQProtocolHandlerTest extends TestCase { //Create a new ProtocolHandler with a fake connection. _handler = new AMQProtocolHandler(new MockAMQConnection("amqp://guest:guest@client/test?brokerlist='vm://:1'")); - - _handler.sessionCreated(new MockIoSession()); - + _handler.setNetworkDriver(new TestNetworkDriver()); AMQBody body = BasicRecoverOkBodyImpl.getFactory().newInstance(null, 1); _blockFrame = new AMQFrame(0, body); diff --git a/qpid/java/common/src/main/java/org/apache/qpid/pool/Job.java b/qpid/java/common/src/main/java/org/apache/qpid/pool/Job.java index 4e4192dbe3..15d1c20ff1 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/pool/Job.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/pool/Job.java @@ -21,9 +21,13 @@ package org.apache.qpid.pool; import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.atomic.AtomicBoolean; import org.apache.mina.common.IoSession; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * A Job is a continuation that batches together other continuations, specifically {@link Event}s, into one continuation. @@ -66,6 +70,8 @@ public class Job implements ReadWriteRunnable private final boolean _readJob; + private final static Logger _logger = LoggerFactory.getLogger(Job.class); + /** * Creates a new job that aggregates many continuations together. * @@ -181,4 +187,38 @@ public class Job implements ReadWriteRunnable public void notCompleted(final Job job); } + + /** + * Adds an {@link Event} to a {@link Job}, triggering the execution of the job if it is not already running. + * + * @param job The job. + * @param event The event to hand off asynchronously. + */ + public static void fireAsynchEvent(ExecutorService pool, Job job, Event event) + { + + job.add(event); + + + if(pool == null) + { + return; + } + + // rather than perform additional checks on pool to check that it hasn't shutdown. + // catch the RejectedExecutionException that will result from executing on a shutdown pool + if (job.activate()) + { + try + { + pool.execute(job); + } + catch(RejectedExecutionException e) + { + _logger.warn("Thread pool shutdown while tasks still outstanding"); + } + } + + } + } diff --git a/qpid/java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngine.java b/qpid/java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngine.java index 8ab845454a..5bfc189b02 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngine.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngine.java @@ -37,6 +37,9 @@ public interface ProtocolEngine extends Receiver // Returns the remote address of the NetworkDriver SocketAddress getRemoteAddress(); + + // Returns the local address of the NetworkDriver + SocketAddress getLocalAddress(); // Returns number of bytes written long getWrittenBytes(); diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/NetworkDriver.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/NetworkDriver.java index 34b0ef65be..86af97bf7e 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/transport/NetworkDriver.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/NetworkDriver.java @@ -24,8 +24,6 @@ import java.net.BindException; import java.net.InetAddress; import java.net.SocketAddress; -import javax.net.ssl.SSLEngine; - import org.apache.qpid.protocol.ProtocolEngine; import org.apache.qpid.protocol.ProtocolEngineFactory; import org.apache.qpid.ssl.SSLContextFactory; @@ -33,13 +31,14 @@ import org.apache.qpid.ssl.SSLContextFactory; public interface NetworkDriver extends Sender { // Creates a NetworkDriver which attempts to connect to destination on port and attaches the ProtocolEngine to - // it using the SSLEngine if provided + // it using the SSLContextFactory if provided void open(int port, InetAddress destination, ProtocolEngine engine, - NetworkDriverConfiguration config, SSLEngine sslEngine) + NetworkDriverConfiguration config, SSLContextFactory sslFactory) throws OpenException; // listens for incoming connections on the specified ports and address and creates a new NetworkDriver which - // processes incoming connections with ProtocolEngines created from factory using the SSLEngine if provided + // processes incoming connections with ProtocolEngines and SSLEngines created from the factories + // (in the case of an SSLContextFactory, if provided) void bind (int port, InetAddress[] addresses, ProtocolEngineFactory protocolFactory, NetworkDriverConfiguration config, SSLContextFactory sslFactory) throws BindException; diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/OpenException.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/OpenException.java index 8628b8c7aa..68fbb5e8ec 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/transport/OpenException.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/OpenException.java @@ -21,7 +21,9 @@ package org.apache.qpid.transport; -public class OpenException extends Exception +import java.io.IOException; + +public class OpenException extends IOException { public OpenException(String string, Throwable lastException) diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java index e34103a944..7cc5f8e442 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java @@ -33,6 +33,7 @@ import javax.net.ssl.SSLEngine; import org.apache.mina.common.ConnectFuture; import org.apache.mina.common.IdleStatus; import org.apache.mina.common.IoAcceptor; +import org.apache.mina.common.IoConnector; import org.apache.mina.common.IoFilterChain; import org.apache.mina.common.IoHandlerAdapter; import org.apache.mina.common.IoSession; @@ -71,7 +72,7 @@ public class MINANetworkDriver extends IoHandlerAdapter implements NetworkDriver private int _processors = 4; private boolean _executorPool = false; private SSLContextFactory _sslFactory = null; - private SocketConnector _socketConnector; + private IoConnector _socketConnector; private IoAcceptor _acceptor; private IoSession _ioSession; private ProtocolEngineFactory _factory; @@ -101,6 +102,7 @@ public class MINANetworkDriver extends IoHandlerAdapter implements NetworkDriver _protectIO = protectIO; _protocolEngine = protocolEngine; _ioSession = session; + _ioSession.setAttachment(_protocolEngine); } public MINANetworkDriver() @@ -108,6 +110,17 @@ public class MINANetworkDriver extends IoHandlerAdapter implements NetworkDriver } + public MINANetworkDriver(IoConnector ioConnector) + { + _socketConnector = ioConnector; + } + + public MINANetworkDriver(IoConnector ioConnector, ProtocolEngine engine) + { + _socketConnector = ioConnector; + _protocolEngine = engine; + } + public void bind(int port, InetAddress[] addresses, ProtocolEngineFactory factory, NetworkDriverConfiguration config, SSLContextFactory sslFactory) throws BindException { @@ -188,8 +201,13 @@ public class MINANetworkDriver extends IoHandlerAdapter implements NetworkDriver public void open(int port, InetAddress destination, ProtocolEngine engine, NetworkDriverConfiguration config, - SSLEngine sslEngine) throws OpenException + SSLContextFactory sslFactory) throws OpenException { + if (sslFactory != null) + { + _sslFactory = sslFactory; + } + if (_useNIO) { _socketConnector = new MultiThreadSocketConnector(1, new QpidThreadExecutor()); @@ -207,7 +225,6 @@ public class MINANetworkDriver extends IoHandlerAdapter implements NetworkDriver { org.apache.mina.common.ByteBuffer.setAllocator(new SimpleByteBufferAllocator()); } - SocketConnectorConfig cfg = (SocketConnectorConfig) _socketConnector.getDefaultConfig(); @@ -229,7 +246,11 @@ public class MINANetworkDriver extends IoHandlerAdapter implements NetworkDriver // one SocketConnector per connection at the moment anyway). This allows // short-running // clients (like unit tests) to complete quickly. - _socketConnector.setWorkerTimeout(0); + if (_socketConnector instanceof SocketConnector) + { + ((SocketConnector) _socketConnector).setWorkerTimeout(0); + } + ConnectFuture future = _socketConnector.connect(new InetSocketAddress(destination, port), this, cfg); future.join(); if (!future.isConnected()) @@ -333,56 +354,54 @@ public class MINANetworkDriver extends IoHandlerAdapter implements NetworkDriver public void sessionCreated(IoSession protocolSession) throws Exception { - if (_acceptingConnections) + // Configure the session with SSL if necessary + SessionUtil.initialize(protocolSession); + if (_executorPool) { - // Configure the session with SSL if necessary - SessionUtil.initialize(protocolSession); - if (_executorPool) + if (_sslFactory != null) { - if (_sslFactory != null) - { - protocolSession.getFilterChain().addAfter("AsynchronousReadFilter", "sslFilter", - new SSLFilter(_sslFactory.buildServerContext())); - } + protocolSession.getFilterChain().addAfter("AsynchronousReadFilter", "sslFilter", + new SSLFilter(_sslFactory.buildServerContext())); } - else + } + else + { + if (_sslFactory != null) { - if (_sslFactory != null) - { - protocolSession.getFilterChain().addBefore("protocolFilter", "sslFilter", - new SSLFilter(_sslFactory.buildServerContext())); - } + protocolSession.getFilterChain().addBefore("protocolFilter", "sslFilter", + new SSLFilter(_sslFactory.buildServerContext())); } + } + // Do we want to have read/write buffer limits? + if (_protectIO) + { + //Add IO Protection Filters + IoFilterChain chain = protocolSession.getFilterChain(); - // Do we want to have read/write buffer limits? - if (_protectIO) - { - //Add IO Protection Filters - IoFilterChain chain = protocolSession.getFilterChain(); + protocolSession.getFilterChain().addLast("tempExecutorFilterForFilterBuilder", new ExecutorFilter()); - protocolSession.getFilterChain().addLast("tempExecutorFilterForFilterBuilder", new ExecutorFilter()); + ReadThrottleFilterBuilder readfilter = new ReadThrottleFilterBuilder(); + readfilter.setMaximumConnectionBufferSize(_config.getReceiveBufferSize()); + readfilter.attach(chain); - ReadThrottleFilterBuilder readfilter = new ReadThrottleFilterBuilder(); - readfilter.setMaximumConnectionBufferSize(_config.getReceiveBufferSize()); - readfilter.attach(chain); + WriteBufferLimitFilterBuilder writefilter = new WriteBufferLimitFilterBuilder(); + writefilter.setMaximumConnectionBufferSize(_config.getSendBufferSize()); + writefilter.attach(chain); - WriteBufferLimitFilterBuilder writefilter = new WriteBufferLimitFilterBuilder(); - writefilter.setMaximumConnectionBufferSize(_config.getSendBufferSize()); - writefilter.attach(chain); + protocolSession.getFilterChain().remove("tempExecutorFilterForFilterBuilder"); + } - protocolSession.getFilterChain().remove("tempExecutorFilterForFilterBuilder"); - } - - if (_ioSession == null) - { - _ioSession = protocolSession; - } - + if (_ioSession == null) + { + _ioSession = protocolSession; + } + + if (_acceptingConnections) + { // Set up the protocol engine ProtocolEngine protocolEngine = _factory.newProtocolEngine(this); MINANetworkDriver newDriver = new MINANetworkDriver(_useNIO, _processors, _executorPool, _protectIO, protocolEngine, protocolSession); protocolEngine.setNetworkDriver(newDriver); - protocolSession.setAttachment(protocolEngine); } } @@ -409,4 +428,13 @@ public class MINANetworkDriver extends IoHandlerAdapter implements NetworkDriver _acceptingConnections = acceptingConnections; } + public void setProtocolEngine(ProtocolEngine protocolEngine) + { + _protocolEngine = protocolEngine; + if (_ioSession != null) + { + _ioSession.setAttachment(protocolEngine); + } + } + } diff --git a/qpid/java/common/src/test/java/org/apache/qpid/transport/TestNetworkDriver.java b/qpid/java/common/src/test/java/org/apache/qpid/transport/TestNetworkDriver.java new file mode 100644 index 0000000000..a4c4b59cdd --- /dev/null +++ b/qpid/java/common/src/test/java/org/apache/qpid/transport/TestNetworkDriver.java @@ -0,0 +1,122 @@ +/* + * + * 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.transport; + +import java.net.BindException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.nio.ByteBuffer; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import org.apache.qpid.protocol.ProtocolEngine; +import org.apache.qpid.protocol.ProtocolEngineFactory; +import org.apache.qpid.ssl.SSLContextFactory; + +/** + * Test implementation of IoSession, which is required for some tests. Methods not being used are not implemented, + * so if this class is being used and some methods are to be used, then please update those. + */ +public class TestNetworkDriver implements NetworkDriver +{ + private final ConcurrentMap attributes = new ConcurrentHashMap(); + private String _remoteAddress = "127.0.0.1"; + private String _localAddress = "127.0.0.1"; + private int _port = 1; + + public TestNetworkDriver() + { + } + + public void setRemoteAddress(String string) + { + this._remoteAddress = string; + } + + public void setPort(int _port) + { + this._port = _port; + } + + public int getPort() + { + return _port; + } + + public void bind(int port, InetAddress[] addresses, ProtocolEngineFactory protocolFactory, + NetworkDriverConfiguration config, SSLContextFactory sslFactory) throws BindException + { + + } + + public SocketAddress getLocalAddress() + { + return new InetSocketAddress(_localAddress, _port); + } + + public SocketAddress getRemoteAddress() + { + return new InetSocketAddress(_remoteAddress, _port); + } + + public void open(int port, InetAddress destination, ProtocolEngine engine, NetworkDriverConfiguration config, + SSLContextFactory sslFactory) throws OpenException + { + + } + + public void setMaxReadIdle(int idleTime) + { + + } + + public void setMaxWriteIdle(int idleTime) + { + + } + + public void close() + { + + } + + public void flush() + { + + } + + public void send(ByteBuffer msg) + { + + } + + public void setIdleTimeout(long l) + { + + } + + public void setLocalAddress(String localAddress) + { + _localAddress = localAddress; + } + +} diff --git a/qpid/java/common/src/test/java/org/apache/qpid/transport/network/mina/MINANetworkDriverTest.java b/qpid/java/common/src/test/java/org/apache/qpid/transport/network/mina/MINANetworkDriverTest.java index 6024875cf5..5500ff9d4b 100644 --- a/qpid/java/common/src/test/java/org/apache/qpid/transport/network/mina/MINANetworkDriverTest.java +++ b/qpid/java/common/src/test/java/org/apache/qpid/transport/network/mina/MINANetworkDriverTest.java @@ -382,6 +382,18 @@ public class MINANetworkDriverTest extends TestCase return null; } } + + public SocketAddress getLocalAddress() + { + if (_driver != null) + { + return _driver.getLocalAddress(); + } + else + { + return null; + } + } public long getWrittenBytes() { @@ -459,6 +471,7 @@ public class MINANetworkDriverTest extends TestCase { return _closed; } + } private class EchoProtocolEngine extends CountingProtocolEngine diff --git a/qpid/java/systests/build.xml b/qpid/java/systests/build.xml index ac3c77e4a3..34a360ecad 100644 --- a/qpid/java/systests/build.xml +++ b/qpid/java/systests/build.xml @@ -20,7 +20,7 @@ nn - or more contributor license agreements. See the NOTICE file --> - + diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/SimpleACLTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/SimpleACLTest.java index b5c0a87b0f..f402522a19 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/SimpleACLTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/SimpleACLTest.java @@ -22,6 +22,9 @@ package org.apache.qpid.server.security.acl; import junit.framework.TestCase; + +import org.apache.log4j.BasicConfigurator; +import org.apache.log4j.Logger; import org.apache.qpid.client.transport.TransportConnection; import org.apache.qpid.client.*; import org.apache.qpid.framing.AMQShortString; @@ -34,11 +37,17 @@ import org.apache.qpid.url.URLSyntaxException; import javax.jms.*; import javax.jms.IllegalStateException; + import java.io.File; +import java.util.ArrayList; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; -public class SimpleACLTest extends QpidTestCase implements ConnectionListener +public class SimpleACLTest extends QpidTestCase implements ConnectionListener, ExceptionListener { private String BROKER = "vm://:"+ApplicationRegistry.DEFAULT_INSTANCE;//"tcp://localhost:5672"; + private ArrayList _thrownExceptions = new ArrayList(); + private CountDownLatch _awaitError = new CountDownLatch(51); public void setUp() throws Exception { @@ -268,7 +277,7 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener } } - public void testClientPublishInvalidQueueSuccess() throws AMQException, URLSyntaxException, JMSException + public void testClientPublishInvalidQueueSuccess() throws AMQException, URLSyntaxException, JMSException, InterruptedException { try { @@ -276,41 +285,38 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener ((AMQConnection) conn).setConnectionListener(this); - Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + Session session = conn.createSession(true, Session.AUTO_ACKNOWLEDGE); conn.start(); - + conn.setExceptionListener(this); MessageProducer sender = ((AMQSession) session).createProducer(null); - Queue queue = session.createQueue("Invalid"); - + Queue queue = session.createQueue("NewQueueThatIDoNotHaveRightsToPublishToo"); + // Send a message that we will wait to be sent, this should give the broker time to close the connection // 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, session.createTextMessage("test"), DeliveryMode.NON_PERSISTENT, 0, 0L, false, false, true); - // Test the connection with a valid consumer - // This may fail as the session may be closed before the queue or the consumer created. - Queue temp = session.createTemporaryQueue(); - - session.createConsumer(temp).close(); - - //Connection should now be closed and will throw the exception caused by the above send - conn.close(); - - fail("Close is not expected to succeed."); + _awaitError.await(1, TimeUnit.SECONDS); } catch (JMSException e) { - Throwable cause = e.getLinkedException(); - if (!(cause instanceof AMQAuthenticationException)) + fail("Unknown exception thrown:" + e.getMessage()); + } + boolean foundCorrectException = false; + for (Exception cause : _thrownExceptions) + { + if (cause instanceof JMSException) { - e.printStackTrace(); + if (((JMSException) cause).getLinkedException() instanceof AMQAuthenticationException) + { + foundCorrectException = true; + } } - assertEquals("Incorrect exception", AMQAuthenticationException.class, cause.getClass()); - assertEquals("Incorrect error code thrown", 403, ((AMQAuthenticationException) cause).getErrorCode().getCode()); } + assertTrue("Did not get AMQAuthenticationException thrown", foundCorrectException); } public void testServerConsumeFromNamedQueueValid() throws AMQException, URLSyntaxException @@ -657,4 +663,10 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener public void failoverComplete() { } + + public void onException(JMSException arg0) + { + _thrownExceptions.add(arg0); + _awaitError.countDown(); + } } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/protocol/AMQProtocolSessionTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/protocol/AMQProtocolSessionTest.java index 91cb37e455..b99cd239d3 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/protocol/AMQProtocolSessionTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/protocol/AMQProtocolSessionTest.java @@ -20,27 +20,27 @@ */ package org.apache.qpid.test.unit.client.protocol; -import org.apache.mina.common.IoSession; import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.protocol.AMQProtocolHandler; import org.apache.qpid.client.protocol.AMQProtocolSession; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.test.utils.QpidTestCase; -import org.apache.qpid.test.utils.protocol.TestIoSession; +import org.apache.qpid.transport.TestNetworkDriver; +import org.apache.qpid.transport.NetworkDriver; public class AMQProtocolSessionTest extends QpidTestCase { private static class AMQProtSession extends AMQProtocolSession { - public AMQProtSession(AMQProtocolHandler protocolHandler, IoSession protocolSession, AMQConnection connection) + public AMQProtSession(AMQProtocolHandler protocolHandler, AMQConnection connection) { - super(protocolHandler,protocolSession,connection); + super(protocolHandler,connection); } - public TestIoSession getMinaProtocolSession() + public TestNetworkDriver getNetworkDriver() { - return (TestIoSession) _minaProtocolSession; + return (TestNetworkDriver) _protocolHandler.getNetworkDriver(); } public AMQShortString genQueueName() @@ -63,8 +63,11 @@ public class AMQProtocolSessionTest extends QpidTestCase { super.setUp(); + AMQConnection con = (AMQConnection) getConnection("guest", "guest"); + AMQProtocolHandler protocolHandler = new AMQProtocolHandler(con); + protocolHandler.setNetworkDriver(new TestNetworkDriver()); //don't care about the values set here apart from the dummy IoSession - _testSession = new AMQProtSession(null,new TestIoSession(), (AMQConnection) getConnection("guest", "guest")); + _testSession = new AMQProtSession(protocolHandler , con); //initialise addresses for test and expected results _port = 123; @@ -75,32 +78,32 @@ public class AMQProtocolSessionTest extends QpidTestCase _validAddress = "abc"; _generatedAddress_3 = "tmp_abc123_3"; } - +/* public void testGenerateQueueName() { AMQShortString testAddress; //test address with / and ; chars which generateQueueName should removeKey - _testSession.getMinaProtocolSession().setStringLocalAddress(_brokenAddress); - _testSession.getMinaProtocolSession().setLocalPort(_port); + _testSession.getNetworkDriver().setLocalAddress(_brokenAddress); + _testSession.getNetworkDriver().setPort(_port); testAddress = _testSession.genQueueName(); assertEquals("Failure when generating a queue exchange from an address with special chars",_generatedAddress,testAddress.toString()); //test empty address - _testSession.getMinaProtocolSession().setStringLocalAddress(_emptyAddress); + _testSession.getNetworkDriver().setLocalAddress(_emptyAddress); testAddress = _testSession.genQueueName(); assertEquals("Failure when generating a queue exchange from an empty address",_generatedAddress_2,testAddress.toString()); //test address with no special chars - _testSession.getMinaProtocolSession().setStringLocalAddress(_validAddress); + _testSession.getNetworkDriver().setStringLocalAddress(_validAddress); testAddress = _testSession.genQueueName(); assertEquals("Failure when generating a queue exchange from an address with no special chars",_generatedAddress_3,testAddress.toString()); } - +*/ protected void tearDown() throws Exception { _testSession = null; -- cgit v1.2.1 From 23ed5eb6dbd7cf39cf18b308a0d4e339c4db1c83 Mon Sep 17 00:00:00 2001 From: Aidan Skinner Date: Wed, 16 Sep 2009 10:07:44 +0000 Subject: QPID-2106: Don't close connections if the broker has asked it to close and there's still stuff to process. Let the cleanup thread do that so that publishes which are denied don't result in instant connection death. git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/java-network-refactor@815705 13f79535-47bb-0310-9956-ffa450edef68 --- .../qpid/server/connection/ConnectionRegistry.java | 8 +++++ .../qpid/server/protocol/AMQProtocolEngine.java | 34 ++++++++++++++-------- .../qpid/server/protocol/AMQProtocolSession.java | 2 ++ .../qpid/server/virtualhost/VirtualHost.java | 8 +++++ 4 files changed, 40 insertions(+), 12 deletions(-) (limited to 'qpid/java') diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/connection/ConnectionRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/connection/ConnectionRegistry.java index 71e07172ed..7b50a2e3ad 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/connection/ConnectionRegistry.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/connection/ConnectionRegistry.java @@ -44,6 +44,14 @@ public class ConnectionRegistry implements IConnectionRegistry { } + + public void expireClosedChannels() + { + for (AMQProtocolSession connection : _registry) + { + connection.closeIfLingeringClosedChannels(); + } + } /** Close all of the currently open connections. */ public void close() throws AMQException diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java index 16ebc76185..4f396015a2 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java @@ -29,6 +29,8 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.atomic.AtomicLong; @@ -135,7 +137,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol private FieldTable _clientProperties; private final List _taskList = new CopyOnWriteArrayList(); - private List _closingChannelsList = new CopyOnWriteArrayList(); + private Map _closingChannelsList = new ConcurrentHashMap(); private ProtocolOutputConverter _protocolOutputConverter; private Principal _authorizedID; private MethodDispatcher _dispatcher; @@ -293,12 +295,8 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol } else { - if (_logger.isInfoEnabled()) - { - _logger.info("Channel[" + channelId + "] awaiting closure. Should close socket as client did not close-ok :" + frame); - } - - closeProtocolSession(); + // The channel has been told to close, we don't process any more frames until + // it's closed. return; } } @@ -513,7 +511,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol public boolean channelAwaitingClosure(int channelId) { - return !_closingChannelsList.isEmpty() && _closingChannelsList.contains(channelId); + return !_closingChannelsList.isEmpty() && _closingChannelsList.containsKey(channelId); } public void addChannel(AMQChannel channel) throws AMQException @@ -525,7 +523,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol final int channelId = channel.getChannelId(); - if (_closingChannelsList.contains(channelId)) + if (_closingChannelsList.containsKey(channelId)) { throw new AMQException("Session is marked awaiting channel close"); } @@ -632,7 +630,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol private void markChannelAwaitingCloseOk(int channelId) { - _closingChannelsList.add(channelId); + _closingChannelsList.put(channelId, System.currentTimeMillis()); } /** @@ -1023,7 +1021,19 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol { return (_clientVersion == null) ? null : _clientVersion.toString(); } - - + + @Override + public void closeIfLingeringClosedChannels() + { + for (Entryid : _closingChannelsList.entrySet()) + { + if (id.getValue() + 30000 > System.currentTimeMillis()) + { + // We have a channel that we closed 30 seconds ago. Client's dead, kill the connection + _logger.error("Closing connection as channel was closed more than 30 seconds ago and no ChannelCloseOk has been processed"); + closeProtocolSession(); + } + } + } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java index b0bef04354..b16ed01c79 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java @@ -225,5 +225,7 @@ public interface AMQProtocolSession extends AMQVersionAwareProtocolSession void commitTransactions(AMQChannel channel) throws AMQException; List getChannels(); + + void closeIfLingeringClosedChannels(); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java index fa6b2285eb..aec437b700 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java @@ -267,6 +267,14 @@ public class VirtualHost implements Accessable _houseKeepingTimer.scheduleAtFixedRate(new RemoveExpiredMessagesTask(), period / 2, period); + + class ForceChannelClosuresTask extends TimerTask + { + public void run() + { + _connectionRegistry.expireClosedChannels(); + } + } } } -- cgit v1.2.1 From e2318508673d16d54b544ca589357003b7cfecc1 Mon Sep 17 00:00:00 2001 From: Aidan Skinner Date: Wed, 16 Sep 2009 10:17:20 +0000 Subject: QPID-2105: Merging the patch didn't uncomment this test, stoopid git. git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/java-network-refactor@815708 13f79535-47bb-0310-9956-ffa450edef68 --- .../qpid/test/unit/client/protocol/AMQProtocolSessionTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'qpid/java') diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/protocol/AMQProtocolSessionTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/protocol/AMQProtocolSessionTest.java index b99cd239d3..7a27925a36 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/protocol/AMQProtocolSessionTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/protocol/AMQProtocolSessionTest.java @@ -78,7 +78,7 @@ public class AMQProtocolSessionTest extends QpidTestCase _validAddress = "abc"; _generatedAddress_3 = "tmp_abc123_3"; } -/* + public void testGenerateQueueName() { AMQShortString testAddress; @@ -97,13 +97,13 @@ public class AMQProtocolSessionTest extends QpidTestCase assertEquals("Failure when generating a queue exchange from an empty address",_generatedAddress_2,testAddress.toString()); //test address with no special chars - _testSession.getNetworkDriver().setStringLocalAddress(_validAddress); + _testSession.getNetworkDriver().setLocalAddress(_validAddress); testAddress = _testSession.genQueueName(); assertEquals("Failure when generating a queue exchange from an address with no special chars",_generatedAddress_3,testAddress.toString()); } -*/ + protected void tearDown() throws Exception { _testSession = null; -- cgit v1.2.1 From 93fa7d17feecb3d27cead67e11b250af1fcc595e Mon Sep 17 00:00:00 2001 From: Aidan Skinner Date: Wed, 16 Sep 2009 11:32:28 +0000 Subject: QPID-2015: Remove AMQIoTransportProtocolSession. Release the executor service in the same class as it's acquired git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/java-network-refactor@815729 13f79535-47bb-0310-9956-ffa450edef68 --- .../qpid/server/protocol/AMQProtocolEngine.java | 2 +- .../protocol/AMQIoTransportProtocolSession.java | 146 --------------------- .../qpid/client/protocol/AMQProtocolHandler.java | 1 + .../java/org/apache/qpid/pool/PoolingFilter.java | 3 - 4 files changed, 2 insertions(+), 150 deletions(-) delete mode 100644 qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQIoTransportProtocolSession.java (limited to 'qpid/java') diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java index 4f396015a2..b776c6ae82 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java @@ -706,7 +706,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol } _closed = true; - + _poolReference.releaseExecutorService(); CurrentActor.get().message(_logSubject, ConnectionMessages.CON_1002()); } } diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQIoTransportProtocolSession.java b/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQIoTransportProtocolSession.java deleted file mode 100644 index 8782e00a12..0000000000 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQIoTransportProtocolSession.java +++ /dev/null @@ -1,146 +0,0 @@ -package org.apache.qpid.client.protocol; -/* - * - * 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. - * - */ - - -import java.util.UUID; - -import javax.security.sasl.SaslClient; - -import org.apache.commons.lang.StringUtils; -import org.apache.mina.common.IdleStatus; -import org.apache.qpid.AMQException; -import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.client.ConnectionTuneParameters; -import org.apache.qpid.client.handler.ClientMethodDispatcherImpl; -import org.apache.qpid.client.state.AMQState; -import org.apache.qpid.framing.AMQDataBlock; -import org.apache.qpid.framing.AMQMethodBody; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.ProtocolInitiation; -import org.apache.qpid.framing.ProtocolVersion; -import org.apache.qpid.transport.Sender; - -public class AMQIoTransportProtocolSession extends AMQProtocolSession -{ - - protected Sender _ioSender; - private SaslClient _saslClient; - private ConnectionTuneParameters _connectionTuneParameters; - - public AMQIoTransportProtocolSession(AMQProtocolHandler protocolHandler, AMQConnection connection) - { - super(protocolHandler, connection); - } - - @Override - public void closeProtocolSession(boolean waitLast) - { - _ioSender.close(); - _protocolHandler.getStateManager().changeState(AMQState.CONNECTION_CLOSED); - } - - @Override - public void init() - { - _ioSender.send(new ProtocolInitiation(_connection.getProtocolVersion()).toNioByteBuffer()); - _ioSender.flush(); - } - - @Override - protected AMQShortString generateQueueName() - { - int id; - synchronized (_queueIdLock) - { - id = _queueId++; - } - return new AMQShortString("tmp_" + UUID.randomUUID() + "_" + id); - } - - @Override - public AMQConnection getAMQConnection() - { - return _connection; - } - - @Override - public SaslClient getSaslClient() - { - return _saslClient; - } - - @Override - public void setSaslClient(SaslClient client) - { - _saslClient = client; - } - - /** @param delay delay in seconds (not ms) */ - @Override - void initHeartbeats(int delay) - { - if (delay > 0) - { - // FIXME: actually do something here - HeartbeatDiagnostics.init(delay, HeartbeatConfig.CONFIG.getTimeout(delay)); - } - } - - @Override - public void methodFrameReceived(final int channel, final AMQMethodBody amqMethodBody) throws AMQException - { - // FIXME? - _protocolHandler.methodBodyReceived(channel, amqMethodBody, null); - } - - @Override - public void writeFrame(AMQDataBlock frame, boolean wait) - { - _ioSender.send(frame.toNioByteBuffer()); - if (wait) - { - _ioSender.flush(); - } - } - - @Override - public void setSender(Sender sender) - { - _ioSender = sender; - } - - @Override - public ConnectionTuneParameters getConnectionTuneParameters() - { - return _connectionTuneParameters; - } - - @Override - public void setConnectionTuneParameters(ConnectionTuneParameters params) - { - _connectionTuneParameters = params; - AMQConnection con = getAMQConnection(); - con.setMaximumChannelCount(params.getChannelMax()); - con.setMaximumFrameSize(params.getFrameMax()); - initHeartbeats((int) params.getHeartbeat()); - } -} diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java b/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java index c7e2493025..99366101d1 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java @@ -716,6 +716,7 @@ public class AMQProtocolHandler implements ProtocolEngine _logger.debug("FailoverException interrupted connection close, ignoring as connection close anyway."); } } + _poolReference.releaseExecutorService(); } /** @return the number of bytes read from this protocol session */ diff --git a/qpid/java/common/src/main/java/org/apache/qpid/pool/PoolingFilter.java b/qpid/java/common/src/main/java/org/apache/qpid/pool/PoolingFilter.java index 4863611c42..4e02ac3a55 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/pool/PoolingFilter.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/pool/PoolingFilter.java @@ -136,9 +136,6 @@ public abstract class PoolingFilter extends IoFilterAdapter implements Job.JobCo public void destroy() { _logger.debug("Destroy called on PoolingFilter " + toString()); - - // When the reference count gets to zero we release the executor service. - _poolReference.releaseExecutorService(); } /** -- cgit v1.2.1 From 31bbc100ac6b3a31eb25d29f407d60ff23334d1f Mon Sep 17 00:00:00 2001 From: Aidan Skinner Date: Thu, 17 Sep 2009 15:19:54 +0000 Subject: QPID-2024 QPID-2105: Remove now unnecessary classes like Event, PoolingFilter, ReadWriteThreadModel. Move the couple of necessary methods to Job. Fix imports. git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/java-network-refactor@816232 13f79535-47bb-0310-9956-ffa450edef68 --- .../qpid/server/protocol/AMQProtocolEngine.java | 20 +- .../qpid/client/protocol/AMQProtocolHandler.java | 53 +-- .../transport/SocketTransportConnection.java | 23 +- .../qpid/client/transport/TransportConnection.java | 14 +- .../transport/VmPipeTransportConnection.java | 6 +- .../src/main/java/org/apache/qpid/pool/Event.java | 167 ------- .../src/main/java/org/apache/qpid/pool/Job.java | 111 +++-- .../java/org/apache/qpid/pool/PoolingFilter.java | 487 --------------------- .../org/apache/qpid/pool/ReadWriteThreadModel.java | 102 ----- .../transport/network/mina/MINANetworkDriver.java | 22 - .../org/apache/qpid/pool/PoolingFilterTest.java | 111 ----- 11 files changed, 113 insertions(+), 1003 deletions(-) delete mode 100644 qpid/java/common/src/main/java/org/apache/qpid/pool/Event.java delete mode 100644 qpid/java/common/src/main/java/org/apache/qpid/pool/PoolingFilter.java delete mode 100644 qpid/java/common/src/main/java/org/apache/qpid/pool/ReadWriteThreadModel.java delete mode 100644 qpid/java/common/src/test/java/org/apache/qpid/pool/PoolingFilterTest.java (limited to 'qpid/java') diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java index b776c6ae82..3bcd102858 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java @@ -62,10 +62,7 @@ import org.apache.qpid.framing.MethodDispatcher; import org.apache.qpid.framing.MethodRegistry; import org.apache.qpid.framing.ProtocolInitiation; import org.apache.qpid.framing.ProtocolVersion; -import org.apache.qpid.pool.Event; import org.apache.qpid.pool.Job; -import org.apache.qpid.pool.PoolingFilter; -import org.apache.qpid.pool.ReadWriteThreadModel; import org.apache.qpid.pool.ReferenceCountingExecutorService; import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.protocol.AMQMethodEvent; @@ -172,14 +169,13 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol _networkDriver = driver; _codecFactory = new AMQCodecFactory(true, this); - - ReadWriteThreadModel threadModel = ReadWriteThreadModel.getInstance(); - _readJob = new Job(threadModel.getAsynchronousReadFilter(), PoolingFilter.MAX_JOB_EVENTS, true); - _writeJob = new Job(threadModel.getAsynchronousWriteFilter(), PoolingFilter.MAX_JOB_EVENTS, false); + _poolReference.acquireExecutorService(); + _readJob = new Job(_poolReference, Job.MAX_JOB_EVENTS, true); + _writeJob = new Job(_poolReference, Job.MAX_JOB_EVENTS, false); _actor = new AMQPConnectionActor(this, virtualHostRegistry.getApplicationRegistry().getRootMessageLogger()); _actor.message(ConnectionMessages.CON_1001(null, null, false, false)); - _poolReference.acquireExecutorService(); + } private AMQProtocolSessionMBean createMBean() throws AMQException @@ -212,7 +208,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol try { final ArrayList dataBlocks = _codecFactory.getDecoder().decodeBuffer(msg); - Job.fireAsynchEvent(_poolReference.getPool(), _readJob, new Event(new Runnable() + Job.fireAsynchEvent(_poolReference.getPool(), _readJob, new Runnable() { @Override public void run() @@ -232,7 +228,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol } } } - })); + }); } catch (Exception e) { @@ -459,14 +455,14 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol final ByteBuffer buf = frame.toNioByteBuffer(); _lastIoTime = System.currentTimeMillis(); _writtenBytes += buf.remaining(); - Job.fireAsynchEvent(_poolReference.getPool(), _writeJob, new Event(new Runnable() + Job.fireAsynchEvent(_poolReference.getPool(), _writeJob, new Runnable() { @Override public void run() { _networkDriver.send(buf); } - })); + }); } public AMQShortString getContextKey() diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java b/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java index 99366101d1..be75fc150f 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java @@ -20,20 +20,22 @@ */ package org.apache.qpid.client.protocol; -import org.apache.mina.filter.ReadThrottleFilterBuilder; -import org.apache.mina.filter.SSLFilter; -import org.apache.mina.filter.WriteBufferLimitFilterBuilder; +import java.io.IOException; +import java.net.SocketAddress; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.Set; +import java.util.concurrent.CopyOnWriteArraySet; +import java.util.concurrent.CountDownLatch; + import org.apache.mina.filter.codec.ProtocolCodecException; -import org.apache.mina.filter.codec.ProtocolCodecFilter; -import org.apache.mina.filter.executor.ExecutorFilter; import org.apache.qpid.AMQConnectionClosedException; import org.apache.qpid.AMQDisconnectedException; import org.apache.qpid.AMQException; import org.apache.qpid.AMQTimeoutException; import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.AMQSession; -import org.apache.qpid.client.SSLConfiguration; -import org.apache.qpid.client.configuration.ClientProperties; import org.apache.qpid.client.failover.FailoverException; import org.apache.qpid.client.failover.FailoverHandler; import org.apache.qpid.client.failover.FailoverState; @@ -42,32 +44,29 @@ import org.apache.qpid.client.state.AMQStateManager; import org.apache.qpid.client.state.StateWaiter; import org.apache.qpid.client.state.listener.SpecificMethodFrameListener; import org.apache.qpid.codec.AMQCodecFactory; -import org.apache.qpid.framing.*; +import org.apache.qpid.framing.AMQBody; +import org.apache.qpid.framing.AMQDataBlock; +import org.apache.qpid.framing.AMQFrame; +import org.apache.qpid.framing.AMQMethodBody; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.ConnectionCloseBody; +import org.apache.qpid.framing.ConnectionCloseOkBody; +import org.apache.qpid.framing.HeartbeatBody; +import org.apache.qpid.framing.MethodRegistry; +import org.apache.qpid.framing.ProtocolInitiation; +import org.apache.qpid.framing.ProtocolVersion; import org.apache.qpid.jms.BrokerDetails; -import org.apache.qpid.pool.Event; import org.apache.qpid.pool.Job; -import org.apache.qpid.pool.PoolingFilter; -import org.apache.qpid.pool.ReadWriteThreadModel; import org.apache.qpid.pool.ReferenceCountingExecutorService; import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.protocol.AMQMethodEvent; import org.apache.qpid.protocol.AMQMethodListener; import org.apache.qpid.protocol.ProtocolEngine; -import org.apache.qpid.ssl.SSLContextFactory; import org.apache.qpid.transport.NetworkDriver; import org.apache.qpid.transport.network.io.IoTransport; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.IOException; -import java.net.SocketAddress; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.Set; -import java.util.concurrent.CopyOnWriteArraySet; -import java.util.concurrent.CountDownLatch; - /** * AMQProtocolHandler is the client side protocol handler for AMQP, it handles all protocol events received from the * network by MINA. The primary purpose of AMQProtocolHandler is to translate the generic event model of MINA into the @@ -107,9 +106,6 @@ import java.util.concurrent.CountDownLatch; * *

*
CRC Card
Responsibilities Collaborations - *
Create the filter chain to filter this handlers events. - * {@link ProtocolCodecFilter}, {@link SSLContextFactory}, {@link SSLFilter}, {@link ReadWriteThreadModel}. - * *
Maintain fail-over state. *
*
@@ -191,9 +187,8 @@ public class AMQProtocolHandler implements ProtocolEngine _protocolSession = new AMQProtocolSession(this, _connection); _stateManager = new AMQStateManager(_protocolSession); _codecFactory = new AMQCodecFactory(false, _protocolSession); - ReadWriteThreadModel threadModel = ReadWriteThreadModel.getInstance(); - _readJob = new Job(threadModel.getAsynchronousReadFilter(), PoolingFilter.MAX_JOB_EVENTS, true); - _writeJob = new Job(threadModel.getAsynchronousWriteFilter(), PoolingFilter.MAX_JOB_EVENTS, false); + _readJob = new Job(_poolReference, Job.MAX_JOB_EVENTS, true); + _writeJob = new Job(_poolReference, Job.MAX_JOB_EVENTS, false); _poolReference.acquireExecutorService(); _failoverHandler = new FailoverHandler(this); } @@ -436,7 +431,7 @@ public class AMQProtocolHandler implements ProtocolEngine _readBytes += msg.remaining(); final ArrayList dataBlocks = _codecFactory.getDecoder().decodeBuffer(msg); - Job.fireAsynchEvent(_poolReference.getPool(), _readJob, new Event(new Runnable() + Job.fireAsynchEvent(_poolReference.getPool(), _readJob, new Runnable() { @Override public void run() @@ -495,7 +490,7 @@ public class AMQProtocolHandler implements ProtocolEngine } } } - })); + }); } catch (Exception e) { diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/transport/SocketTransportConnection.java b/qpid/java/client/src/main/java/org/apache/qpid/client/transport/SocketTransportConnection.java index 77c9c40e82..1ac8f62e32 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/transport/SocketTransportConnection.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/transport/SocketTransportConnection.java @@ -20,37 +20,20 @@ */ package org.apache.qpid.client.transport; +import java.io.IOException; +import java.net.InetSocketAddress; + import org.apache.mina.common.ByteBuffer; -import org.apache.mina.common.ConnectFuture; import org.apache.mina.common.IoConnector; import org.apache.mina.common.SimpleByteBufferAllocator; -import org.apache.mina.filter.SSLFilter; -import org.apache.mina.transport.socket.nio.ExistingSocketConnector; -import org.apache.mina.transport.socket.nio.SocketConnectorConfig; -import org.apache.mina.transport.socket.nio.SocketSessionConfig; - import org.apache.qpid.client.SSLConfiguration; import org.apache.qpid.client.protocol.AMQProtocolHandler; import org.apache.qpid.jms.BrokerDetails; -import org.apache.qpid.pool.ReadWriteThreadModel; import org.apache.qpid.ssl.SSLContextFactory; import org.apache.qpid.transport.network.mina.MINANetworkDriver; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import sun.net.InetAddressCachePolicy; - -import java.io.IOException; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.security.GeneralSecurityException; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import javax.net.ssl.SSLEngine; - public class SocketTransportConnection implements ITransportConnection { private static final Logger _logger = LoggerFactory.getLogger(SocketTransportConnection.class); diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/transport/TransportConnection.java b/qpid/java/client/src/main/java/org/apache/qpid/client/transport/TransportConnection.java index 45194750dc..a4f8bb0166 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/transport/TransportConnection.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/transport/TransportConnection.java @@ -20,6 +20,12 @@ */ package org.apache.qpid.client.transport; +import java.io.IOException; +import java.net.Socket; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + import org.apache.mina.common.IoConnector; import org.apache.mina.common.IoHandlerAdapter; import org.apache.mina.common.IoServiceConfig; @@ -30,20 +36,12 @@ import org.apache.mina.transport.vmpipe.VmPipeAcceptor; import org.apache.mina.transport.vmpipe.VmPipeAddress; import org.apache.qpid.client.vmbroker.AMQVMBrokerCreationException; import org.apache.qpid.jms.BrokerDetails; -import org.apache.qpid.pool.ReadWriteThreadModel; -import org.apache.qpid.protocol.ProtocolEngine; import org.apache.qpid.protocol.ProtocolEngineFactory; import org.apache.qpid.thread.QpidThreadExecutor; import org.apache.qpid.transport.network.mina.MINANetworkDriver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.net.Socket; - /** * The TransportConnection is a helper class responsible for connecting to an AMQ server. It sets up the underlying * connector, which currently always uses TCP/IP sockets. It creates the "protocol handler" which deals with MINA diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/transport/VmPipeTransportConnection.java b/qpid/java/client/src/main/java/org/apache/qpid/client/transport/VmPipeTransportConnection.java index 3de6f9b9ea..504d475740 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/transport/VmPipeTransportConnection.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/transport/VmPipeTransportConnection.java @@ -20,20 +20,18 @@ */ package org.apache.qpid.client.transport; +import java.io.IOException; + import org.apache.mina.common.ConnectFuture; -import org.apache.mina.common.IoServiceConfig; import org.apache.mina.transport.vmpipe.QpidVmPipeConnector; import org.apache.mina.transport.vmpipe.VmPipeAddress; import org.apache.mina.transport.vmpipe.VmPipeConnector; import org.apache.qpid.client.protocol.AMQProtocolHandler; import org.apache.qpid.jms.BrokerDetails; -import org.apache.qpid.pool.ReadWriteThreadModel; import org.apache.qpid.transport.network.mina.MINANetworkDriver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.IOException; - public class VmPipeTransportConnection implements ITransportConnection { private static final Logger _logger = LoggerFactory.getLogger(VmPipeTransportConnection.class); diff --git a/qpid/java/common/src/main/java/org/apache/qpid/pool/Event.java b/qpid/java/common/src/main/java/org/apache/qpid/pool/Event.java deleted file mode 100644 index 49bce9f2f9..0000000000 --- a/qpid/java/common/src/main/java/org/apache/qpid/pool/Event.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.pool; - -import org.apache.mina.common.IoFilter; -import org.apache.mina.common.IoSession; - -/** - * An Event is a continuation, which is used to break a Mina filter chain and save the current point in the chain - * for later processing. It is an abstract class, with different implementations for continuations of different kinds - * of Mina events. - * - *

These continuations are typically batched by {@link Job} for processing by a worker thread pool. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Process a continuation in the context of a Mina session. - *
- * - * @todo Pull up _nextFilter and getNextFilter into Event, as all events use it. Inner classes need to be non-static - * to use instance variables in the parent. Consequently they need to be non-inner to be instantiable outside of - * the context of the outer Event class. The inner class construction used here is preventing common code re-use - * (though not by a huge amount), but makes for an inelegent way of handling inheritance and doesn't seem like - * a justifiable use of inner classes. Move the inner classes out into their own files. - * - * @todo Could make Event implement Runnable, FutureTask, or a custom Continuation interface, to clarify its status as - * a continuation. Job is also a continuation, as is the job completion handler. Or, as Event is totally abstract, - * it is really an interface, so could just drop it and use the continuation interface instead. - */ -public class Event -{ - private Runnable _runner; - - public Event() - { - - } - - /** - * Creates a continuation. - */ - public Event(Runnable runner) - { - _runner = runner; - } - - /** - * Processes the continuation - */ - public void process() - { - _runner.run(); - } - - /** - * A continuation ({@link Event}) that takes a Mina messageReceived event, and passes it to a NextFilter. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Pass a Mina messageReceived event to a NextFilter. {@link IoFilter.NextFilter}, {@link IoSession} - *
- */ - public static final class MinaReceivedEvent extends Event - { - private final Object _data; - private final IoFilter.NextFilter _nextFilter; - private final IoSession _session; - - public MinaReceivedEvent(final IoFilter.NextFilter nextFilter, final Object data, final IoSession session) - { - _nextFilter = nextFilter; - _data = data; - _session = session; - } - - public void process() - { - _nextFilter.messageReceived(_session, _data); - } - - public IoFilter.NextFilter getNextFilter() - { - return _nextFilter; - } - } - - /** - * A continuation ({@link Event}) that takes a Mina filterWrite event, and passes it to a NextFilter. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Pass a Mina filterWrite event to a NextFilter. - * {@link IoFilter.NextFilter}, {@link IoFilter.WriteRequest}, {@link IoSession} - *
- */ - public static final class MinaWriteEvent extends Event - { - private final IoFilter.WriteRequest _data; - private final IoFilter.NextFilter _nextFilter; - private IoSession _session; - - public MinaWriteEvent(final IoFilter.NextFilter nextFilter, final IoFilter.WriteRequest data, final IoSession session) - { - _nextFilter = nextFilter; - _data = data; - _session = session; - } - - public void process() - { - _nextFilter.filterWrite(_session, _data); - } - - public IoFilter.NextFilter getNextFilter() - { - return _nextFilter; - } - } - - /** - * A continuation ({@link Event}) that takes a Mina sessionClosed event, and passes it to a NextFilter. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Pass a Mina sessionClosed event to a NextFilter. {@link IoFilter.NextFilter}, {@link IoSession} - *
- */ - public static final class CloseEvent extends Event - { - private final IoFilter.NextFilter _nextFilter; - private final IoSession _session; - - public CloseEvent(final IoFilter.NextFilter nextFilter, final IoSession session) - { - _nextFilter = nextFilter; - _session = session; - } - - public void process() - { - _nextFilter.sessionClosed(_session); - } - - public IoFilter.NextFilter getNextFilter() - { - return _nextFilter; - } - } -} diff --git a/qpid/java/common/src/main/java/org/apache/qpid/pool/Job.java b/qpid/java/common/src/main/java/org/apache/qpid/pool/Job.java index 15d1c20ff1..82b600de88 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/pool/Job.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/pool/Job.java @@ -25,7 +25,6 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.atomic.AtomicBoolean; -import org.apache.mina.common.IoSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -56,40 +55,28 @@ import org.slf4j.LoggerFactory; */ public class Job implements ReadWriteRunnable { + + /** Defines the maximum number of events that will be batched into a single job. */ + public static final int MAX_JOB_EVENTS = Integer.getInteger("amqj.server.read_write_pool.max_events", 10); + /** The maximum number of events to process per run of the job. More events than this may be queued in the job. */ private final int _maxEvents; /** Holds the queue of events that make up the job. */ - private final java.util.Queue _eventQueue = new ConcurrentLinkedQueue(); + private final java.util.Queue _eventQueue = new ConcurrentLinkedQueue(); /** Holds a status flag, that indicates when the job is actively running. */ private final AtomicBoolean _active = new AtomicBoolean(); - /** Holds the completion continuation, called upon completion of a run of the job. */ - private final JobCompletionHandler _completionHandler; - private final boolean _readJob; + private ReferenceCountingExecutorService _poolReference; + private final static Logger _logger = LoggerFactory.getLogger(Job.class); - /** - * Creates a new job that aggregates many continuations together. - * - * @param session The Mina session. - * @param completionHandler The per job run, terminal continuation. - * @param maxEvents The maximum number of aggregated continuations to process per run of the job. - * @param readJob - */ - Job(IoSession session, JobCompletionHandler completionHandler, int maxEvents, final boolean readJob) - { - _completionHandler = completionHandler; - _maxEvents = maxEvents; - _readJob = readJob; - } - - public Job(JobCompletionHandler completionHandler, int maxEvents, boolean readJob) + public Job(ReferenceCountingExecutorService poolReference, int maxEvents, boolean readJob) { - _completionHandler = completionHandler; + _poolReference = poolReference; _maxEvents = maxEvents; _readJob = readJob; } @@ -99,7 +86,7 @@ public class Job implements ReadWriteRunnable * * @param evt The continuation to enqueue. */ - public void add(Event evt) + public void add(Runnable evt) { _eventQueue.add(evt); } @@ -113,14 +100,14 @@ public class Job implements ReadWriteRunnable int i = _maxEvents; while( --i != 0 ) { - Event e = _eventQueue.poll(); + Runnable e = _eventQueue.poll(); if (e == null) { return true; } else { - e.process(); + e.run(); } } return false; @@ -162,11 +149,11 @@ public class Job implements ReadWriteRunnable if(processAll()) { deactivate(); - _completionHandler.completed(this); + completed(); } else { - _completionHandler.notCompleted(this); + notCompleted(); } } @@ -174,19 +161,6 @@ public class Job implements ReadWriteRunnable { return _readJob; } - - /** - * Another interface for a continuation. - * - * @todo Get rid of this interface as there are other interfaces that could be used instead, such as FutureTask, - * Runnable or a custom Continuation interface. - */ - static interface JobCompletionHandler - { - public void completed(Job job); - - public void notCompleted(final Job job); - } /** * Adds an {@link Event} to a {@link Job}, triggering the execution of the job if it is not already running. @@ -194,7 +168,7 @@ public class Job implements ReadWriteRunnable * @param job The job. * @param event The event to hand off asynchronously. */ - public static void fireAsynchEvent(ExecutorService pool, Job job, Event event) + public static void fireAsynchEvent(ExecutorService pool, Job job, Runnable event) { job.add(event); @@ -221,4 +195,59 @@ public class Job implements ReadWriteRunnable } + /** + * Implements a terminal continuation for the {@link Job} for this filter. Whenever the Job completes its processing + * of a batch of events this is called. This method simply re-activates the job, if it has more events to process. + * + * @param session The Mina session to work in. + * @param job The job that completed. + */ + public void completed() + { + if (!isComplete()) + { + final ExecutorService pool = _poolReference.getPool(); + + if(pool == null) + { + return; + } + + + // ritchiem : 2006-12-13 Do we need to perform the additional checks here? + // Can the pool be shutdown at this point? + if (activate()) + { + try + { + pool.execute(this); + } + catch(RejectedExecutionException e) + { + _logger.warn("Thread pool shutdown while tasks still outstanding"); + } + + } + } + } + + public void notCompleted() + { + final ExecutorService pool = _poolReference.getPool(); + + if(pool == null) + { + return; + } + + try + { + pool.execute(this); + } + catch(RejectedExecutionException e) + { + _logger.warn("Thread pool shutdown while tasks still outstanding"); + } + } + } diff --git a/qpid/java/common/src/main/java/org/apache/qpid/pool/PoolingFilter.java b/qpid/java/common/src/main/java/org/apache/qpid/pool/PoolingFilter.java deleted file mode 100644 index 4e02ac3a55..0000000000 --- a/qpid/java/common/src/main/java/org/apache/qpid/pool/PoolingFilter.java +++ /dev/null @@ -1,487 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.pool; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.RejectedExecutionException; - -import org.apache.mina.common.IdleStatus; -import org.apache.mina.common.IoFilterAdapter; -import org.apache.mina.common.IoSession; -import org.apache.qpid.pool.Event.CloseEvent; -import org.apache.qpid.pool.Event.MinaReceivedEvent; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * PoolingFilter, is a no-op pass through filter that hands all events down the Mina filter chain by default. As it - * adds no behaviour by default to the filter chain, it is abstract. - * - *

PoolingFilter provides a capability, available to sub-classes, to handle events in the chain asynchronously, by - * adding them to a job. If a job is not active, adding an event to it activates it. If it is active, the event is - * added to the job, which will run to completion and eventually process the event. The queue on the job itself acts as - * a buffer between stages of the pipeline. - * - *

There are two convenience methods, {@link #createAynschReadPoolingFilter} and - * {@link #createAynschWritePoolingFilter}, for obtaining pooling filters that handle 'messageReceived' and - * 'filterWrite' events, making it possible to process these event streams seperately. - * - *

Pooling filters have a name, in order to distinguish different filter types. They set up a {@link Job} on the - * Mina session they are working with, and store it in the session against their identifying name. This allows different - * filters with different names to be set up on the same filter chain, on the same Mina session, that batch their - * workloads in different jobs. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Implement default, pass through filter. - *
Create pooling filters and a specific thread pool. {@link ReferenceCountingExecutorService} - *
Provide the ability to batch Mina events for asynchronous processing. {@link Job}, {@link Event} - *
Provide a terminal continuation to keep jobs running till empty. - * {@link Job}, {@link Job.JobCompletionHandler} - *
- * - * @todo The static helper methods are pointless. Could just call new. - */ -public abstract class PoolingFilter extends IoFilterAdapter implements Job.JobCompletionHandler -{ - /** Used for debugging purposes. */ - private static final Logger _logger = LoggerFactory.getLogger(PoolingFilter.class); - - /** Holds the managed reference to obtain the executor for the batched jobs. */ - private final ReferenceCountingExecutorService _poolReference; - - /** Used to hold a name for identifying differeny pooling filter types. */ - private final String _name; - - /** Defines the maximum number of events that will be batched into a single job. */ - public static final int MAX_JOB_EVENTS = Integer.getInteger("amqj.server.read_write_pool.max_events", 10); - - private final int _maxEvents; - - private final boolean _readFilter; - - /** - * Creates a named pooling filter, on the specified shared thread pool. - * - * @param refCountingPool The thread pool reference. - * @param name The identifying name of the filter type. - */ - public PoolingFilter(ReferenceCountingExecutorService refCountingPool, String name, int maxEvents, boolean readFilter) - { - _poolReference = refCountingPool; - _name = name; - _maxEvents = maxEvents; - _readFilter = readFilter; - } - - /** - * Helper method to get an instance of a pooling filter that handles read events asynchronously. - * - * @param refCountingPool A managed reference to the thread pool. - * @param name The filter types identifying name. - * - * @return A pooling filter for asynchronous read events. - */ - public static PoolingFilter createAynschReadPoolingFilter(ReferenceCountingExecutorService refCountingPool, String name) - { - return new AsynchReadPoolingFilter(refCountingPool, name); - } - - /** - * Helper method to get an instance of a pooling filter that handles write events asynchronously. - * - * @param refCountingPool A managed reference to the thread pool. - * @param name The filter types identifying name. - * - * @return A pooling filter for asynchronous write events. - */ - public static PoolingFilter createAynschWritePoolingFilter(ReferenceCountingExecutorService refCountingPool, String name) - { - return new AsynchWritePoolingFilter(refCountingPool, name); - } - - /** - * Called by Mina to initialize this filter. Takes a reference to the thread pool. - */ - public void init() - { - _logger.debug("Init called on PoolingFilter " + toString()); - - // Called when the filter is initialised in the chain. If the reference count is - // zero this acquire will initialise the pool. - _poolReference.acquireExecutorService(); - } - - /** - * Called by Mina to clean up this filter. Releases the reference to the thread pool. - */ - public void destroy() - { - _logger.debug("Destroy called on PoolingFilter " + toString()); - } - - /** - * Adds an {@link Event} to a {@link Job}, triggering the execution of the job if it is not already running. - * - * @param job The job. - * @param event The event to hand off asynchronously. - */ - void fireAsynchEvent(Job job, Event event) - { - - job.add(event); - - final ExecutorService pool = _poolReference.getPool(); - - if(pool == null) - { - return; - } - - // rather than perform additional checks on pool to check that it hasn't shutdown. - // catch the RejectedExecutionException that will result from executing on a shutdown pool - if (job.activate()) - { - try - { - pool.execute(job); - } - catch(RejectedExecutionException e) - { - _logger.warn("Thread pool shutdown while tasks still outstanding"); - } - } - - } - - /** - * Creates a Job on the Mina session, identified by this filters name, in which this filter places asynchronously - * handled events. - * - * @param session The Mina session. - */ - public void createNewJobForSession(IoSession session) - { - Job job = new Job(session, this, MAX_JOB_EVENTS,_readFilter); - session.setAttribute(_name, job); - } - - /** - * Retrieves this filters Job, by this filters name, from the Mina session. - * - * @param session The Mina session. - * - * @return The Job for this filter to place asynchronous events into. - */ - public Job getJobForSession(IoSession session) - { - return (Job) session.getAttribute(_name); - } - - /** - * Implements a terminal continuation for the {@link Job} for this filter. Whenever the Job completes its processing - * of a batch of events this is called. This method simply re-activates the job, if it has more events to process. - * - * @param session The Mina session to work in. - * @param job The job that completed. - */ - public void completed(Job job) - { - - - if (!job.isComplete()) - { - final ExecutorService pool = _poolReference.getPool(); - - if(pool == null) - { - return; - } - - - // ritchiem : 2006-12-13 Do we need to perform the additional checks here? - // Can the pool be shutdown at this point? - if (job.activate()) - { - try - { - pool.execute(job); - } - catch(RejectedExecutionException e) - { - _logger.warn("Thread pool shutdown while tasks still outstanding"); - } - - } - } - } - - public void notCompleted(Job job) - { - final ExecutorService pool = _poolReference.getPool(); - - if(pool == null) - { - return; - } - - try - { - pool.execute(job); - } - catch(RejectedExecutionException e) - { - _logger.warn("Thread pool shutdown while tasks still outstanding"); - } - - } - - - - /** - * No-op pass through filter to the next filter in the chain. - * - * @param nextFilter The next filter in the chain. - * @param session The Mina session. - * - * @throws Exception This method does not throw any exceptions, but has Exception in its signature to allow - * overriding sub-classes the ability to. - */ - public void sessionOpened(final NextFilter nextFilter, final IoSession session) throws Exception - { - nextFilter.sessionOpened(session); - } - - /** - * No-op pass through filter to the next filter in the chain. - * - * @param nextFilter The next filter in the chain. - * @param session The Mina session. - * - * @throws Exception This method does not throw any exceptions, but has Exception in its signature to allow - * overriding sub-classes the ability to. - */ - public void sessionClosed(final NextFilter nextFilter, final IoSession session) throws Exception - { - nextFilter.sessionClosed(session); - } - - /** - * No-op pass through filter to the next filter in the chain. - * - * @param nextFilter The next filter in the chain. - * @param session The Mina session. - * @param status The session idle status. - * - * @throws Exception This method does not throw any exceptions, but has Exception in its signature to allow - * overriding sub-classes the ability to. - */ - public void sessionIdle(final NextFilter nextFilter, final IoSession session, final IdleStatus status) throws Exception - { - nextFilter.sessionIdle(session, status); - } - - /** - * No-op pass through filter to the next filter in the chain. - * - * @param nextFilter The next filter in the chain. - * @param session The Mina session. - * @param cause The underlying exception. - * - * @throws Exception This method does not throw any exceptions, but has Exception in its signature to allow - * overriding sub-classes the ability to. - */ - public void exceptionCaught(final NextFilter nextFilter, final IoSession session, final Throwable cause) throws Exception - { - nextFilter.exceptionCaught(session, cause); - } - - /** - * No-op pass through filter to the next filter in the chain. - * - * @param nextFilter The next filter in the chain. - * @param session The Mina session. - * @param message The message received. - * - * @throws Exception This method does not throw any exceptions, but has Exception in its signature to allow - * overriding sub-classes the ability to. - */ - public void messageReceived(final NextFilter nextFilter, final IoSession session, final Object message) throws Exception - { - nextFilter.messageReceived(session, message); - } - - /** - * No-op pass through filter to the next filter in the chain. - * - * @param nextFilter The next filter in the chain. - * @param session The Mina session. - * @param message The message sent. - * - * @throws Exception This method does not throw any exceptions, but has Exception in its signature to allow - * overriding sub-classes the ability to. - */ - public void messageSent(final NextFilter nextFilter, final IoSession session, final Object message) throws Exception - { - nextFilter.messageSent(session, message); - } - - /** - * No-op pass through filter to the next filter in the chain. - * - * @param nextFilter The next filter in the chain. - * @param session The Mina session. - * @param writeRequest The write request event. - * - * @throws Exception This method does not throw any exceptions, but has Exception in its signature to allow - * overriding sub-classes the ability to. - */ - public void filterWrite(final NextFilter nextFilter, final IoSession session, final WriteRequest writeRequest) - throws Exception - { - nextFilter.filterWrite(session, writeRequest); - } - - /** - * No-op pass through filter to the next filter in the chain. - * - * @param nextFilter The next filter in the chain. - * @param session The Mina session. - * - * @throws Exception This method does not throw any exceptions, but has Exception in its signature to allow - * overriding sub-classes the ability to. - */ - public void filterClose(NextFilter nextFilter, IoSession session) throws Exception - { - nextFilter.filterClose(session); - } - - /** - * No-op pass through filter to the next filter in the chain. - * - * @param nextFilter The next filter in the chain. - * @param session The Mina session. - * - * @throws Exception This method does not throw any exceptions, but has Exception in its signature to allow - * overriding sub-classes the ability to. - */ - public void sessionCreated(NextFilter nextFilter, IoSession session) throws Exception - { - nextFilter.sessionCreated(session); - } - - /** - * Prints the filter types identifying name to a string, mainly for debugging purposes. - * - * @return The filter types identifying name. - */ - public String toString() - { - return _name; - } - - /** - * AsynchReadPoolingFilter is a pooling filter that handles 'messageReceived' and 'sessionClosed' events - * asynchronously. - */ - public static class AsynchReadPoolingFilter extends PoolingFilter - { - /** - * Creates a pooling filter that handles read events asynchronously. - * - * @param refCountingPool A managed reference to the thread pool. - * @param name The filter types identifying name. - */ - public AsynchReadPoolingFilter(ReferenceCountingExecutorService refCountingPool, String name) - { - super(refCountingPool, name, Integer.getInteger("amqj.server.read_write_pool.max_read_events", MAX_JOB_EVENTS),true); - } - - /** - * Hands off this event for asynchronous execution. - * - * @param nextFilter The next filter in the chain. - * @param session The Mina session. - * @param message The message received. - */ - public void messageReceived(NextFilter nextFilter, final IoSession session, Object message) - { - Job job = getJobForSession(session); - fireAsynchEvent(job, new MinaReceivedEvent(nextFilter, message, session)); - } - - /** - * Hands off this event for asynchronous execution. - * - * @param nextFilter The next filter in the chain. - * @param session The Mina session. - */ - public void sessionClosed(final NextFilter nextFilter, final IoSession session) - { - Job job = getJobForSession(session); - fireAsynchEvent(job, new CloseEvent(nextFilter, session)); - } - } - - /** - * AsynchWritePoolingFilter is a pooling filter that handles 'filterWrite' and 'sessionClosed' events - * asynchronously. - */ - public static class AsynchWritePoolingFilter extends PoolingFilter - { - /** - * Creates a pooling filter that handles write events asynchronously. - * - * @param refCountingPool A managed reference to the thread pool. - * @param name The filter types identifying name. - */ - public AsynchWritePoolingFilter(ReferenceCountingExecutorService refCountingPool, String name) - { - super(refCountingPool, name, Integer.getInteger("amqj.server.read_write_pool.max_write_events", MAX_JOB_EVENTS),false); - } - - /** - * Hands off this event for asynchronous execution. - * - * @param nextFilter The next filter in the chain. - * @param session The Mina session. - * @param writeRequest The write request event. - */ - public void filterWrite(final NextFilter nextFilter, final IoSession session, final WriteRequest writeRequest) - { - Job job = getJobForSession(session); - fireAsynchEvent(job, new Event.MinaWriteEvent(nextFilter, writeRequest, session)); - } - - /** - * Hands off this event for asynchronous execution. - * - * @param nextFilter The next filter in the chain. - * @param session The Mina session. - */ - public void sessionClosed(final NextFilter nextFilter, final IoSession session) - { - Job job = getJobForSession(session); - fireAsynchEvent(job, new CloseEvent(nextFilter, session)); - } - } - -} diff --git a/qpid/java/common/src/main/java/org/apache/qpid/pool/ReadWriteThreadModel.java b/qpid/java/common/src/main/java/org/apache/qpid/pool/ReadWriteThreadModel.java deleted file mode 100644 index 8cea70e597..0000000000 --- a/qpid/java/common/src/main/java/org/apache/qpid/pool/ReadWriteThreadModel.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.pool; - -import org.apache.mina.common.IoFilterChain; -import org.apache.mina.common.ThreadModel; -import org.apache.mina.filter.ReferenceCountingIoFilter; - -/** - * ReadWriteThreadModel is a Mina i/o filter chain factory, which creates a filter chain with seperate filters to - * handle read and write events. The seperate filters are {@link PoolingFilter}s, which have thread pools to handle - * these events. The effect of this is that reading and writing may happen concurrently. - * - *

Socket i/o will only happen with concurrent reads and writes if Mina has seperate selector threads for each. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Create a filter chain with seperate read and write thread pools for read/write Mina events. - * {@link PoolingFilter} - *
- */ -public class ReadWriteThreadModel implements ThreadModel -{ - /** Holds the singleton instance of this factory. */ - private static final ReadWriteThreadModel _instance = new ReadWriteThreadModel(); - - /** Holds the thread pooling filter for reads. */ - private final PoolingFilter _asynchronousReadFilter; - - /** Holds the thread pooloing filter for writes. */ - private final PoolingFilter _asynchronousWriteFilter; - - /** - * Creates a new factory for concurrent i/o, thread pooling filter chain construction. This is private, so that - * only a singleton instance of the factory is ever created. - */ - private ReadWriteThreadModel() - { - final ReferenceCountingExecutorService executor = ReferenceCountingExecutorService.getInstance(); - _asynchronousReadFilter = PoolingFilter.createAynschReadPoolingFilter(executor, "AsynchronousReadFilter"); - _asynchronousWriteFilter = PoolingFilter.createAynschWritePoolingFilter(executor, "AsynchronousWriteFilter"); - } - - /** - * Gets the singleton instance of this filter chain factory. - * - * @return The singleton instance of this filter chain factory. - */ - public static ReadWriteThreadModel getInstance() - { - return _instance; - } - - /** - * Gets the read filter. - * - * @return The read filter. - */ - public PoolingFilter getAsynchronousReadFilter() - { - return _asynchronousReadFilter; - } - - /** - * Gets the write filter. - * - * @return The write filter. - */ - public PoolingFilter getAsynchronousWriteFilter() - { - return _asynchronousWriteFilter; - } - - /** - * Adds the concurrent read and write filters to a filter chain. - * - * @param chain The Mina filter chain to add to. - */ - public void buildFilterChain(IoFilterChain chain) - { - chain.addFirst("AsynchronousReadFilter", new ReferenceCountingIoFilter(_asynchronousReadFilter)); - chain.addLast("AsynchronousWriteFilter", new ReferenceCountingIoFilter(_asynchronousWriteFilter)); - } -} diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java index 7cc5f8e442..38ea9307b7 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java @@ -28,8 +28,6 @@ import java.net.InetSocketAddress; import java.net.SocketAddress; import java.nio.ByteBuffer; -import javax.net.ssl.SSLEngine; - import org.apache.mina.common.ConnectFuture; import org.apache.mina.common.IdleStatus; import org.apache.mina.common.IoAcceptor; @@ -50,7 +48,6 @@ import org.apache.mina.transport.socket.nio.SocketConnectorConfig; import org.apache.mina.transport.socket.nio.SocketSessionConfig; import org.apache.mina.util.NewThreadExecutor; import org.apache.mina.util.SessionUtil; -import org.apache.qpid.pool.ReadWriteThreadModel; import org.apache.qpid.protocol.ProtocolEngine; import org.apache.qpid.protocol.ProtocolEngineFactory; import org.apache.qpid.ssl.SSLContextFactory; @@ -58,7 +55,6 @@ import org.apache.qpid.thread.QpidThreadExecutor; import org.apache.qpid.transport.NetworkDriver; import org.apache.qpid.transport.NetworkDriverConfiguration; import org.apache.qpid.transport.OpenException; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -148,14 +144,6 @@ public class MINANetworkDriver extends IoHandlerAdapter implements NetworkDriver sc.setTcpNoDelay(config.getTcpNoDelay()); } - // if we do not use the executor pool threading model we get the default - // leader follower - // implementation provided by MINA - if (_executorPool) - { - sconfig.setThreadModel(ReadWriteThreadModel.getInstance()); - } - if (sslFactory != null) { _sslFactory = sslFactory; @@ -227,14 +215,6 @@ public class MINANetworkDriver extends IoHandlerAdapter implements NetworkDriver } SocketConnectorConfig cfg = (SocketConnectorConfig) _socketConnector.getDefaultConfig(); - - // if we do not use our own thread model we get the MINA default which is to use - // its own leader-follower model - boolean readWriteThreading = Boolean.getBoolean("amqj.shared_read_write_pool"); - if (readWriteThreading) - { - cfg.setThreadModel(ReadWriteThreadModel.getInstance()); - } SocketSessionConfig scfg = (SocketSessionConfig) cfg.getSessionConfig(); scfg.setTcpNoDelay((config != null) ? config.getTcpNoDelay() : true); @@ -258,8 +238,6 @@ public class MINANetworkDriver extends IoHandlerAdapter implements NetworkDriver throw new OpenException("Could not open connection", _lastException); } _ioSession = future.getSession(); - ReadWriteThreadModel.getInstance().getAsynchronousReadFilter().createNewJobForSession(_ioSession); - ReadWriteThreadModel.getInstance().getAsynchronousWriteFilter().createNewJobForSession(_ioSession); _ioSession.setAttachment(engine); engine.setNetworkDriver(this); _protocolEngine = engine; diff --git a/qpid/java/common/src/test/java/org/apache/qpid/pool/PoolingFilterTest.java b/qpid/java/common/src/test/java/org/apache/qpid/pool/PoolingFilterTest.java deleted file mode 100644 index 6383d52298..0000000000 --- a/qpid/java/common/src/test/java/org/apache/qpid/pool/PoolingFilterTest.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * - */ -package org.apache.qpid.pool; - -import junit.framework.TestCase; -import junit.framework.Assert; -import org.apache.qpid.session.TestSession; -import org.apache.mina.common.IoFilter; -import org.apache.mina.common.IoSession; -import org.apache.mina.common.IdleStatus; - -import java.util.concurrent.RejectedExecutionException; - -public class PoolingFilterTest extends TestCase -{ - private PoolingFilter _pool; - ReferenceCountingExecutorService _executorService; - - public void setUp() - { - - //Create Pool - _executorService = ReferenceCountingExecutorService.getInstance(); - _executorService.acquireExecutorService(); - _pool = PoolingFilter.createAynschWritePoolingFilter(_executorService, - "AsynchronousWriteFilter"); - - } - - public void testRejectedExecution() throws Exception - { - - TestSession testSession = new TestSession(); - _pool.createNewJobForSession(testSession); - _pool.filterWrite(new NoOpFilter(), testSession, new IoFilter.WriteRequest("Message")); - - //Shutdown the pool - _executorService.getPool().shutdownNow(); - - try - { - - testSession = new TestSession(); - _pool.createNewJobForSession(testSession); - //prior to fix for QPID-172 this would throw RejectedExecutionException - _pool.filterWrite(null, testSession, null); - } - catch (RejectedExecutionException rje) - { - Assert.fail("RejectedExecutionException should not occur after pool has shutdown:" + rje); - } - } - - private static class NoOpFilter implements IoFilter.NextFilter - { - - public void sessionOpened(IoSession session) - { - } - - public void sessionClosed(IoSession session) - { - } - - public void sessionIdle(IoSession session, IdleStatus status) - { - } - - public void exceptionCaught(IoSession session, Throwable cause) - { - } - - public void messageReceived(IoSession session, Object message) - { - } - - public void messageSent(IoSession session, Object message) - { - } - - public void filterWrite(IoSession session, IoFilter.WriteRequest writeRequest) - { - } - - public void filterClose(IoSession session) - { - } - - public void sessionCreated(IoSession session) - { - } - } -} -- cgit v1.2.1 From 7d6a028be9f6c47418e98a6fa74a359864428150 Mon Sep 17 00:00:00 2001 From: Aidan Skinner Date: Thu, 17 Sep 2009 16:21:13 +0000 Subject: Merge from trunk git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/java-network-refactor@816261 13f79535-47bb-0310-9956-ffa450edef68 --- qpid/java/broker/bin/qpid-passwd | 70 +-- qpid/java/broker/etc/acl.config.xml | 230 --------- qpid/java/broker/etc/config-systests-derby.xml | 141 ------ qpid/java/broker/etc/config-systests.xml | 143 ------ qpid/java/broker/etc/config.xml | 132 +++++- .../broker/etc/persistent_config-config-test.xml | 93 ---- qpid/java/broker/etc/sample-parsed-config.xml | 72 --- qpid/java/broker/etc/virtualhosts-config-test.xml | 40 -- qpid/java/broker/etc/virtualhosts-systests.xml | 124 ----- qpid/java/broker/etc/virtualhosts.xml | 123 ----- .../apache/qpid/server/AMQBrokerManagerMBean.java | 6 +- .../server/configuration/ServerConfiguration.java | 35 +- .../qpid/server/virtualhost/VirtualHost.java | 12 + .../configuration/ServerConfigurationTest.java | 55 ++- ...config-systests-ServerConfigurationTest-New.xml | 93 ++++ ...config-systests-ServerConfigurationTest-Old.xml | 72 +++ .../systests/etc/config-systests-acl-settings.xml | 139 ++++++ qpid/java/systests/etc/config-systests-acl.xml | 30 ++ .../etc/config-systests-derby-settings.xml | 64 +++ qpid/java/systests/etc/config-systests-derby.xml | 30 ++ .../java/systests/etc/config-systests-settings.xml | 29 ++ qpid/java/systests/etc/config-systests.xml | 29 ++ .../virtualhosts-ServerConfigurationTest-New.xml | 40 ++ .../management/jmx/ManagementActorLoggingTest.java | 527 +++++++-------------- .../configuration/ServerConfigurationFileTest.java | 2 + .../apache/qpid/server/logging/AlertingTest.java | 14 +- .../logging/DerbyMessageStoreLoggingTest.java | 43 +- .../qpid/server/logging/ManagementLoggingTest.java | 6 +- .../logging/MemoryMessageStoreLoggingTest.java | 12 +- .../server/logging/VirtualHostLoggingTest.java | 8 +- .../org/apache/qpid/server/queue/ModelTest.java | 299 ++++++++++++ .../qpid/server/security/acl/SimpleACLTest.java | 134 +++--- .../test/client/timeouts/SyncWaitDelayTest.java | 21 +- .../apache/qpid/test/utils/FailoverBaseCase.java | 4 +- .../org/apache/qpid/test/utils/JMXTestUtils.java | 208 ++++++++ .../org/apache/qpid/test/utils/QpidTestCase.java | 139 +++--- qpid/java/test-profiles/010Excludes | 3 + qpid/java/test-profiles/08Excludes | 5 + qpid/java/test-profiles/Excludes | 6 +- qpid/java/test-profiles/cpp.testprofile | 1 + qpid/java/test-profiles/default.testprofile | 5 +- 41 files changed, 1636 insertions(+), 1603 deletions(-) delete mode 100644 qpid/java/broker/etc/acl.config.xml delete mode 100644 qpid/java/broker/etc/config-systests-derby.xml delete mode 100644 qpid/java/broker/etc/config-systests.xml delete mode 100644 qpid/java/broker/etc/persistent_config-config-test.xml delete mode 100644 qpid/java/broker/etc/sample-parsed-config.xml delete mode 100644 qpid/java/broker/etc/virtualhosts-config-test.xml delete mode 100644 qpid/java/broker/etc/virtualhosts-systests.xml delete mode 100644 qpid/java/broker/etc/virtualhosts.xml create mode 100644 qpid/java/systests/etc/config-systests-ServerConfigurationTest-New.xml create mode 100644 qpid/java/systests/etc/config-systests-ServerConfigurationTest-Old.xml create mode 100644 qpid/java/systests/etc/config-systests-acl-settings.xml create mode 100644 qpid/java/systests/etc/config-systests-acl.xml create mode 100644 qpid/java/systests/etc/config-systests-derby-settings.xml create mode 100644 qpid/java/systests/etc/config-systests-derby.xml create mode 100644 qpid/java/systests/etc/config-systests-settings.xml create mode 100644 qpid/java/systests/etc/config-systests.xml create mode 100644 qpid/java/systests/etc/virtualhosts-ServerConfigurationTest-New.xml create mode 100644 qpid/java/systests/src/main/java/org/apache/qpid/server/queue/ModelTest.java create mode 100644 qpid/java/systests/src/main/java/org/apache/qpid/test/utils/JMXTestUtils.java (limited to 'qpid/java') diff --git a/qpid/java/broker/bin/qpid-passwd b/qpid/java/broker/bin/qpid-passwd index 63b30b5e71..b84580da60 100755 --- a/qpid/java/broker/bin/qpid-passwd +++ b/qpid/java/broker/bin/qpid-passwd @@ -1,35 +1,35 @@ -#!/bin/bash -# -# 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. -# - -if [ -z "$QPID_HOME" ]; then - export QPID_HOME=$(dirname $(dirname $(readlink -f $0))) - export PATH=${PATH}:${QPID_HOME}/bin -fi - -# Set classpath to include Qpid jar with all required jars in manifest -QPID_LIBS=$QPID_HOME/lib/qpid-all.jar - -# Set other variables used by the qpid-run script before calling -export JAVA=java \ - JAVA_VM=-server \ - JAVA_MEM=-Xmx1024m \ - QPID_CLASSPATH=$QPID_LIBS - -. qpid-run org.apache.qpid.tools.security.Passwd "$@" +#!/bin/bash +# +# 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. +# + +if [ -z "$QPID_HOME" ]; then + export QPID_HOME=$(dirname $(dirname $(readlink -f $0))) + export PATH=${PATH}:${QPID_HOME}/bin +fi + +# Set classpath to include Qpid jar with all required jars in manifest +QPID_LIBS=$QPID_HOME/lib/qpid-all.jar + +# Set other variables used by the qpid-run script before calling +export JAVA=java \ + JAVA_VM=-server \ + JAVA_MEM=-Xmx1024m \ + QPID_CLASSPATH=$QPID_LIBS + +. qpid-run org.apache.qpid.tools.security.Passwd "$@" diff --git a/qpid/java/broker/etc/acl.config.xml b/qpid/java/broker/etc/acl.config.xml deleted file mode 100644 index a2b723fc63..0000000000 --- a/qpid/java/broker/etc/acl.config.xml +++ /dev/null @@ -1,230 +0,0 @@ - - - - ${QPID_HOME} - ${QPID_WORK} - ${prefix}/etc - - - false - - false - nio - 5672 - 8672 - 32768 - 32768 - - - false - 8999 - false - - - - false - false - 65535 - false - false - - - - - - - passwordfile - org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase - - - passwordFile - ${conf}/passwd - - - - - - - org.apache.qpid.server.security.access.plugins.DenyAll - - - - ${conf}/jmxremote.access - passwordfile - - - - - ${conf}/virtualhosts - - - test - - - org.apache.qpid.server.store.MemoryMessageStore - - - - amq.direct - - 4235264 - - 2117632 - - 600000 - - - - - - org.apache.qpid.server.security.access.plugins.SimpleXML - - - - - - - amq.direct - - - - - example.RequestQueue - - client - - - - - - tmp_* - - server - - - - TempQueue* - - server - - - - - - - - - - - - - - - - - client - - - - - - - example.RequestQueue - - server - - - - - - - - - - - - - - - - amq.direct - - client - - - - - - - example.RequestQueue - - server - - - - - - - - - - - - - - - - development - - - org.apache.qpid.server.store.MemoryMessageStore - - - - - - localhost - - - org.apache.qpid.server.store.MemoryMessageStore - - - - - - - - 0 - 2.0 - - - ${conf}/virtualhosts.xml - - - diff --git a/qpid/java/broker/etc/config-systests-derby.xml b/qpid/java/broker/etc/config-systests-derby.xml deleted file mode 100644 index e9cfa04ab5..0000000000 --- a/qpid/java/broker/etc/config-systests-derby.xml +++ /dev/null @@ -1,141 +0,0 @@ - - - - ${QPID_HOME} - ${QPID_WORK} - ${prefix}/etc - - - false - - false - - nio - 5672 - 8672 - 32768 - 32768 - - - false - 8999 - - false - - ${prefix}/../test-profiles/test_resources/ssl/keystore.jks - password - - - - - false - false - 65535 - false - false - - - - - - - passwordfile - org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase - - - passwordFile - ${conf}/passwd - - - - - - - org.apache.qpid.server.security.access.plugins.AllowAll - - - false - - - ${conf}/jmxremote.access - passwordfile - - - - - ${conf}/virtualhosts - - - localhost - - - org.apache.qpid.server.store.DerbyMessageStore - ${work}/derbyDB/localhost-store - - - - 20000 - - - - - - - development - - - org.apache.qpid.server.store.DerbyMessageStore - ${work}/derbyDB/development-store - - - - - - test - - - org.apache.qpid.server.store.DerbyMessageStore - ${work}/derbyDB/test-store - - - - - - - 0 - 2.0 - - - true - - - ${conf}/virtualhosts-systests.xml - - - diff --git a/qpid/java/broker/etc/config-systests.xml b/qpid/java/broker/etc/config-systests.xml deleted file mode 100644 index 42e8c9dbba..0000000000 --- a/qpid/java/broker/etc/config-systests.xml +++ /dev/null @@ -1,143 +0,0 @@ - - - - ${QPID_HOME} - ${QPID_WORK} - ${prefix}/etc - - - false - - false - 262144 - 262144 - - nio - 5672 - 8672 - 32768 - 32768 - - - false - 8999 - - false - - ${prefix}/../test-profiles/test_resources/ssl/keystore.jks - password - - - - - false - false - 65535 - false - false - en_US - - - - - - - passwordfile - org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase - - - passwordFile - ${conf}/passwd - - - - - - - org.apache.qpid.server.security.access.plugins.AllowAll - - - false - - - ${conf}/jmxremote.access - passwordfile - - - - - ${conf}/virtualhosts - - - localhost - - - org.apache.qpid.server.store.MemoryMessageStore - - - - 20000 - - - - - - - development - - - org.apache.qpid.server.store.MemoryMessageStore - - - - - - test - - - org.apache.qpid.server.store.MemoryMessageStore - - - - - - - 0 - 2.0 - - - true - - - ON - - ${conf}/virtualhosts-systests.xml - - - diff --git a/qpid/java/broker/etc/config.xml b/qpid/java/broker/etc/config.xml index 928b773606..8fb3a8cf5a 100644 --- a/qpid/java/broker/etc/config.xml +++ b/qpid/java/broker/etc/config.xml @@ -24,17 +24,20 @@ ${QPID_WORK} ${prefix}/etc - - true - true + false + false /path/to/keystore.ks keystorepass - --> + false false + 262144 + 262144 nio 5672 @@ -59,6 +62,7 @@ 65535 false false + en_US @@ -89,40 +93,143 @@ - ${conf}/virtualhosts + test localhost - org.apache.qpid.server.store.MemoryMessageStore + org.apache.qpid.server.store.MemoryMessageStore + 20000 + + + direct + test.direct + true + + + topic + test.topic + + + + amq.direct + 4235264 + + 2117632 + + 600000 + + 50 + + + + queue + + + ping + + + test-queue + + test.direct + true + + + + test-ping + + test.direct + + + + + development - org.apache.qpid.server.store.MemoryMessageStore + org.apache.qpid.server.store.MemoryMessageStore + + + + 30000 + 50 + + queue + + amq.direct + 4235264 + + 2117632 + + 600000 + + + + + ping + + amq.direct + 4235264 + + 2117632 + + 600000 + + + + - test - org.apache.qpid.server.store.MemoryMessageStore + org.apache.qpid.server.store.MemoryMessageStore + + + + 30000 + 50 + + queue + + amq.direct + 4235264 + + 2117632 + + 600000 + + + + + ping + + amq.direct + 4235264 + + 2117632 + + 600000 + + + + - 0 @@ -132,7 +239,8 @@ true - ${conf}/virtualhosts.xml + ON + diff --git a/qpid/java/broker/etc/persistent_config-config-test.xml b/qpid/java/broker/etc/persistent_config-config-test.xml deleted file mode 100644 index 258f54397d..0000000000 --- a/qpid/java/broker/etc/persistent_config-config-test.xml +++ /dev/null @@ -1,93 +0,0 @@ - - - - - ${QPID_WORK} - ${QPID_HOME}/etc - ${conf} - - nio - 5672 - 32768 - 32768 - - - false - 8999 - - - - false - false - 65535 - false - - - - - - passwordfile - org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase - - - passwordFile - ${passwordDir}/passwd - - - - - - - org.apache.qpid.server.security.access.plugins.AllowAll - - - ${passwordDir}/jmxremote.access - passwordfile - - - - - - dev-only - - - org.apache.qpid.server.store.MemoryMessageStore - ${work}/bdbstore/dev-only-store - - - - - - 0 - 2.0 - - - true - - - ${conf}/virtualhosts-config-test.xml - - - diff --git a/qpid/java/broker/etc/sample-parsed-config.xml b/qpid/java/broker/etc/sample-parsed-config.xml deleted file mode 100644 index 37dfae4d2e..0000000000 --- a/qpid/java/broker/etc/sample-parsed-config.xml +++ /dev/null @@ -1,72 +0,0 @@ - - -${QPID_WORK} -${QPID_HOME}/etc -${conf} - -nio -5672 -32768 -32768 - - -false -8999 - - - -false -false -65535 -false - - - - -passwordfile -org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase - - -passwordFile -${passwordDir}/passwd - - - - - -org.apache.qpid.server.security.access.plugins.AllowAll - - -${passwordDir}/jmxremote.access -passwordfile - - -${conf}/virtualhosts-config-test.xml -dev-only - -dev-only - - -org.apache.qpid.server.store.MemoryMessageStore -${work}/bdbstore/dev-only-store - - -amq.direct -102400 -20480 -60000 - -dev-queue - - - - - - -0 -2.0 - - -true - - diff --git a/qpid/java/broker/etc/virtualhosts-config-test.xml b/qpid/java/broker/etc/virtualhosts-config-test.xml deleted file mode 100644 index 168aa074da..0000000000 --- a/qpid/java/broker/etc/virtualhosts-config-test.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - dev-only - - dev-only - - - amq.direct - - 102400 - 20480 - 60000 - - - dev-queue - - - - - diff --git a/qpid/java/broker/etc/virtualhosts-systests.xml b/qpid/java/broker/etc/virtualhosts-systests.xml deleted file mode 100644 index 4f23f55579..0000000000 --- a/qpid/java/broker/etc/virtualhosts-systests.xml +++ /dev/null @@ -1,124 +0,0 @@ - - - - test - - localhost - - - - direct - test.direct - true - - - topic - test.topic - - - - amq.direct - 4235264 - 2117632 - 600000 - 50 - - - queue - - - ping - - - test-queue - - test.direct - true - - - - test-ping - - test.direct - - - - - - - - - - development - - - 30000 - 50 - - queue - - amq.direct - 4235264 - 2117632 - 600000 - - - - ping - - amq.direct - 4235264 - 2117632 - 600000 - - - - - - - test - - - 30000 - 50 - - queue - - amq.direct - 4235264 - 2117632 - 600000 - - - - ping - - amq.direct - 4235264 - 2117632 - 600000 - - - - - - diff --git a/qpid/java/broker/etc/virtualhosts.xml b/qpid/java/broker/etc/virtualhosts.xml deleted file mode 100644 index f62ec3f5d7..0000000000 --- a/qpid/java/broker/etc/virtualhosts.xml +++ /dev/null @@ -1,123 +0,0 @@ - - - - test - - localhost - - - - direct - test.direct - true - - - topic - test.topic - - - - amq.direct - 4235264 - 2117632 - 600000 - - - queue - - - ping - - - test-queue - - test.direct - true - - - - test-ping - - test.direct - - - - - - - - - - development - - - 30000 - 5000 - - queue - - amq.direct - 4235264 - 2117632 - 600000 - - - - ping - - amq.direct - 4235264 - 2117632 - 600000 - - - - - - - test - - - 30000 - 5000 - - queue - - amq.direct - 4235264 - 2117632 - 600000 - - - - ping - - amq.direct - 4235264 - 2117632 - 600000 - - - - - - diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java index 2afd3c1dc3..5cfa8066e5 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java @@ -317,8 +317,10 @@ public class AMQBrokerManagerMBean extends AMQManagedObject implements ManagedBr try { queue.delete(); - _messageStore.removeQueue(queue); - + if (queue.isDurable()) + { + _messageStore.removeQueue(queue); + } } catch (AMQException ex) { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java index b3c8975c7c..a72c2889d1 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java @@ -148,32 +148,27 @@ public class ServerConfiguration implements SignalHandler Object thing = i.next(); if (thing instanceof String) { + //Open the Virtualhost.xml file and copy values in to main config XMLConfiguration vhostConfiguration = new XMLConfiguration((String) thing); - List hosts = vhostConfiguration.getList("virtualhost.name"); - for (int j = 0; j < hosts.size(); j++) - { - String name = (String) hosts.get(j); - // Add the keys of the virtual host to the main config then bail out - - Configuration myConf = vhostConfiguration.subset("virtualhost." + name); - Iterator k = myConf.getKeys(); - while (k.hasNext()) - { - String key = (String) k.next(); - conf.setProperty("virtualhosts.virtualhost."+name+"."+key, myConf.getProperty(key)); - } - VirtualHostConfiguration vhostConfig = new VirtualHostConfiguration(name, conf.subset("virtualhosts.virtualhost."+name)); - _virtualHosts.put(vhostConfig.getName(), vhostConfig); - } - // Grab things other than the virtualhosts themselves Iterator keys = vhostConfiguration.getKeys(); while (keys.hasNext()) { String key = (String) keys.next(); - conf.setProperty("virtualhosts."+key, vhostConfiguration.getProperty(key)); + conf.setProperty("virtualhosts." + key, vhostConfiguration.getProperty(key)); } } } + + List hosts = conf.getList("virtualhosts.virtualhost.name"); + for (int j = 0; j < hosts.size(); j++) + { + String name = (String) hosts.get(j); + // Add the keys of the virtual host to the main config then bail out + + VirtualHostConfiguration vhostConfig = new VirtualHostConfiguration(name, conf.subset("virtualhosts.virtualhost." + name)); + _virtualHosts.put(vhostConfig.getName(), vhostConfig); + } + } private void substituteEnvironmentVariables() @@ -203,7 +198,7 @@ public class ServerConfiguration implements SignalHandler } /** - * Check the configuration file to see if status updates are enabled. + * Check the configuration file to see if status updates are enabled. * @return true if status updates are enabled */ public boolean getStatusUpdatesEnabled() @@ -467,7 +462,7 @@ public class ServerConfiguration implements SignalHandler { return getConfig().getBoolean("management.enabled", true); } - + public void setManagementEnabled(boolean enabled) { getConfig().setProperty("management.enabled", enabled); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java index aec437b700..3b776a62b4 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java @@ -195,10 +195,22 @@ public class VirtualHost implements Accessable // perform a createExchange twice with the same details in the // MessageStore(RoutingTable) as some instances may not like that. // Derby being one. + // todo this can be removed with the resolution fo QPID-2096 configFileRT.exchange.clear(); initialiseModel(hostConfig); + //todo REMOVE Work Around for QPID-2096 + // This means that all durable exchanges declared in the configuration + // will not be stored in the MessageStore. + // They will still be created/registered/available on startup for as + // long as they are contained in the configuration. However, when they + // are removed from the configuration they will no longer exist. + // This differs from durable queues as they will be writen to to the + // store. After QPID-2096 has been resolved exchanges will mirror that + // functionality. + configFileRT.exchange.clear(); + if (store != null) { _messageStore = store; diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java index 2285f5256e..93e7e756e6 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java @@ -54,7 +54,7 @@ public class ServerConfigurationTest extends TestCase _config = new XMLConfiguration(); } - + @Override public void tearDown() throws Exception { @@ -727,7 +727,7 @@ public class ServerConfigurationTest extends TestCase assertEquals(true, config.getQpidNIO()); // From the second file, not // present in the first } - + public void testVariableInterpolation() throws Exception { File mainFile = File.createTempFile(getClass().getName(), null); @@ -742,7 +742,7 @@ public class ServerConfigurationTest extends TestCase out.close(); ServerConfiguration config = new ServerConfiguration(mainFile.getAbsoluteFile()); - assertEquals("Did not get correct interpolated value", + assertEquals("Did not get correct interpolated value", "foo", config.getManagementKeyStorePath()); } @@ -783,7 +783,7 @@ public class ServerConfigurationTest extends TestCase out.write("\t\n"); out.write("\n"); out.close(); - + // Load config ApplicationRegistry reg = new ConfigurationFileApplicationRegistry(mainFile); ApplicationRegistry.initialise(reg, 1); @@ -791,18 +791,18 @@ public class ServerConfigurationTest extends TestCase // Test config VirtualHostRegistry virtualHostRegistry = reg.getVirtualHostRegistry(); VirtualHost virtualHost = virtualHostRegistry.getVirtualHost("test"); - + TestNetworkDriver testDriver = new TestNetworkDriver(); testDriver.setRemoteAddress("127.0.0.1"); AMQProtocolEngine session = new AMQProtocolEngine(virtualHostRegistry, testDriver); assertFalse(reg.getAccessManager().authoriseConnect(session, virtualHost)); - + testDriver.setRemoteAddress("127.1.2.3"); session = new AMQProtocolEngine(virtualHostRegistry, testDriver); assertTrue(reg.getAccessManager().authoriseConnect(session, virtualHost)); } - + public void testCombinedConfigurationFirewall() throws Exception { // Write out config @@ -868,7 +868,7 @@ public class ServerConfigurationTest extends TestCase TestNetworkDriver testDriver = new TestNetworkDriver(); testDriver.setRemoteAddress("127.0.0.1"); - + AMQProtocolEngine session = new AMQProtocolEngine(virtualHostRegistry, testDriver); session.setNetworkDriver(testDriver); assertFalse(reg.getAccessManager().authoriseConnect(session, virtualHost)); @@ -945,22 +945,22 @@ public class ServerConfigurationTest extends TestCase fileBRandom.setLength(0); fileBRandom.seek(0); fileBRandom.close(); - + out = new FileWriter(fileB); out.write("\n"); out.write("\t"); out.write("\n"); out.close(); - + reg.getConfiguration().reparseConfigFile(); - + assertTrue(reg.getAccessManager().authoriseConnect(session, virtualHost)); - + fileBRandom = new RandomAccessFile(fileB, "rw"); fileBRandom.setLength(0); fileBRandom.seek(0); fileBRandom.close(); - + out = new FileWriter(fileB); out.write("\n"); out.write("\t"); @@ -968,17 +968,17 @@ public class ServerConfigurationTest extends TestCase out.close(); reg.getConfiguration().reparseConfigFile(); - + assertFalse(reg.getAccessManager().authoriseConnect(session, virtualHost)); } public void testnewParserOutputVsOldParserOutput() throws ConfigurationException { String configDir = System.getProperty("QPID_HOME")+"/etc"; - - XMLConfiguration oldConfig = new XMLConfiguration(configDir +"/sample-parsed-config.xml"); - Configuration newConfig = new ServerConfiguration(new File(configDir+"/persistent_config-config-test.xml")).getConfig(); - + + XMLConfiguration oldConfig = new XMLConfiguration(configDir +"/config-systests-ServerConfigurationTest-Old.xml"); + Configuration newConfig = new ServerConfiguration(new File(configDir+"/config-systests-ServerConfigurationTest-New.xml")).getConfig(); + Iterator xmlKeys = oldConfig.getKeys(); while (xmlKeys.hasNext()) { @@ -986,6 +986,21 @@ public class ServerConfigurationTest extends TestCase assertEquals("Incorrect value for "+key, oldConfig.getProperty(key), newConfig.getProperty(key)); } } - - + + + public void testNoVirtualhostXMLFile() throws Exception + { + int REGISTRY=1; + + File configFile = new File(System.getProperty("QPID_HOME")+"/etc/config.xml"); + assertTrue(configFile.exists()); + + ApplicationRegistry.initialise(new ConfigurationFileApplicationRegistry(configFile), REGISTRY); + + VirtualHostRegistry virtualHostRegistry = ApplicationRegistry.getInstance(REGISTRY).getVirtualHostRegistry(); + + assertEquals("Incorrect virtualhost count", 3 , virtualHostRegistry.getVirtualHosts().size()); + } + + } diff --git a/qpid/java/systests/etc/config-systests-ServerConfigurationTest-New.xml b/qpid/java/systests/etc/config-systests-ServerConfigurationTest-New.xml new file mode 100644 index 0000000000..33cc90b895 --- /dev/null +++ b/qpid/java/systests/etc/config-systests-ServerConfigurationTest-New.xml @@ -0,0 +1,93 @@ + + + + + ${QPID_WORK} + ${QPID_HOME}/etc + ${conf} + + nio + 5672 + 32768 + 32768 + + + false + 8999 + + + + false + false + 65535 + false + + + + + + passwordfile + org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase + + + passwordFile + ${passwordDir}/passwd + + + + + + + org.apache.qpid.server.security.access.plugins.AllowAll + + + ${passwordDir}/jmxremote.access + passwordfile + + + + + + dev-only + + + org.apache.qpid.server.store.MemoryMessageStore + ${work}/bdbstore/dev-only-store + + + + + + 0 + 2.0 + + + true + + + ${conf}/virtualhosts-ServerConfigurationTest-New.xml + + + diff --git a/qpid/java/systests/etc/config-systests-ServerConfigurationTest-Old.xml b/qpid/java/systests/etc/config-systests-ServerConfigurationTest-Old.xml new file mode 100644 index 0000000000..67e0702c41 --- /dev/null +++ b/qpid/java/systests/etc/config-systests-ServerConfigurationTest-Old.xml @@ -0,0 +1,72 @@ + + +${QPID_WORK} +${QPID_HOME}/etc +${conf} + +nio +5672 +32768 +32768 + + +false +8999 + + + +false +false +65535 +false + + + + +passwordfile +org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase + + +passwordFile +${passwordDir}/passwd + + + + + +org.apache.qpid.server.security.access.plugins.AllowAll + + +${passwordDir}/jmxremote.access +passwordfile + + +${conf}/virtualhosts-ServerConfigurationTest-New.xml +dev-only + +dev-only + + +org.apache.qpid.server.store.MemoryMessageStore +${work}/bdbstore/dev-only-store + + +amq.direct +102400 +20480 +60000 + +dev-queue + + + + + + +0 +2.0 + + +true + + diff --git a/qpid/java/systests/etc/config-systests-acl-settings.xml b/qpid/java/systests/etc/config-systests-acl-settings.xml new file mode 100644 index 0000000000..c5374a5c5e --- /dev/null +++ b/qpid/java/systests/etc/config-systests-acl-settings.xml @@ -0,0 +1,139 @@ + + + + + + + + test + + + amq.direct + + 4235264 + + 2117632 + + 600000 + + + + + + org.apache.qpid.server.security.access.plugins.SimpleXML + + + + + + + amq.direct + + + + + example.RequestQueue + + client + + + + + + tmp_* + + server + + + + TempQueue* + + server + + + + + + + + + + + + + + + + + client + + + + + + + example.RequestQueue + + server + + + + + + + + + + + + + + + + amq.direct + + client + + + + + + + example.RequestQueue + + server + + + + + + + + + + + + + + + + diff --git a/qpid/java/systests/etc/config-systests-acl.xml b/qpid/java/systests/etc/config-systests-acl.xml new file mode 100644 index 0000000000..34104dbe6b --- /dev/null +++ b/qpid/java/systests/etc/config-systests-acl.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + diff --git a/qpid/java/systests/etc/config-systests-derby-settings.xml b/qpid/java/systests/etc/config-systests-derby-settings.xml new file mode 100644 index 0000000000..9c25b5682e --- /dev/null +++ b/qpid/java/systests/etc/config-systests-derby-settings.xml @@ -0,0 +1,64 @@ + + + + + ${conf}/virtualhosts + + + localhost + + + org.apache.qpid.server.store.DerbyMessageStore + ${work}/derbyDB/localhost-store + + + + 20000 + + + + + + + development + + + org.apache.qpid.server.store.DerbyMessageStore + ${work}/derbyDB/development-store + + + + + + test + + + org.apache.qpid.server.store.DerbyMessageStore + ${work}/derbyDB/test-store + + + + + + + + diff --git a/qpid/java/systests/etc/config-systests-derby.xml b/qpid/java/systests/etc/config-systests-derby.xml new file mode 100644 index 0000000000..18ba0c4ad9 --- /dev/null +++ b/qpid/java/systests/etc/config-systests-derby.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + diff --git a/qpid/java/systests/etc/config-systests-settings.xml b/qpid/java/systests/etc/config-systests-settings.xml new file mode 100644 index 0000000000..4e9c863fda --- /dev/null +++ b/qpid/java/systests/etc/config-systests-settings.xml @@ -0,0 +1,29 @@ + + + + + false + + false + + + diff --git a/qpid/java/systests/etc/config-systests.xml b/qpid/java/systests/etc/config-systests.xml new file mode 100644 index 0000000000..290c082a4f --- /dev/null +++ b/qpid/java/systests/etc/config-systests.xml @@ -0,0 +1,29 @@ + + + + + + + + + + diff --git a/qpid/java/systests/etc/virtualhosts-ServerConfigurationTest-New.xml b/qpid/java/systests/etc/virtualhosts-ServerConfigurationTest-New.xml new file mode 100644 index 0000000000..168aa074da --- /dev/null +++ b/qpid/java/systests/etc/virtualhosts-ServerConfigurationTest-New.xml @@ -0,0 +1,40 @@ + + + + dev-only + + dev-only + + + amq.direct + + 102400 + 20480 + 60000 + + + dev-queue + + + + + diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagementActorLoggingTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagementActorLoggingTest.java index b4ba6e8156..2e107ada34 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagementActorLoggingTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagementActorLoggingTest.java @@ -20,26 +20,19 @@ */ package org.apache.qpid.management.jmx; -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.ManagedConnection; import org.apache.qpid.management.common.mbeans.ManagedExchange; import org.apache.qpid.server.logging.AbstractTestLogging; import org.apache.qpid.server.logging.subjects.AbstractTestLogSubject; +import org.apache.qpid.test.utils.JMXTestUtils; import javax.jms.Connection; import javax.jms.ExceptionListener; import javax.jms.JMSException; import javax.management.JMException; -import javax.management.MBeanException; -import javax.management.MBeanServerConnection; -import javax.management.MBeanServerInvocationHandler; -import javax.management.ObjectName; -import javax.management.remote.JMXConnector; import java.io.IOException; import java.util.List; -import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -50,33 +43,21 @@ import java.util.concurrent.TimeUnit; */ public class ManagementActorLoggingTest extends AbstractTestLogging { - MBeanServerConnection _mbsc; - JMXConnector _jmxc; + private JMXTestUtils _jmxUtils; private static final String USER = "admin"; @Override public void setUp() throws Exception { - setConfigurationProperty("management.enabled", "true"); + _jmxUtils = new JMXTestUtils(this, USER, USER); + _jmxUtils.setUp(); super.setUp(); - - if (isExternalBroker()) - { - _jmxc = JMXConnnectionFactory.getJMXConnection( - 5000, "127.0.0.1", - getManagementPort(getPort()), USER, USER); - - _mbsc = _jmxc.getMBeanServerConnection(); - } } @Override public void tearDown() throws Exception { - if (isExternalBroker()) - { - _jmxc.close(); - } + _jmxUtils.close(); super.tearDown(); } @@ -107,34 +88,31 @@ public class ManagementActorLoggingTest extends AbstractTestLogging */ public void testJMXManagementConsoleConnection() throws IOException { - if (isExternalBroker()) - { - List results = _monitor.findMatches("MNG-1007"); + List results = _monitor.findMatches("MNG-1007"); - assertEquals("Unexpected Management Connection count", 1, results.size()); + assertEquals("Unexpected Management Connection count", 1, results.size()); - String log = getLog(results.get(0)); + String log = getLog(results.get(0)); - validateMessageID("MNG-1007", log); + validateMessageID("MNG-1007", log); - assertTrue("User not in log message:" + log, log.endsWith(USER)); - // Extract the id from the log string - // MESSAGE [mng:1(rmi://169.24.29.116)] MNG-1007 : Open : User admin - int connectionID = Integer.parseInt(fromActor(getLog(results.get(0))).charAt(4) + ""); + assertTrue("User not in log message:" + log, log.endsWith(USER)); + // Extract the id from the log string + // MESSAGE [mng:1(rmi://169.24.29.116)] MNG-1007 : Open : User admin + int connectionID = Integer.parseInt(fromActor(getLog(results.get(0))).charAt(4) + ""); - results = _monitor.findMatches("MNG-1008"); + results = _monitor.findMatches("MNG-1008"); - assertEquals("Unexpected Management Connection close count", 0, results.size()); + assertEquals("Unexpected Management Connection close count", 0, results.size()); - _jmxc.close(); + _jmxUtils.close(); - results = _monitor.findMatches("MNG-1008"); + results = _monitor.findMatches("MNG-1008"); - assertEquals("Unexpected Management Connection count", 1, results.size()); + assertEquals("Unexpected Management Connection count", 1, results.size()); - assertEquals("Close does not have same id as open,", connectionID, - Integer.parseInt(fromActor(getLog(results.get(0))).charAt(4) + "")); - } + assertEquals("Close does not have same id as open,", connectionID, + Integer.parseInt(fromActor(getLog(results.get(0))).charAt(4) + "")); } /** @@ -159,56 +137,40 @@ public class ManagementActorLoggingTest extends AbstractTestLogging */ public void testConnectionCloseViaManagement() throws IOException, Exception { - if (isExternalBroker()) + //Create a connection to the broker + Connection connection = getConnection(); + + // Monitor the connection for an exception being thrown + // this should be a DisconnectionException but it is not this tests + // job to valiate that. Only use the exception as a synchronisation + // to check the log file for the Close message + final CountDownLatch exceptionReceived = new CountDownLatch(1); + connection.setExceptionListener(new ExceptionListener() { - - //Create a connection to the broker - Connection connection = getConnection(); - - // Monitor the connection for an exception being thrown - // this should be a DisconnectionException but it is not this tests - // job to valiate that. Only use the exception as a synchronisation - // to check the log file for the Close message - final CountDownLatch exceptionReceived = new CountDownLatch(1); - connection.setExceptionListener(new ExceptionListener() + public void onException(JMSException e) { - public void onException(JMSException e) - { - //Failover being attempted. - exceptionReceived.countDown(); - } - }); - - //Remove the connection close from any 0-10 connections - _monitor.reset(); + //Failover being attempted. + exceptionReceived.countDown(); + } + }); - // Get all active AMQP connections - AllObjects allObject = new AllObjects(_mbsc); - allObject.querystring = "org.apache.qpid:type=VirtualHost.Connection,*"; + //Remove the connection close from any 0-10 connections + _monitor.reset(); - Set objectNames = allObject.returnObjects(); + // Get a managedConnection + ManagedConnection mangedConnection = _jmxUtils.getManagedObject(ManagedConnection.class, "org.apache.qpid:type=VirtualHost.Connection,*"); - assertEquals("More than one test connection returned", 1, objectNames.size()); + //Close the connection + mangedConnection.closeConnection(); - ObjectName connectionName = objectNames.iterator().next(); + //Wait for the connection to close + assertTrue("Timed out waiting for conneciton to report close", + exceptionReceived.await(2, TimeUnit.SECONDS)); - ManagedConnection mangedConnection = MBeanServerInvocationHandler. - newProxyInstance(_mbsc, connectionName, - ManagedConnection.class, false); + //Validate results + List results = _monitor.findMatches("CON-1002"); - - //Close the connection - mangedConnection.closeConnection(); - - //Wait for the connection to close - assertTrue("Timed out waiting for conneciton to report close", - exceptionReceived.await(2, TimeUnit.SECONDS)); - - //Validate results - List results = _monitor.findMatches("CON-1002"); - - assertEquals("Unexpected Connection Close count", 1, results.size()); - } + assertEquals("Unexpected Connection Close count", 1, results.size()); } /** @@ -234,114 +196,100 @@ public class ManagementActorLoggingTest extends AbstractTestLogging */ public void testCreateExchangeDirectTransientViaManagementConsole() throws IOException, JMException { - if (isExternalBroker()) - { - //Remove any previous exchange declares - _monitor.reset(); - - createExchange("direct"); + _monitor.reset(); - // Validate + _jmxUtils.createExchange("test", "direct", null, false); - //1 - ID is correct - List results = _monitor.findMatches("EXH-1001"); + // Validate - assertEquals("More than one exchange creation found", 1, results.size()); + //1 - ID is correct + List results = _monitor.findMatches("EXH-1001"); - String log = getLog(results.get(0)); + assertEquals("More than one exchange creation found", 1, results.size()); - // Validate correct exchange name - assertTrue("Incorrect exchange name created:" + log, log.endsWith(getName())); + String log = getLog(results.get(0)); - // Validate it was a management actor. - String actor = fromActor(log); - assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); + // Validate correct exchange name + assertTrue("Incorrect exchange name created:" + log, log.endsWith(getName())); - } + // Validate it was a management actor. + String actor = fromActor(log); + assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); } public void testCreateExchangeTopicTransientViaManagementConsole() throws IOException, JMException { - if (isExternalBroker()) - { - //Remove any previous exchange declares - _monitor.reset(); + //Remove any previous exchange declares + _monitor.reset(); - createExchange("topic"); + _jmxUtils.createExchange("test", "topic", null, false); - // Validate + // Validate - //1 - ID is correct - List results = _monitor.findMatches("EXH-1001"); + //1 - ID is correct + List results = _monitor.findMatches("EXH-1001"); - assertEquals("More than one exchange creation found", 1, results.size()); + assertEquals("More than one exchange creation found", 1, results.size()); - String log = getLog(results.get(0)); + String log = getLog(results.get(0)); - // Validate correct exchange name - assertTrue("Incorrect exchange name created:" + log, log.endsWith(getName())); + // Validate correct exchange name + assertTrue("Incorrect exchange name created:" + log, log.endsWith(getName())); - // Validate it was a management actor. - String actor = fromActor(log); - assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); + // Validate it was a management actor. + String actor = fromActor(log); + assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); - } } public void testCreateExchangeFanoutTransientViaManagementConsole() throws IOException, JMException { - if (isExternalBroker()) - { - //Remove any previous exchange declares - _monitor.reset(); + //Remove any previous exchange declares + _monitor.reset(); - createExchange("fanout"); + _jmxUtils.createExchange("test", "fanout", null, false); - // Validate + // Validate - //1 - ID is correct - List results = _monitor.findMatches("EXH-1001"); + //1 - ID is correct + List results = _monitor.findMatches("EXH-1001"); - assertEquals("More than one exchange creation found", 1, results.size()); + assertEquals("More than one exchange creation found", 1, results.size()); - String log = getLog(results.get(0)); + String log = getLog(results.get(0)); - // Validate correct exchange name - assertTrue("Incorrect exchange name created:" + log, log.endsWith(getName())); + // Validate correct exchange name + assertTrue("Incorrect exchange name created:" + log, log.endsWith(getName())); - // Validate it was a management actor. - String actor = fromActor(log); - assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); + // Validate it was a management actor. + String actor = fromActor(log); + assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); - } } public void testCreateExchangeHeadersTransientViaManagementConsole() throws IOException, JMException { - if (isExternalBroker()) - { - //Remove any previous exchange declares - _monitor.reset(); + //Remove any previous exchange declares + _monitor.reset(); - createExchange("headers"); + _jmxUtils.createExchange("test", "headers", null, false); - // Validate + // Validate - //1 - ID is correct - List results = _monitor.findMatches("EXH-1001"); + //1 - ID is correct + List results = _monitor.findMatches("EXH-1001"); - assertEquals("More than one exchange creation found", 1, results.size()); + assertEquals("More than one exchange creation found", 1, results.size()); - String log = getLog(results.get(0)); + String log = getLog(results.get(0)); - // Validate correct exchange name - assertTrue("Incorrect exchange name created:" + log, log.endsWith(getName())); + // Validate correct exchange name + assertTrue("Incorrect exchange name created:" + log, log.endsWith(getName())); - // Validate it was a management actor. - String actor = fromActor(log); - assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); + // Validate it was a management actor. + String actor = fromActor(log); + assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); - } } /** @@ -365,29 +313,26 @@ public class ManagementActorLoggingTest extends AbstractTestLogging */ public void testCreateQueueTransientViaManagementConsole() throws IOException, JMException { - if (isExternalBroker()) - { - //Remove any previous queue declares - _monitor.reset(); + //Remove any previous queue declares + _monitor.reset(); - createQueue(); + _jmxUtils.createQueue("test", getName(), null, false); - // Validate + // Validate - List results = _monitor.findMatches("QUE-1001"); + List results = _monitor.findMatches("QUE-1001"); - assertEquals("More than one queue creation found", 1, results.size()); + assertEquals("More than one queue creation found", 1, results.size()); - String log = getLog(results.get(0)); + String log = getLog(results.get(0)); - // Validate correct queue name - String subject = fromSubject(log); - assertEquals("Incorrect queue name created", getName(), AbstractTestLogSubject.getSlice("qu", subject)); + // Validate correct queue name + String subject = fromSubject(log); + assertEquals("Incorrect queue name created", getName(), AbstractTestLogSubject.getSlice("qu", subject)); - // Validate it was a management actor. - String actor = fromActor(log); - assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); - } + // Validate it was a management actor. + String actor = fromActor(log); + assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); } /** @@ -411,34 +356,29 @@ public class ManagementActorLoggingTest extends AbstractTestLogging */ public void testQueueDeleteViaManagementConsole() throws IOException, JMException { - if (isExternalBroker()) - { - //Remove any previous queue declares - _monitor.reset(); + //Remove any previous queue declares + _monitor.reset(); - createQueue(); + _jmxUtils.createQueue("test", getName(), null, false); - ManagedBroker managedBroker = MBeanServerInvocationHandler. - newProxyInstance(_mbsc, getVirtualHostManagerObjectName(), - ManagedBroker.class, false); + ManagedBroker managedBroker = _jmxUtils.getManagedBroker("test"); - managedBroker.deleteQueue(getName()); + managedBroker.deleteQueue(getName()); - List results = _monitor.findMatches("QUE-1002"); + List results = _monitor.findMatches("QUE-1002"); - assertEquals("More than one queue deletion found", 1, results.size()); + assertEquals("More than one queue deletion found", 1, results.size()); - String log = getLog(results.get(0)); + String log = getLog(results.get(0)); - // Validate correct binding - String subject = fromSubject(log); - assertEquals("Incorrect queue named in delete", getName(), AbstractTestLogSubject.getSlice("qu", subject)); + // Validate correct binding + String subject = fromSubject(log); + assertEquals("Incorrect queue named in delete", getName(), AbstractTestLogSubject.getSlice("qu", subject)); - // Validate it was a management actor. - String actor = fromActor(log); - assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); + // Validate it was a management actor. + String actor = fromActor(log); + assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); - } } /** @@ -462,98 +402,83 @@ public class ManagementActorLoggingTest extends AbstractTestLogging */ public void testBindingCreateOnDirectViaManagementConsole() throws IOException, JMException { - if (isExternalBroker()) - { - //Remove any previous queue declares - _monitor.reset(); + //Remove any previous queue declares + _monitor.reset(); - createQueue(); + _jmxUtils.createQueue("test", getName(), null, false); - ManagedExchange managedExchange = MBeanServerInvocationHandler. - newProxyInstance(_mbsc, getExchange("amq.direct"), - ManagedExchange.class, false); + ManagedExchange managedExchange = _jmxUtils.getManagedExchange("amq.direct"); - managedExchange.createNewBinding(getName(), getName()); + managedExchange.createNewBinding(getName(), getName()); - List results = _monitor.findMatches("BND-1001"); + List results = _monitor.findMatches("BND-1001"); - assertEquals("More than one bind creation found", 1, results.size()); + assertEquals("More than one bind creation found", 1, results.size()); - String log = getLog(results.get(0)); + String log = getLog(results.get(0)); - // Validate correct binding - String subject = fromSubject(log); - assertEquals("Incorrect queue named in create", getName(), AbstractTestLogSubject.getSlice("qu", subject)); - assertEquals("Incorrect routing key in create", getName(), AbstractTestLogSubject.getSlice("rk", subject)); + // Validate correct binding + String subject = fromSubject(log); + assertEquals("Incorrect queue named in create", getName(), AbstractTestLogSubject.getSlice("qu", subject)); + assertEquals("Incorrect routing key in create", getName(), AbstractTestLogSubject.getSlice("rk", subject)); - // Validate it was a management actor. - String actor = fromActor(log); - assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); - } + // Validate it was a management actor. + String actor = fromActor(log); + assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); } public void testBindingCreateOnTopicViaManagementConsole() throws IOException, JMException { - if (isExternalBroker()) - { - //Remove any previous queue declares - _monitor.reset(); + //Remove any previous queue declares + _monitor.reset(); - createQueue(); + _jmxUtils.createQueue("test", getName(), null, false); - ManagedExchange managedExchange = MBeanServerInvocationHandler. - newProxyInstance(_mbsc, getExchange("amq.topic"), - ManagedExchange.class, false); + ManagedExchange managedExchange = _jmxUtils.getManagedExchange("amq.topic"); - managedExchange.createNewBinding(getName(), getName()); + managedExchange.createNewBinding(getName(), getName()); - List results = _monitor.findMatches("BND-1001"); + List results = _monitor.findMatches("BND-1001"); - assertEquals("More than one bind creation found", 1, results.size()); + assertEquals("More than one bind creation found", 1, results.size()); - String log = getLog(results.get(0)); + String log = getLog(results.get(0)); - // Validate correct binding - String subject = fromSubject(log); - assertEquals("Incorrect queue named in create", getName(), AbstractTestLogSubject.getSlice("qu", subject)); - assertEquals("Incorrect routing key in create", getName(), AbstractTestLogSubject.getSlice("rk", subject)); + // Validate correct binding + String subject = fromSubject(log); + assertEquals("Incorrect queue named in create", getName(), AbstractTestLogSubject.getSlice("qu", subject)); + assertEquals("Incorrect routing key in create", getName(), AbstractTestLogSubject.getSlice("rk", subject)); - // Validate it was a management actor. - String actor = fromActor(log); - assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); - } + // Validate it was a management actor. + String actor = fromActor(log); + assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); } public void testBindingCreateOnFanoutViaManagementConsole() throws IOException, JMException { - if (isExternalBroker()) - { - //Remove any previous queue declares - _monitor.reset(); + //Remove any previous queue declares + _monitor.reset(); - createQueue(); + _jmxUtils.createQueue("test", getName(), null, false); - ManagedExchange managedExchange = MBeanServerInvocationHandler. - newProxyInstance(_mbsc, getExchange("amq.fanout"), - ManagedExchange.class, false); + ManagedExchange managedExchange = _jmxUtils.getManagedExchange("amq.fanout"); - managedExchange.createNewBinding(getName(), getName()); + managedExchange.createNewBinding(getName(), getName()); - List results = _monitor.findMatches("BND-1001"); + List results = _monitor.findMatches("BND-1001"); - assertEquals("More than one bind creation found", 1, results.size()); + assertEquals("More than one bind creation found", 1, results.size()); - String log = getLog(results.get(0)); + String log = getLog(results.get(0)); - // Validate correct binding - String subject = fromSubject(log); - assertEquals("Incorrect queue named in create", getName(), AbstractTestLogSubject.getSlice("qu", subject)); - assertEquals("Incorrect routing key in create", "*", AbstractTestLogSubject.getSlice("rk", subject)); + // Validate correct binding + String subject = fromSubject(log); + assertEquals("Incorrect queue named in create", getName(), AbstractTestLogSubject.getSlice("qu", subject)); + assertEquals("Incorrect routing key in create", "*", AbstractTestLogSubject.getSlice("rk", subject)); - // Validate it was a management actor. - String actor = fromActor(log); - assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); - } + // Validate it was a management actor. + String actor = fromActor(log); + assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); } /** @@ -578,114 +503,28 @@ public class ManagementActorLoggingTest extends AbstractTestLogging */ public void testUnRegisterExchangeViaManagementConsole() throws IOException, JMException { - if (isExternalBroker()) - { + //Remove any previous queue declares + _monitor.reset(); - //Remove any previous queue declares - _monitor.reset(); + _jmxUtils.createExchange("test", "direct", null, false); - createExchange("direct"); + ManagedBroker managedBroker = _jmxUtils.getManagedBroker("test"); - ManagedBroker managedBroker = MBeanServerInvocationHandler. - newProxyInstance(_mbsc, getVirtualHostManagerObjectName(), - ManagedBroker.class, false); + managedBroker.unregisterExchange(getName()); - managedBroker.unregisterExchange(getName()); + List results = _monitor.findMatches("EXH-1002"); - List results = _monitor.findMatches("EXH-1002"); - - assertEquals("More than one exchange deletion found", 1, results.size()); - - String log = getLog(results.get(0)); - - // Validate correct binding - String subject = fromSubject(log); - assertEquals("Incorrect exchange named in delete", "direct/" + getName(), AbstractTestLogSubject.getSlice("ex", subject)); - - // Validate it was a management actor. - String actor = fromActor(log); - assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); - } - } - - /** - * Create a non-durable test exchange with the current test name - * - * @throws JMException - is thrown if a exchange with this testName already exists - * @throws IOException - if there is a problem with the JMX Connection - * @throws javax.management.MBeanException - * - if there is another problem creating the exchange - */ - private void createExchange(String type) - throws JMException, IOException, MBeanException - { - ManagedBroker managedBroker = MBeanServerInvocationHandler. - newProxyInstance(_mbsc, getVirtualHostManagerObjectName(), - ManagedBroker.class, false); - - managedBroker.createNewExchange(getName(), type, false); - } - - /** - * 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 - */ - private void createQueue() - throws JMException, IOException - { - ManagedBroker managedBroker = MBeanServerInvocationHandler. - newProxyInstance(_mbsc, getVirtualHostManagerObjectName(), - ManagedBroker.class, false); - - managedBroker.createNewQueue(getName(), null, false); - } - - /** - * Retrive the ObjectName for the test Virtualhost. - * - * This is then use to create aproxy to the ManagedBroker MBean. - * - * @return the ObjectName for the 'test' VirtualHost. - */ - private ObjectName getVirtualHostManagerObjectName() - { - // Get the name of the test manager - AllObjects allObject = new AllObjects(_mbsc); - allObject.querystring = "org.apache.qpid:type=VirtualHost.VirtualHostManager,VirtualHost=test,*"; - - Set objectNames = allObject.returnObjects(); - - 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(); - } - - /** - * Retrive the ObjectName for the given Exchange on the test Virtualhost. - * - * This is then use to create aproxy to the ManagedExchange MBean. - * - * @param exchange The exchange to retireve e.g. 'direct' - * - * @return the ObjectName for the given exchange on the test VirtualHost. - */ - private ObjectName getExchange(String exchange) - { - // Get the name of the test manager - AllObjects allObject = new AllObjects(_mbsc); - allObject.querystring = "org.apache.qpid:type=VirtualHost.Exchange,VirtualHost=test,name=" + exchange + ",*"; + assertEquals("More than one exchange deletion found", 1, results.size()); - Set objectNames = allObject.returnObjects(); + String log = getLog(results.get(0)); - assertEquals("Incorrect number of exchange with name '" + exchange + - "' returned", 1, objectNames.size()); + // Validate correct binding + String subject = fromSubject(log); + assertEquals("Incorrect exchange named in delete", "direct/" + getName(), AbstractTestLogSubject.getSlice("ex", subject)); - // We have verified we have only one value in objectNames so return it - return objectNames.iterator().next(); + // Validate it was a management actor. + String actor = fromActor(log); + assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); } } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/configuration/ServerConfigurationFileTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/configuration/ServerConfigurationFileTest.java index c4803e121e..0a88ef391c 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/server/configuration/ServerConfigurationFileTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/configuration/ServerConfigurationFileTest.java @@ -40,6 +40,8 @@ public class ServerConfigurationFileTest extends QpidTestCase { fail("Unable to test without config file:" + _configFile); } + + saveTestConfiguration(); _serverConfig = new ServerConfiguration(_configFile); } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/AlertingTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/AlertingTest.java index 620b2a5161..683abee4da 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/AlertingTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/AlertingTest.java @@ -94,7 +94,7 @@ public class AlertingTest extends AbstractTestLogging { _connection = getConnection(); _session = _connection.createSession(true, Session.SESSION_TRANSACTED); - _destination = _session.createQueue("testQueue"); + _destination = _session.createQueue(getTestQueueName()); // Consumer is only used to actually create the destination _session.createConsumer(_destination).close(); @@ -116,14 +116,12 @@ public class AlertingTest extends AbstractTestLogging // Add the current contents of the log file to test output message.append(_monitor.readFile()); - // Write the server config file to test output - message.append("Server configuration file in use:\n"); - message.append(FileUtils.readFileAsString(_configFile)); + // Write the test config file to test output + message.append("Server configuration overrides in use:\n"); + message.append(FileUtils.readFileAsString(getTestConfigFile())); - // Write the virtualhost config file to test output - message.append("\nVirtualhost configuration file in use:\n"); - message.append(FileUtils.readFileAsString(ServerConfiguration. - flatConfig(_configFile).getString("virtualhosts"))); + message.append("\nVirtualhost maxMessageCount:\n"); + message.append((new ServerConfiguration(_configFile)).getConfig().getString("virtualhosts.virtualhost." + VIRTUALHOST + ".queues.maximumMessageCount")); fail(message.toString()); } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/DerbyMessageStoreLoggingTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/DerbyMessageStoreLoggingTest.java index 254ec9693d..cc3993249c 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/DerbyMessageStoreLoggingTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/DerbyMessageStoreLoggingTest.java @@ -28,6 +28,7 @@ import javax.jms.Connection; import javax.jms.Queue; import javax.jms.Session; import java.util.List; +import java.io.File; /** * The MessageStore test suite validates that the follow log messages as @@ -56,9 +57,9 @@ public class DerbyMessageStoreLoggingTest extends MemoryMessageStoreLoggingTest //We call super.setUp but this will not start the broker as that is //part of the test case. - // Load current configuration file to get the list of defined vhosts - Configuration configuration = ServerConfiguration.flatConfig(_configFile); - List vhosts = configuration.getList("virtualhosts.virtualhost.name"); + // Load the default configuration file to get the list of defined vhosts + ServerConfiguration configuration = new ServerConfiguration(new File(_configFile.getParent() + "/config.xml")); + List vhosts = configuration.getConfig().getList("virtualhosts.virtualhost.name"); // Make them all persistent i.e. Use DerbyMessageStore and // test that it logs correctly. @@ -97,8 +98,8 @@ public class DerbyMessageStoreLoggingTest extends MemoryMessageStoreLoggingTest assertTrue("MST messages not logged", results.size() > 0); // Load VirtualHost list from file. - Configuration configuration = ServerConfiguration.flatConfig(_configFile); - List vhosts = configuration.getList("virtualhosts.virtualhost.name"); + ServerConfiguration configuration = new ServerConfiguration(_configFile); + List vhosts = configuration.getConfig().getList("virtualhosts.virtualhost.name"); //Validate each vhost logs a creation results = _monitor.findMatches("MST-1002"); @@ -117,7 +118,7 @@ public class DerbyMessageStoreLoggingTest extends MemoryMessageStoreLoggingTest // the virtualhost name, found above. AND // the index that the virtualhost is within the configuration. // we can retrive that from the vhosts list previously extracted. - String fullStoreName = configuration.getString("virtualhosts.virtualhost(" + vhosts.indexOf(vhostName) + ")." + vhostName + ".store.class"); + String fullStoreName = configuration.getConfig().getString("virtualhosts.virtualhost(" + vhosts.indexOf(vhostName) + ")." + vhostName + ".store.class"); // Get the Simple class name from the expected class name of o.a.q.s.s.MMS String storeName = fullStoreName.substring(fullStoreName.lastIndexOf(".") + 1); @@ -160,8 +161,8 @@ public class DerbyMessageStoreLoggingTest extends MemoryMessageStoreLoggingTest assertTrue("MST messages not logged", results.size() > 0); // Load VirtualHost list from file. - Configuration configuration = ServerConfiguration.flatConfig(_configFile); - List vhosts = configuration.getList("virtualhosts.virtualhost.name"); + ServerConfiguration configuration = new ServerConfiguration(_configFile); + List vhosts = configuration.getConfig().getList("virtualhosts.virtualhost.name"); //Validate each vhost logs a creation results = _monitor.findMatches("MST-1004"); @@ -186,7 +187,7 @@ public class DerbyMessageStoreLoggingTest extends MemoryMessageStoreLoggingTest // the virtualhost name, found above. AND // the index that the virtualhost is within the configuration. // we can retrive that from the vhosts list previously extracted. - String fullStoreName = configuration.getString("virtualhosts.virtualhost(" + vhosts.indexOf(vhostName) + ")." + vhostName + ".store.class"); + String fullStoreName = configuration.getConfig().getString("virtualhosts.virtualhost(" + vhosts.indexOf(vhostName) + ")." + vhostName + ".store.class"); // Get the Simple class name from the expected class name of o.a.q.s.s.MMS String storeName = fullStoreName.substring(fullStoreName.lastIndexOf(".") + 1); @@ -227,8 +228,8 @@ public class DerbyMessageStoreLoggingTest extends MemoryMessageStoreLoggingTest assertTrue("MST messages not logged", results.size() > 0); // Load VirtualHost list from file. - Configuration configuration = ServerConfiguration.flatConfig(_configFile); - List vhosts = configuration.getList("virtualhosts.virtualhost.name"); + ServerConfiguration configuration = new ServerConfiguration(_configFile); + List vhosts = configuration.getConfig().getList("virtualhosts.virtualhost.name"); //Validate each vhost logs a creation results = _monitor.findMatches("MST-1006"); @@ -253,7 +254,7 @@ public class DerbyMessageStoreLoggingTest extends MemoryMessageStoreLoggingTest // the virtualhost name, found above. AND // the index that the virtualhost is within the configuration. // we can retrive that from the vhosts list previously extracted. - String fullStoreName = configuration.getString("virtualhosts.virtualhost(" + vhosts.indexOf(vhostName) + ")." + vhostName + ".store.class"); + String fullStoreName = configuration.getConfig().getString("virtualhosts.virtualhost(" + vhosts.indexOf(vhostName) + ")." + vhostName + ".store.class"); // Get the Simple class name from the expected class name of o.a.q.s.s.MMS String storeName = fullStoreName.substring(fullStoreName.lastIndexOf(".") + 1); @@ -293,8 +294,8 @@ public class DerbyMessageStoreLoggingTest extends MemoryMessageStoreLoggingTest assertTrue("MST messages not logged", results.size() > 0); // Load VirtualHost list from file. - Configuration configuration = ServerConfiguration.flatConfig(_configFile); - List vhosts = configuration.getList("virtualhosts.virtualhost.name"); + ServerConfiguration configuration = new ServerConfiguration(_configFile); + List vhosts = configuration.getConfig().getList("virtualhosts.virtualhost.name"); //Validate each vhost logs a creation results = _monitor.findMatches("MST-1004 : Recovery Start :"); @@ -316,7 +317,7 @@ public class DerbyMessageStoreLoggingTest extends MemoryMessageStoreLoggingTest // the virtualhost name, found above. AND // the index that the virtualhost is within the configuration. // we can retrive that from the vhosts list previously extracted. - String fullStoreName = configuration.getString("virtualhosts.virtualhost(" + vhosts.indexOf(vhostName) + ")." + vhostName + ".store.class"); + String fullStoreName = configuration.getConfig().getString("virtualhosts.virtualhost(" + vhosts.indexOf(vhostName) + ")." + vhostName + ".store.class"); // Get the Simple class name from the expected class name of o.a.q.s.s.MMS String storeName = fullStoreName.substring(fullStoreName.lastIndexOf(".") + 1); @@ -358,8 +359,8 @@ public class DerbyMessageStoreLoggingTest extends MemoryMessageStoreLoggingTest assertTrue("MST messages not logged", results.size() > 0); // Load VirtualHost list from file. - Configuration configuration = ServerConfiguration.flatConfig(_configFile); - List vhosts = configuration.getList("virtualhosts.virtualhost.name"); + ServerConfiguration configuration = new ServerConfiguration(_configFile); + List vhosts = configuration.getConfig().getList("virtualhosts.virtualhost.name"); //Validate each vhost logs a creation results = _monitor.findMatches("MST-1006 : Recovery Complete :"); @@ -381,7 +382,7 @@ public class DerbyMessageStoreLoggingTest extends MemoryMessageStoreLoggingTest // the virtualhost name, found above. AND // the index that the virtualhost is within the configuration. // we can retrive that from the vhosts list previously extracted. - String fullStoreName = configuration.getString("virtualhosts.virtualhost(" + vhosts.indexOf(vhostName) + ")." + vhostName + ".store.class"); + String fullStoreName = configuration.getConfig().getString("virtualhosts.virtualhost(" + vhosts.indexOf(vhostName) + ")." + vhostName + ".store.class"); // Get the Simple class name from the expected class name of o.a.q.s.s.MMS String storeName = fullStoreName.substring(fullStoreName.lastIndexOf(".") + 1); @@ -500,8 +501,8 @@ public class DerbyMessageStoreLoggingTest extends MemoryMessageStoreLoggingTest assertTrue("MST messages not logged", results.size() > 0); // Load VirtualHost list from file. - Configuration configuration = ServerConfiguration.flatConfig(_configFile); - List vhosts = configuration.getList("virtualhosts.virtualhost.name"); + ServerConfiguration configuration = new ServerConfiguration(_configFile); + List vhosts = configuration.getConfig().getList("virtualhosts.virtualhost.name"); //Validate each vhost logs a creation results = _monitor.findMatches("MST-1004 : Recovery Start : " + queueName); @@ -542,7 +543,7 @@ public class DerbyMessageStoreLoggingTest extends MemoryMessageStoreLoggingTest // the virtualhost name, found above. AND // the index that the virtualhost is within the configuration. // we can retrive that from the vhosts list previously extracted. - String fullStoreName = configuration.getString("virtualhosts.virtualhost(" + vhosts.indexOf(vhostName) + ")." + vhostName + ".store.class"); + String fullStoreName = configuration.getConfig().getString("virtualhosts.virtualhost(" + vhosts.indexOf(vhostName) + ")." + vhostName + ".store.class"); // Get the Simple class name from the expected class name of o.a.q.s.s.MMS String storeName = fullStoreName.substring(fullStoreName.lastIndexOf(".") + 1); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/ManagementLoggingTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/ManagementLoggingTest.java index 11c003a2a7..8b7c881a32 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/ManagementLoggingTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/ManagementLoggingTest.java @@ -24,6 +24,7 @@ import junit.framework.AssertionFailedError; import org.apache.qpid.util.LogMonitor; import java.util.List; +import java.io.File; /** * Management Console Test Suite @@ -308,9 +309,8 @@ public class ManagementLoggingTest extends AbstractTestLogging // We expect the RMIConnector Server port to be 100 higher than // the RMI Server Port - int mPort = getPort() + (DEFAULT_MANAGEMENT_PORT - DEFAULT_PORT) + 100; - assertTrue("SSL Keystore entry expected(" + mPort + ").:" + getMessageString(log), - getMessageString(log).endsWith(getConfigurationStringProperty("management.ssl.keyStorePath"))); + assertTrue("SSL Keystore entry expected.:" + getMessageString(log), + getMessageString(log).endsWith(new File(getConfigurationStringProperty("management.ssl.keyStorePath")).getName())); } catch (AssertionFailedError afe) { diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/MemoryMessageStoreLoggingTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/MemoryMessageStoreLoggingTest.java index a1cbeca6de..2298ba4da0 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/MemoryMessageStoreLoggingTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/MemoryMessageStoreLoggingTest.java @@ -89,8 +89,8 @@ public class MemoryMessageStoreLoggingTest extends AbstractTestLogging assertEquals("MST-1001 is not the first MST message", "MST-1001", getMessageID(fromMessage(log))); // Load VirtualHost list from file. - Configuration configuration = ServerConfiguration.flatConfig(_configFile); - List vhosts = configuration.getList("virtualhosts.virtualhost.name"); + ServerConfiguration configuration = new ServerConfiguration(_configFile); + List vhosts = configuration.getConfig().getList("virtualhosts.virtualhost.name"); //Validate each vhost logs a creation results = _monitor.findMatches("MST-1001"); @@ -109,7 +109,7 @@ public class MemoryMessageStoreLoggingTest extends AbstractTestLogging // the virtualhost name, found above. AND // the index that the virtualhost is within the configuration. // we can retrive that from the vhosts list previously extracted. - String fullStoreName = configuration.getString("virtualhosts.virtualhost(" + vhosts.indexOf(vhostName) + ")." + vhostName + ".store.class"); + String fullStoreName = configuration.getConfig().getString("virtualhosts.virtualhost(" + vhosts.indexOf(vhostName) + ")." + vhostName + ".store.class"); // Get the Simple class name from the expected class name of o.a.q.s.s.MMS String storeName = fullStoreName.substring(fullStoreName.lastIndexOf(".") + 1); @@ -156,8 +156,8 @@ public class MemoryMessageStoreLoggingTest extends AbstractTestLogging assertTrue("MST messages not logged", results.size() > 0); // Load VirtualHost list from file. - Configuration configuration = ServerConfiguration.flatConfig(_configFile); - List vhosts = configuration.getList("virtualhosts.virtualhost.name"); + ServerConfiguration configuration = new ServerConfiguration(_configFile); + List vhosts = configuration.getConfig().getList("virtualhosts.virtualhost.name"); //Validate each vhost logs a creation results = _monitor.findMatches("MST-1003"); @@ -176,7 +176,7 @@ public class MemoryMessageStoreLoggingTest extends AbstractTestLogging // the virtualhost name, found above. AND // the index that the virtualhost is within the configuration. // we can retrive that from the vhosts list previously extracted. - String fullStoreName = configuration.getString("virtualhosts.virtualhost(" + vhosts.indexOf(vhostName) + ")." + vhostName + ".store.class"); + String fullStoreName = configuration.getConfig().getString("virtualhosts.virtualhost(" + vhosts.indexOf(vhostName) + ")." + vhostName + ".store.class"); // Get the Simple class name from the expected class name of o.a.q.s.s.MMS String storeName = fullStoreName.substring(fullStoreName.lastIndexOf(".") + 1); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/VirtualHostLoggingTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/VirtualHostLoggingTest.java index 7bf644508e..f4a0c8b27d 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/VirtualHostLoggingTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/VirtualHostLoggingTest.java @@ -64,8 +64,8 @@ public class VirtualHostLoggingTest extends AbstractTestLogging try { // Validation - Configuration configuration = ServerConfiguration.flatConfig(_configFile); - List vhosts = configuration.getList("virtualhosts.virtualhost.name"); + ServerConfiguration configuration = new ServerConfiguration(_configFile); + List vhosts = configuration.getConfig().getList("virtualhosts.virtualhost.name"); //Validate each vhost logs a creation results = _monitor.findMatches("VHT-1001"); @@ -117,8 +117,8 @@ public class VirtualHostLoggingTest extends AbstractTestLogging { // Validation - Configuration configuration = ServerConfiguration.flatConfig(_configFile); - List vhosts = configuration.getList("virtualhosts.virtualhost.name"); + ServerConfiguration configuration = new ServerConfiguration(_configFile); + List vhosts = configuration.getConfig().getList("virtualhosts.virtualhost.name"); //Validate each vhost logs a creation results = _monitor.findMatches("VHT-1002"); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/ModelTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/ModelTest.java new file mode 100644 index 0000000000..078b8f43ce --- /dev/null +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/ModelTest.java @@ -0,0 +1,299 @@ +/* + * + * 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.queue; + +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.management.common.mbeans.ManagedBroker; +import org.apache.qpid.management.common.mbeans.ManagedQueue; +import org.apache.qpid.test.utils.JMXTestUtils; +import org.apache.qpid.test.utils.QpidTestCase; + +import javax.jms.Connection; +import javax.jms.JMSException; +import javax.jms.Session; +import javax.management.JMException; +import javax.management.MBeanException; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.UndeclaredThrowableException; + +/** + * This Test validates the Queue Model on the broker. + * Currently it has some basic queue creation / deletion tests. + * However, it should be expanded to include other tests that relate to the + * model. i.e. + * + * The Create and Delete tests should ensure that the requisite logging is + * performed. + * + * Additions to this suite would be to complete testing of creations, validating + * fields such as owner/exclusive, autodelete and priority are correctly set. + * + * Currently this test uses the JMX interface to validate that the queue has + * been declared as expected so these tests cannot run against a CPP broker. + * + * + * Tests should ensure that they clean up after themselves. + * e,g. Durable queue creation test should perform a queue delete. + */ +public class ModelTest extends QpidTestCase +{ + + private static final String USER = "admin"; + private JMXTestUtils _jmxUtils; + private static final String VIRTUALHOST_NAME = "test"; + + @Override + public void setUp() throws Exception + { + // Create a JMX Helper + _jmxUtils = new JMXTestUtils(this, USER, USER); + _jmxUtils.setUp(); + super.setUp(); + + // Open the JMX Connection + _jmxUtils.open(); + } + + @Override + public void tearDown() throws Exception + { + // Close the JMX Connection + _jmxUtils.close(); + super.tearDown(); + } + + /** + * Test that a transient queue can be created via AMQP. + * + * @throws Exception On unexpected error + */ + public void testQueueCreationTransientViaAMQP() throws Exception + { + Connection connection = getConnection(); + + String queueName = getTestQueueName(); + boolean durable = false; + boolean autoDelete = false; + boolean exclusive = false; + + createViaAMQPandValidateViaJMX(connection, queueName, durable, + autoDelete, exclusive); + } + + /** + * Test that a durable queue can be created via AMQP. + * + * @throws Exception On unexpected error + */ + + public void testQueueCreationDurableViaAMQP() throws Exception + { + Connection connection = getConnection(); + + String queueName = getTestQueueName(); + boolean durable = true; + boolean autoDelete = false; + boolean exclusive = false; + + createViaAMQPandValidateViaJMX(connection, queueName, durable, + autoDelete, exclusive); + + // Clean up + ManagedBroker managedBroker = + _jmxUtils.getManagedBroker(VIRTUALHOST_NAME); + managedBroker.deleteQueue(queueName); + } + + /** + * Test that a transient queue can be created via JMX. + * + * @throws IOException if there is a problem via the JMX connection + * @throws javax.management.JMException if there is a problem with the JMX command + */ + public void testCreationTransientViaJMX() throws IOException, JMException + { + String name = getName(); + String owner = null; + boolean durable = false; + + createViaJMXandValidateViaJMX(name, owner, durable, durable); + } + + /** + * Test that a durable queue can be created via JMX. + * + * @throws IOException if there is a problem via the JMX connection + * @throws javax.management.JMException if there is a problem with the JMX command + */ + public void testCreationDurableViaJMX() throws IOException, JMException + { + String name = getName(); + String owner = null; + boolean durable = true; + + createViaJMXandValidateViaJMX(name, owner, durable, durable); + + // Clean up + ManagedBroker managedBroker = + _jmxUtils.getManagedBroker(VIRTUALHOST_NAME); + managedBroker.deleteQueue(name); + } + + /** + * Test that a transient queue can be deleted via JMX. + * + * @throws IOException if there is a problem via the JMX connection + * @throws javax.management.JMException if there is a problem with the JMX command + */ + public void testDeletionTransientViaJMX() throws IOException, JMException + { + String name = getName(); + + _jmxUtils.createQueue(VIRTUALHOST_NAME, name, null, false); + + ManagedBroker managedBroker = _jmxUtils. + getManagedBroker(VIRTUALHOST_NAME); + + try + { + managedBroker.deleteQueue(name); + } + catch (UndeclaredThrowableException e) + { + fail(((MBeanException) ((InvocationTargetException) + e.getUndeclaredThrowable()).getTargetException()).getTargetException().getMessage()); + } + } + + /** + * Test that a durable queue can be created via JMX. + * + * @throws IOException if there is a problem via the JMX connection + * @throws javax.management.JMException if there is a problem with the JMX command + */ + public void testDeletionDurableViaJMX() throws IOException, JMException + { + String name = getName(); + + _jmxUtils.createQueue(VIRTUALHOST_NAME, name, null, true); + + ManagedBroker managedBroker = _jmxUtils. + getManagedBroker(VIRTUALHOST_NAME); + + try + { + managedBroker.deleteQueue(name); + } + catch (UndeclaredThrowableException e) + { + fail(((MBeanException) ((InvocationTargetException) + e.getUndeclaredThrowable()).getTargetException()).getTargetException().getMessage()); + } + } + + /* + * Helper Methods + */ + + /** + * Using the provided JMS Connection create a queue using the AMQP extension + * with the given properties and then validate it was created correctly via + * the JMX Connection + * + * @param connection Qpid JMS Connection + * @param queueName String the desired QueueName + * @param durable boolean if the queue should be durable + * @param autoDelete boolean if the queue is an autoDelete queue + * @param exclusive boolean if the queue is exclusive + * + * @throws AMQException if there is a problem with the createQueue call + * @throws JMException if there is a problem with the JMX validatation + * @throws IOException if there is a problem with the JMX connection + * @throws JMSException if there is a problem creating the JMS Session + */ + private void createViaAMQPandValidateViaJMX(Connection connection, + String queueName, + boolean durable, + boolean autoDelete, + boolean exclusive) + throws AMQException, JMException, IOException, JMSException + { + AMQSession session = (AMQSession) connection.createSession(false, + Session.AUTO_ACKNOWLEDGE); + + session.createQueue(new AMQShortString(queueName), + autoDelete, durable, exclusive); + + validateQueueViaJMX(queueName, exclusive ? ((AMQConnection) connection). + getUsername() : null, durable, autoDelete); + } + + /** + * Use the JMX Helper to create a queue with the given properties and then + * validate it was created correctly via the JMX Connection + * + * @param queueName String the desired QueueName + * @param owner String the owner value that should be set + * @param durable boolean if the queue should be durable + * @param autoDelete boolean if the queue is an autoDelete queue + * + * @throws JMException if there is a problem with the JMX validatation + * @throws IOException if there is a problem with the JMX connection + */ + private void createViaJMXandValidateViaJMX(String queueName, String owner, + boolean durable, boolean autoDelete) + throws JMException, IOException + { + _jmxUtils.createQueue(VIRTUALHOST_NAME, queueName, owner, durable); + + validateQueueViaJMX(queueName, owner, durable, autoDelete); + } + + /** + * Validate that a queue with the given properties exists on the broker + * + * @param queueName String the desired QueueName + * @param owner String the owner value that should be set + * @param durable boolean if the queue should be durable + * @param autoDelete boolean if the queue is an autoDelete queue + * + * @throws JMException if there is a problem with the JMX validatation + * @throws IOException if there is a problem with the JMX connection + */ + private void validateQueueViaJMX(String queueName, String owner, boolean durable, boolean autoDelete) + throws JMException, IOException + { + ManagedQueue managedQueue = _jmxUtils. + getManagedObject(ManagedQueue.class, + _jmxUtils.getQueueObjectName(VIRTUALHOST_NAME, + queueName)); + + assertEquals(queueName, managedQueue.getName()); + assertEquals(String.valueOf(owner), managedQueue.getOwner()); + assertEquals(durable, managedQueue.isDurable()); + assertEquals(autoDelete, managedQueue.isAutoDelete()); + } + +} diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/SimpleACLTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/SimpleACLTest.java index f402522a19..bb7b5efc75 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/SimpleACLTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/SimpleACLTest.java @@ -21,6 +21,7 @@ package org.apache.qpid.server.security.acl; + import junit.framework.TestCase; import org.apache.log4j.BasicConfigurator; @@ -30,6 +31,7 @@ import org.apache.qpid.client.*; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.registry.ConfigurationFileApplicationRegistry; +import org.apache.qpid.AMQConnectionFailureException; import org.apache.qpid.AMQException; import org.apache.qpid.test.utils.QpidTestCase; import org.apache.qpid.jms.ConnectionListener; @@ -37,6 +39,7 @@ import org.apache.qpid.url.URLSyntaxException; import javax.jms.*; import javax.jms.IllegalStateException; +import javax.naming.NamingException; import java.io.File; import java.util.ArrayList; @@ -51,46 +54,30 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E public void setUp() throws Exception { - //Shutdown the QTC broker - stopBroker(); - - // Initialise ACLs. - final String QpidExampleHome = System.getProperty("QPID_EXAMPLE_HOME"); - final File defaultaclConfigFile = new File(QpidExampleHome, "etc/acl.config.xml"); - - if (!defaultaclConfigFile.exists()) - { - System.err.println("Configuration file not found:" + defaultaclConfigFile); - fail("Configuration file not found:" + defaultaclConfigFile); - } + final String QPID_HOME = System.getProperty("QPID_HOME"); - if (System.getProperty("QPID_HOME") == null) + if (QPID_HOME == null) { fail("QPID_HOME not set"); } - ConfigurationFileApplicationRegistry config = new ConfigurationFileApplicationRegistry(defaultaclConfigFile); - ApplicationRegistry.initialise(config, ApplicationRegistry.DEFAULT_INSTANCE); - TransportConnection.createVMBroker(ApplicationRegistry.DEFAULT_INSTANCE); - } + // Initialise ACLs. + _configFile = new File(QPID_HOME, "etc/config-systests-acl.xml"); - public void tearDown() - { - TransportConnection.killVMBroker(ApplicationRegistry.DEFAULT_INSTANCE); - ApplicationRegistry.remove(ApplicationRegistry.DEFAULT_INSTANCE); + super.setUp(); } - public String createConnectionString(String username, String password, String broker) + public String createConnectionString(String username, String password) { - return "amqp://" + username + ":" + password + "@clientid/test?brokerlist='" + broker + "?retries='0''"; + return "amqp://" + username + ":" + password + "@clientid/test?brokerlist='" + getBroker() + "?retries='0''"; } public void testAccessAuthorized() throws AMQException, URLSyntaxException { try { - Connection conn = createConnection("client", "guest"); + Connection conn = getConnection("client", "guest"); Session sesh = conn.createSession(true, Session.SESSION_TRANSACTED); @@ -103,28 +90,32 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E } catch (Exception e) { - fail("Connection was not created due to:" + e.getMessage()); + fail("Connection was not created due to:" + e); } } - public void testAccessNoRights() throws URLSyntaxException, JMSException + public void testAccessNoRights() throws Exception { try { - Connection conn = createConnection("guest", "guest"); + Connection conn = getConnection("guest", "guest"); //Attempt to do do things to test connection. Session sesh = conn.createSession(true, Session.SESSION_TRANSACTED); conn.start(); sesh.rollback(); - conn.close(); fail("Connection was created."); } - catch (AMQException amqe) + catch (JMSException jmse) { - Throwable cause = amqe.getCause(); - assertEquals("Exception was wrong type", AMQAuthenticationException.class, cause.getClass()); + Throwable linkedException = jmse.getLinkedException(); + assertNotNull("Cause was null", linkedException); + + assertEquals("Linked Exception was wrong type", AMQConnectionFailureException.class, linkedException.getClass()); + + Throwable cause = linkedException.getCause(); + assertEquals("Cause was wrong type", AMQAuthenticationException.class, cause.getClass()); assertEquals("Incorrect error code thrown", 403, ((AMQAuthenticationException) cause).getErrorCode().getCode()); } } @@ -133,7 +124,7 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E { try { - Connection conn = createConnection("client", "guest"); + Connection conn = getConnection("client", "guest"); Session sesh = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); @@ -149,11 +140,11 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E } } - public void testClientConsumeFromNamedQueueInvalid() throws AMQException, URLSyntaxException + public void testClientConsumeFromNamedQueueInvalid() throws NamingException, Exception { try { - Connection conn = createConnection("client", "guest"); + Connection conn = getConnection("client", "guest"); //Prevent Failover ((AMQConnection) conn).setConnectionListener(this); @@ -180,7 +171,7 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E { try { - Connection conn = createConnection("client", "guest"); + Connection conn = getConnection("client", "guest"); Session sesh = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); @@ -198,11 +189,11 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E } } - public void testClientCreateNamedQueue() throws JMSException, URLSyntaxException, AMQException + public void testClientCreateNamedQueue() throws NamingException, JMSException, AMQException, Exception { try { - Connection conn = createConnection("client", "guest"); + Connection conn = getConnection("client", "guest"); Session sesh = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); @@ -216,6 +207,7 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E } catch (AMQAuthenticationException amqe) { + amqe.printStackTrace(); assertEquals("Incorrect error code thrown", 403, ((AMQAuthenticationException) amqe).getErrorCode().getCode()); } } @@ -224,7 +216,7 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E { try { - Connection conn = createConnection("client", "guest"); + Connection conn = getConnection("client", "guest"); ((AMQConnection) conn).setConnectionListener(this); @@ -251,7 +243,7 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E { try { - Connection conn = createConnection("client", "guest"); + Connection conn = getConnection("client", "guest"); ((AMQConnection) conn).setConnectionListener(this); @@ -277,11 +269,11 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E } } - public void testClientPublishInvalidQueueSuccess() throws AMQException, URLSyntaxException, JMSException, InterruptedException + public void testClientPublishInvalidQueueSuccess() throws AMQException, URLSyntaxException, JMSException, NamingException, Exception { try { - Connection conn = createConnection("client", "guest"); + Connection conn = getConnection("client", "guest"); ((AMQConnection) conn).setConnectionListener(this); @@ -323,7 +315,7 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E { try { - Connection conn = createConnection("server", "guest"); + Connection conn = getConnection("server", "guest"); Session sesh = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); @@ -339,11 +331,11 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E } } - public void testServerConsumeFromNamedQueueInvalid() throws AMQException, URLSyntaxException + public void testServerConsumeFromNamedQueueInvalid() throws AMQException, URLSyntaxException, NamingException, Exception { try - { - Connection conn = createConnection("client", "guest"); + { + Connection conn = getConnection("client", "guest"); Session sesh = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); @@ -364,11 +356,11 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E } } - public void testServerConsumeFromTemporaryQueue() throws AMQException, URLSyntaxException + public void testServerConsumeFromTemporaryQueue() throws AMQException, URLSyntaxException, NamingException, Exception { try { - Connection conn = createConnection("server","guest"); + Connection conn = getConnection("server", "guest"); Session sesh = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); @@ -388,30 +380,22 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E } } - private Connection createConnection(String username, String password) throws AMQException + @Override + public Connection getConnection(String username, String password) throws NamingException, JMSException { - AMQConnection connection = null; - try - { - connection = new AMQConnection(createConnectionString(username, password, BROKER)); - } - catch (URLSyntaxException e) - { - // This should never happen as we generate the URLs. - fail(e.getMessage()); - } + AMQConnection connection = (AMQConnection) super.getConnection(username, password); //Prevent Failover connection.setConnectionListener(this); - return (Connection)connection; + return (Connection) connection; } public void testServerCreateNamedQueueValid() throws JMSException, URLSyntaxException { try { - Connection conn = createConnection("server", "guest"); + Connection conn = getConnection("server", "guest"); Session sesh = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); @@ -428,11 +412,11 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E } } - public void testServerCreateNamedQueueInvalid() throws JMSException, URLSyntaxException, AMQException + public void testServerCreateNamedQueueInvalid() throws JMSException, URLSyntaxException, AMQException, NamingException, Exception { try { - Connection conn = createConnection("server", "guest"); + Connection conn = getConnection("server", "guest"); Session sesh = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); @@ -450,18 +434,18 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E } } - public void testServerCreateTemporaryQueueInvalid() throws JMSException, URLSyntaxException, AMQException + public void testServerCreateTemporaryQueueInvalid() throws NamingException, Exception { try { - Connection conn = createConnection("server", "guest"); + Connection conn = getConnection("server", "guest"); Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); conn.start(); session.createTemporaryQueue(); - + fail("Test failed as creation succeded."); //conn will be automatically closed } @@ -475,19 +459,19 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E } } - public void testServerCreateAutoDeleteQueueInvalid() throws JMSException, URLSyntaxException, AMQException + public void testServerCreateAutoDeleteQueueInvalid() throws NamingException, JMSException, AMQException, Exception { Connection connection = null; try { - connection = createConnection("server", "guest"); + connection = getConnection("server", "guest"); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); connection.start(); ((AMQSession) session).createQueue(new AMQShortString("again_ensure_auto_delete_queue_for_temporary"), - true, false, false); + true, false, false); fail("Test failed as creation succeded."); //connection will be automatically closed @@ -495,7 +479,7 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E catch (AMQAuthenticationException amqe) { assertEquals("Incorrect error code thrown", 403, amqe.getErrorCode().getCode()); - } + } } /** @@ -506,10 +490,10 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E * @throws URLSyntaxException * @throws JMSException */ - public void testServerPublishUsingTransactionSuccess() throws AMQException, URLSyntaxException, JMSException + public void testServerPublishUsingTransactionSuccess() throws AMQException, URLSyntaxException, JMSException, NamingException, Exception { //Set up the Server - Connection serverConnection = createConnection("server", "guest"); + Connection serverConnection = getConnection("server", "guest"); ((AMQConnection) serverConnection).setConnectionListener(this); @@ -522,7 +506,7 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E serverConnection.start(); //Set up the consumer - Connection clientConnection = createConnection("client", "guest"); + Connection clientConnection = getConnection("client", "guest"); //Send a test mesage Session clientSession = clientConnection.createSession(false, Session.AUTO_ACKNOWLEDGE); @@ -563,8 +547,6 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E //Send the message using a transaction as this will allow us to retrieve any errors that occur on the broker. serverSession.commit(); - - //Ensure Response is received. Message clientResponseMsg = clientResponse.receive(2000); assertNotNull("Client did not receive response message,", clientResponseMsg); @@ -588,11 +570,11 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E } } - public void testServerPublishInvalidQueueSuccess() throws AMQException, URLSyntaxException, JMSException + public void testServerPublishInvalidQueueSuccess() throws AMQException, URLSyntaxException, JMSException, NamingException, Exception { try { - Connection conn = createConnection("server", "guest"); + Connection conn = getConnection("server", "guest"); ((AMQConnection) conn).setConnectionListener(this); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/client/timeouts/SyncWaitDelayTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/client/timeouts/SyncWaitDelayTest.java index b13170efc9..a123fb290c 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/client/timeouts/SyncWaitDelayTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/client/timeouts/SyncWaitDelayTest.java @@ -57,26 +57,13 @@ public class SyncWaitDelayTest extends QpidTestCase public void setUp() throws Exception { - super.setUp(); - stopBroker(); - if (!_configFile.exists()) - { - fail("Unable to test without config file:" + _configFile); - } - XMLConfiguration configuration = new XMLConfiguration(_configFile); - configuration.setProperty("virtualhosts.virtualhost." + VIRTUALHOST+".store.class", "org.apache.qpid.server.store.SlowMessageStore"); - configuration.setProperty("virtualhosts.virtualhost." + VIRTUALHOST+".store.delays.commitTran.post", POST_COMMIT_DELAY); - configuration.setProperty("management.enabled", "false"); + setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST+".store.class", "org.apache.qpid.server.store.SlowMessageStore"); + setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST+".store.delays.commitTran.post", String.valueOf(POST_COMMIT_DELAY)); + setConfigurationProperty("management.enabled", "false"); - File tmpFile = File.createTempFile("configFile", "test"); - tmpFile.deleteOnExit(); - configuration.save(tmpFile); - - _configFile = tmpFile; - - startBroker(1); + super.setUp(); //Set the syncWrite timeout to be just larger than the delay on the commitTran. setSystemProperty("amqj.default_syncwrite_timeout", String.valueOf(SYNC_WRITE_TIMEOUT)); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/FailoverBaseCase.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/FailoverBaseCase.java index 1bef07fcd5..64bd1503ba 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/FailoverBaseCase.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/FailoverBaseCase.java @@ -21,6 +21,8 @@ package org.apache.qpid.test.utils; import javax.jms.Connection; +import javax.jms.JMSException; +import javax.naming.NamingException; import org.apache.qpid.util.FileUtils; @@ -64,7 +66,7 @@ public class FailoverBaseCase extends QpidTestCase * @return a connection * @throws Exception */ - public Connection getConnection() throws Exception + public Connection getConnection() throws JMSException, NamingException { Connection conn = (Boolean.getBoolean("profile.use_ssl"))? diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/JMXTestUtils.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/JMXTestUtils.java new file mode 100644 index 0000000000..3f8cdb9c25 --- /dev/null +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/JMXTestUtils.java @@ -0,0 +1,208 @@ +/* + * + * 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.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 javax.management.JMException; +import javax.management.MBeanException; +import javax.management.MBeanServerConnection; +import javax.management.MBeanServerInvocationHandler; +import javax.management.ObjectName; +import javax.management.remote.JMXConnector; +import java.io.IOException; +import java.util.Set; + +/** + * + */ +public class JMXTestUtils +{ + QpidTestCase _test; + MBeanServerConnection _mbsc; + JMXConnector _jmxc; + + private String USER; + private String PASSWORD; + + public JMXTestUtils(QpidTestCase test, String user, String password) + { + _test = test; + USER = user; + PASSWORD = password; + } + + public void setUp() throws IOException, ConfigurationException, Exception + { + _test.setConfigurationProperty("management.enabled", "true"); + } + + public void open() throws Exception + { + _jmxc = JMXConnnectionFactory.getJMXConnection( + 5000, "127.0.0.1", + _test.getManagementPort(_test.getPort()), USER, PASSWORD); + + _mbsc = _jmxc.getMBeanServerConnection(); + } + + public void close() throws IOException + { + _jmxc.close(); + } + + /** + * Create a non-durable test exchange with the current test 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 + */ + public void createExchange(String virtualHostName, String name, String type, boolean durable) + throws JMException, IOException, MBeanException + { + ManagedBroker managedBroker = getManagedBroker(virtualHostName); + + managedBroker.createNewExchange(name, type, durable); + } + + /** + * 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 + */ + public void createQueue(String virtualHostName, String name, String owner, boolean durable) + throws JMException, IOException + { + ManagedBroker managedBroker = getManagedBroker(virtualHostName); + + managedBroker.createNewQueue(name, owner, durable); + } + + /** + * Retrive the ObjectName for the test Virtualhost. + * + * This is then use to create aproxy to the ManagedBroker MBean. + * + * @return the ObjectName for the 'test' VirtualHost. + */ + public ObjectName getVirtualHostManagerObjectName(String vhostName) + { + // Get the name of the test manager + AllObjects allObject = new AllObjects(_mbsc); + allObject.querystring = "org.apache.qpid:type=VirtualHost.VirtualHostManager,VirtualHost=" + vhostName + ",*"; + + Set objectNames = allObject.returnObjects(); + + _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(); + } + + /** + * Retrive the ObjectName for the given Exchange on the test Virtualhost. + * + * This is then use to create aproxy to the ManagedExchange MBean. + * + * @param queue The exchange to retireve e.g. 'direct' + * + * @return the ObjectName for the given exchange on the test VirtualHost. + */ + public ObjectName getQueueObjectName(String virtualHostName, String queue) + { + // Get the name of the test manager + AllObjects allObject = new AllObjects(_mbsc); + allObject.querystring = "org.apache.qpid:type=VirtualHost.Queue,VirtualHost=" + virtualHostName + ",name=" + queue + ",*"; + + Set objectNames = allObject.returnObjects(); + + _test.assertEquals("Incorrect number of exchange with name '" + queue + + "' returned", 1, objectNames.size()); + + // We have verified we have only one value in objectNames so return it + return objectNames.iterator().next(); + } + + /** + * Retrive the ObjectName for the given Exchange on the test Virtualhost. + * + * This is then use to create aproxy 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. + */ + public ObjectName getExchangeObjectName(String virtualHostName, String exchange) + { + // Get the name of the test manager + AllObjects allObject = new AllObjects(_mbsc); + allObject.querystring = "org.apache.qpid:type=VirtualHost.Exchange,VirtualHost=" + virtualHostName + ",name=" + exchange + ",*"; + + Set objectNames = allObject.returnObjects(); + + _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(); + } + + public T getManagedObject(Class managedClass, String queryString) + { + AllObjects allObject = new AllObjects(_mbsc); + allObject.querystring = queryString; + + Set objectNames = allObject.returnObjects(); + + _test.assertEquals("More than one " + managedClass + " returned", 1, objectNames.size()); + + ObjectName objectName = objectNames.iterator().next(); + + return getManagedObject(managedClass, objectName); + } + + public T getManagedObject(Class managedClass, ObjectName objectName) + { + return MBeanServerInvocationHandler. + newProxyInstance(_mbsc, objectName, managedClass, false); + } + + public ManagedBroker getManagedBroker(String virtualHost) + { + return getManagedObject(ManagedBroker.class, getVirtualHostManagerObjectName(virtualHost).toString()); + } + + public ManagedExchange getManagedExchange(String exchangeName) + { + return MBeanServerInvocationHandler. + newProxyInstance(_mbsc, getExchangeObjectName("test", exchangeName), + ManagedExchange.class, false); + } +} diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidTestCase.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidTestCase.java index db096710dc..76e4118c96 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidTestCase.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidTestCase.java @@ -21,6 +21,7 @@ import junit.framework.TestCase; import junit.framework.TestResult; import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.XMLConfiguration; +import org.apache.qpid.AMQException; import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.AMQConnectionFactory; import org.apache.qpid.client.transport.TransportConnection; @@ -30,6 +31,7 @@ import org.apache.qpid.server.configuration.ServerConfiguration; import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.registry.ConfigurationFileApplicationRegistry; import org.apache.qpid.server.store.DerbyMessageStore; +import org.apache.qpid.url.URLSyntaxException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -73,6 +75,7 @@ public class QpidTestCase extends TestCase protected long RECEIVE_TIMEOUT = 1000l; private Map _setProperties = new HashMap(); + private XMLConfiguration _testConfiguration = new XMLConfiguration(); /** * Some tests are excluded when the property test.excludes is set to true. @@ -183,8 +186,7 @@ public class QpidTestCase extends TestCase public static final String QUEUE = "queue"; public static final String TOPIC = "topic"; /** Map to hold test defined environment properties */ - private Map _env; - + private Map _env; public QpidTestCase(String name) { @@ -335,7 +337,7 @@ public class QpidTestCase extends TestCase latch.countDown(); } - if (latch != null && line.contains(stopped)) + if (!seenReady && line.contains(stopped)) { stopLine = line; } @@ -368,7 +370,9 @@ public class QpidTestCase extends TestCase /** * Return the management portin use by the broker on this main port + * * @param mainPort the broker's main port. + * * @return the management port that corresponds to the broker on the given port */ protected int getManagementPort(int mainPort) @@ -415,9 +419,14 @@ public class QpidTestCase extends TestCase { port = getPort(port); + // Save any configuratio changes that have been made + saveTestConfiguration(); + Process process = null; if (_broker.equals(VM)) { + setConfigurationProperty("management.jmxport", String.valueOf(getManagementPort(port))); + saveTestConfiguration(); // create an in_VM broker ApplicationRegistry.initialise(new ConfigurationFileApplicationRegistry(_configFile), port); TransportConnection.createVMBroker(port); @@ -438,15 +447,35 @@ public class QpidTestCase extends TestCase env.put("PATH", env.get("PATH").concat(File.pathSeparator + qpidHome + "/bin")); //Add the test name to the broker run. - env.put("QPID_PNAME", "-DPNAME=\"" + _testName + "\""); + // DON'T change PNAME, qpid.stop needs this value. + env.put("QPID_PNAME", "-DPNAME=QPBRKR -DTNAME=\"" + _testName + "\""); env.put("QPID_WORK", System.getProperty("QPID_WORK")); // Add all the environment settings the test requested if (!_env.isEmpty()) { - for(Map.Entry entry : _env.entrySet()) + for (Map.Entry entry : _env.entrySet()) + { + env.put(entry.getKey(), entry.getValue()); + } + } + + String QPID_OPTS = " "; + // Add all the specified system properties to QPID_OPTS + if (!_setProperties.isEmpty()) + { + for (String key : _setProperties.keySet()) + { + QPID_OPTS += "-D" + key + "=" + System.getProperty(key) + " "; + } + + if (env.containsKey("QPID_OPTS")) { - env.put(entry.getKey() ,entry.getValue()); + env.put("QPID_OPTS", env.get("QPID_OPTS") + QPID_OPTS); + } + else + { + env.put("QPID_OPTS", QPID_OPTS); } } @@ -484,6 +513,27 @@ public class QpidTestCase extends TestCase _brokers.put(port, process); } + public String getTestConfigFile() + { + String path = _output == null ? System.getProperty("java.io.tmpdir") : _output; + return path + "/" + getTestQueueName() + ".xml"; + } + + protected void saveTestConfiguration() throws ConfigurationException + { + String testConfig = getTestConfigFile(); + //Specifiy the test configuration + setSystemProperty("test.config", testConfig); + + // This is a work + if (_testConfiguration.isEmpty()) + { + _testConfiguration.addProperty("test", getTestQueueName()); + } + + _testConfiguration.save(getTestConfigFile()); + } + public void cleanBroker() { if (_brokerClean != null) @@ -565,18 +615,12 @@ public class QpidTestCase extends TestCase storeClass = bdb; } - // First we munge the config file and, if we're in a VM, set up an additional logfile - XMLConfiguration configuration = new XMLConfiguration(_configFile); - configuration.setProperty("virtualhosts.virtualhost." + virtualhost + + + _testConfiguration.setProperty("virtualhosts.virtualhost." + virtualhost + ".store.class", storeClass.getName()); - configuration.setProperty("virtualhosts.virtualhost." + virtualhost + + _testConfiguration.setProperty("virtualhosts.virtualhost." + virtualhost + ".store." + DerbyMessageStore.ENVIRONMENT_PATH_PROPERTY, - "${work}/" + virtualhost); - - File tmpFile = File.createTempFile("configFile", "test"); - tmpFile.deleteOnExit(); - configuration.save(tmpFile); - _configFile = tmpFile; + "${QPID_WORK}/" + virtualhost); } /** @@ -591,6 +635,10 @@ public class QpidTestCase extends TestCase */ protected String getConfigurationStringProperty(String property) throws ConfigurationException { + // Call save Configuration to be sure we have saved the test specific + // file. As the optional status + saveTestConfiguration(); + ServerConfiguration configuration = new ServerConfiguration(_configFile); return configuration.getConfig().getString(property); } @@ -613,48 +661,9 @@ public class QpidTestCase extends TestCase protected void setConfigurationProperty(String property, String value) throws ConfigurationException, IOException { - XMLConfiguration configuration = new XMLConfiguration(_configFile); - - // If we are modifying a virtualhost value then we need to do so in - // the virtualhost.xml file as these values overwrite the values in - // the main config.xml file - if (property.startsWith("virtualhosts")) - { - // So locate the virtualhost.xml file and use the ServerConfiguration - // flatConfig method to get the interpolated value. - String vhostConfigFile = ServerConfiguration. - flatConfig(_configFile).getString("virtualhosts"); - - // Load the vhostConfigFile - XMLConfiguration vhostConfiguration = new XMLConfiguration(vhostConfigFile); - - // Set the value specified in to the vhostConfig. - // Remembering that property will be 'virtualhosts.virtulhost....' - // so we need to take off the 'virtualhosts.' from the start. - vhostConfiguration.setProperty(property.substring(property.indexOf(".") + 1), value); - - // Write out the new virtualhost config file - File tmpFile = File.createTempFile("virtualhost-configFile", ".xml"); - tmpFile.deleteOnExit(); - vhostConfiguration.save(tmpFile); - - // Change the property and value to be the new virtualhosts file - // so that then update the value in the main config file. - property = "virtualhosts"; - value = tmpFile.getAbsolutePath(); - } - - configuration.setProperty(property, value); - - // Write the new server config file - File tmpFile = File.createTempFile("configFile", ".xml"); - tmpFile.deleteOnExit(); - configuration.save(tmpFile); - - _logger.info("Qpid Test Case now using configuration File:" - + tmpFile.getAbsolutePath()); - - _configFile = tmpFile; + //Write the value in to this configuration file which will override the + // defaults. + _testConfiguration.setProperty(property, value); } /** @@ -695,14 +704,13 @@ public class QpidTestCase extends TestCase * Add an environtmen variable for the external broker environment * * @param property the property to set - * @param value the value to set it to + * @param value the value to set it to */ protected void setBrokerEnvironment(String property, String value) { - _env.put(property,value); + _env.put(property, value); } - /** * Check whether the broker is an 0.8 * @@ -720,7 +728,7 @@ public class QpidTestCase extends TestCase protected boolean isJavaBroker() { - return _brokerLanguage.equals("java"); + return _brokerLanguage.equals("java") || _broker.equals("vm"); } protected boolean isCppBroker() @@ -807,7 +815,7 @@ public class QpidTestCase extends TestCase return (AMQConnectionFactory) getInitialContext().lookup(factoryName); } - public Connection getConnection() throws Exception + public Connection getConnection() throws JMSException, NamingException { return getConnection("guest", "guest"); } @@ -831,7 +839,7 @@ public class QpidTestCase extends TestCase * * @throws Exception if there is an error getting the connection */ - public Connection getConnection(String username, String password) throws Exception + public Connection getConnection(String username, String password) throws JMSException, NamingException { _logger.info("get Connection"); Connection con = getConnectionFactory().createConnection(username, password); @@ -840,7 +848,7 @@ public class QpidTestCase extends TestCase return con; } - public Connection getConnection(String username, String password, String id) throws Exception + public Connection getConnection(String username, String password, String id) throws JMSException, URLSyntaxException, AMQException, NamingException { _logger.info("get Connection"); Connection con; @@ -860,6 +868,7 @@ public class QpidTestCase extends TestCase /** * Return a uniqueName for this test. * In this case it returns a queue Named by the TestCase and TestName + * * @return String name for a queue */ protected String getTestQueueName() diff --git a/qpid/java/test-profiles/010Excludes b/qpid/java/test-profiles/010Excludes index 36e7317e31..f03d62667d 100644 --- a/qpid/java/test-profiles/010Excludes +++ b/qpid/java/test-profiles/010Excludes @@ -83,6 +83,9 @@ org.apache.qpid.server.logging.* // CPP Broker does not have a JMX interface to test org.apache.qpid.management.jmx.* +// JMX is used in this test for validation +org.apache.qpid.server.queue.ModelTest#* + // 0-10 is not supported by the MethodRegistry org.apache.qpid.test.unit.close.JavaServerCloseRaceConditionTest#* diff --git a/qpid/java/test-profiles/08Excludes b/qpid/java/test-profiles/08Excludes index 0866694854..b277c6d929 100644 --- a/qpid/java/test-profiles/08Excludes +++ b/qpid/java/test-profiles/08Excludes @@ -15,3 +15,8 @@ org.apache.qpid.server.persistent.NoLocalAfterRecoveryTest#* org.apache.qpid.client.SessionCreateTest#* org.apache.qpid.test.client.RollbackOrderTest#* + +// QPID-2097 exclude it from the InVM test runs until InVM JMX Interface is reliable +org.apache.qpid.management.jmx.ManagementActorLoggingTest#* +org.apache.qpid.server.queue.ModelTest#* + diff --git a/qpid/java/test-profiles/Excludes b/qpid/java/test-profiles/Excludes index 7ef2a15e51..a72d3bc86c 100644 --- a/qpid/java/test-profiles/Excludes +++ b/qpid/java/test-profiles/Excludes @@ -13,5 +13,9 @@ org.apache.qpid.server.logging.BrokerLoggingTest#testBrokerShutdownListeningTCPS org.apache.qpid.server.logging.BrokerLoggingTest#testBrokerShutdownStopped org.apache.qpid.server.logging.VirtualHostLoggingTest#testVirtualhostClosure org.apache.qpid.server.logging.MemoryMessageStoreLoggingTest#testMessageStoreClose -org.apache.qpid.server.logging.DerbyMessageStoreLoggingTest#testMessageStoreClose +// QPID-XXX : Test fails to start external broker due to Derby Exception. +org.apache.qpid.server.logging.DerbyMessageStoreLoggingTest#* + +// QPID-2081 :The configuration changes are now highlighting the close race condition +org.apache.qpid.server.security.acl.SimpleACLTest#* diff --git a/qpid/java/test-profiles/cpp.testprofile b/qpid/java/test-profiles/cpp.testprofile index 1d5416fe19..b3b979c786 100644 --- a/qpid/java/test-profiles/cpp.testprofile +++ b/qpid/java/test-profiles/cpp.testprofile @@ -8,6 +8,7 @@ broker.executable=${broker.dir}/qpidd broker.module.ssl=${module.dir}/ssl.so broker.module.cluster=${module.dir}/cluster.so broker.module.store=${store.module.dir}/msgstore.so +broker.stopped=Exception constructed broker.modules= broker.args= diff --git a/qpid/java/test-profiles/default.testprofile b/qpid/java/test-profiles/default.testprofile index 49d4a25b82..86a5b2efb3 100644 --- a/qpid/java/test-profiles/default.testprofile +++ b/qpid/java/test-profiles/default.testprofile @@ -18,9 +18,10 @@ log4j.debug=false test.port=15672 test.mport=18999 +#Note : Management will start open second port on: mport + 100 : 19099 test.port.ssl=15671 -test.port.alt=15772 -test.port.alt.ssl=15771 +test.port.alt=25672 +test.port.alt.ssl=25671 test.exclude=true profile.excludes=08TransientExcludes -- cgit v1.2.1 From 2296769193754d1bc09e1dc3b998709a5808ecbb Mon Sep 17 00:00:00 2001 From: Aidan Skinner Date: Fri, 18 Sep 2009 12:54:23 +0000 Subject: QPID-2104 AMQProtocolHandler: hand the actual write off to a seperate thread git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/java-network-refactor@816612 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/qpid/client/protocol/AMQProtocolHandler.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'qpid/java') diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java b/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java index be75fc150f..06a1fe2696 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java @@ -564,9 +564,16 @@ public class AMQProtocolHandler implements ProtocolEngine public void writeFrame(AMQDataBlock frame, boolean wait) { - ByteBuffer buf = frame.toNioByteBuffer(); + final ByteBuffer buf = frame.toNioByteBuffer(); _writtenBytes += buf.remaining(); - _networkDriver.send(buf); + Job.fireAsynchEvent(_poolReference.getPool(), _writeJob, new Runnable() + { + @Override + public void run() + { + _networkDriver.send(buf); + } + }); if (PROTOCOL_DEBUG) { _protocolLogger.debug(String.format("SEND: [%s] %s", this, frame)); -- cgit v1.2.1 From 555d38fcb330e544a01a2c0a2d9e0d94d4560b2d Mon Sep 17 00:00:00 2001 From: Aidan Skinner Date: Fri, 18 Sep 2009 12:55:10 +0000 Subject: MINANetworkDriverTest: Make sure we sleep for at least the alloted time. git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/java-network-refactor@816613 13f79535-47bb-0310-9956-ffa450edef68 --- .../network/mina/MINANetworkDriverTest.java | 36 ++++++++++++---------- 1 file changed, 20 insertions(+), 16 deletions(-) (limited to 'qpid/java') diff --git a/qpid/java/common/src/test/java/org/apache/qpid/transport/network/mina/MINANetworkDriverTest.java b/qpid/java/common/src/test/java/org/apache/qpid/transport/network/mina/MINANetworkDriverTest.java index 5500ff9d4b..5af07d9735 100644 --- a/qpid/java/common/src/test/java/org/apache/qpid/transport/network/mina/MINANetworkDriverTest.java +++ b/qpid/java/common/src/test/java/org/apache/qpid/transport/network/mina/MINANetworkDriverTest.java @@ -186,14 +186,7 @@ public class MINANetworkDriverTest extends TestCase _client.open(TEST_PORT, InetAddress.getLocalHost(), _countingEngine, null, null); assertFalse("Reader should not have been idle", _countingEngine.getReaderHasBeenIdle()); _client.setMaxReadIdle(1); - try - { - Thread.sleep(1000); - } - catch (InterruptedException e) - { - // Eat it - } + sleepForAtLeast(1500); assertTrue("Reader should have been idle", _countingEngine.getReaderHasBeenIdle()); } @@ -211,14 +204,7 @@ public class MINANetworkDriverTest extends TestCase _client.open(TEST_PORT, InetAddress.getLocalHost(), _countingEngine, null, null); assertFalse("Reader should not have been idle", _countingEngine.getWriterHasBeenIdle()); _client.setMaxWriteIdle(1); - try - { - Thread.sleep(1000); - } - catch (InterruptedException e) - { - // Eat it - } + sleepForAtLeast(1500); assertTrue("Reader should have been idle", _countingEngine.getWriterHasBeenIdle()); } @@ -484,4 +470,22 @@ public class MINANetworkDriverTest extends TestCase _driver.send(msg); } } + + public static void sleepForAtLeast(long period) + { + long start = System.currentTimeMillis(); + long timeLeft = period; + while (timeLeft > 0) + { + try + { + Thread.sleep(timeLeft); + } + catch (InterruptedException e) + { + // Ignore it + } + timeLeft = period - (System.currentTimeMillis() - start); + } + } } \ No newline at end of file -- cgit v1.2.1 From 788f96fd8af146cba5bff57300b1a513988c34b9 Mon Sep 17 00:00:00 2001 From: Aidan Skinner Date: Fri, 18 Sep 2009 12:55:40 +0000 Subject: Fix bind error message git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/java-network-refactor@816614 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/qpid/transport/network/mina/MINANetworkDriver.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'qpid/java') diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java index 38ea9307b7..b0d1c46572 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java @@ -159,7 +159,7 @@ public class MINANetworkDriver extends IoHandlerAdapter implements NetworkDriver } catch (IOException e) { - throw new BindException(String.format("Could not bind to {0}:{2}", addr, port)); + throw new BindException(String.format("Could not bind to %1s:%2s", addr, port)); } } } @@ -171,7 +171,7 @@ public class MINANetworkDriver extends IoHandlerAdapter implements NetworkDriver } catch (IOException e) { - throw new BindException(String.format("Could not bind to *:{1}", port)); + throw new BindException(String.format("Could not bind to *:%1s", port)); } } _acceptingConnections = true; -- cgit v1.2.1 From 98cc985dbd81a84cd0b0a969c57cb941680ec81f Mon Sep 17 00:00:00 2001 From: Aidan Skinner Date: Sun, 11 Oct 2009 23:22:08 +0000 Subject: Merge from trunk git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/java-network-refactor@824198 13f79535-47bb-0310-9956-ffa450edef68 --- qpid/java/broker/etc/log4j.xml | 4 + .../java/org/apache/qpid/server/AMQChannel.java | 109 ++- .../server/configuration/QueueConfiguration.java | 10 + .../server/configuration/ServerConfiguration.java | 13 +- .../configuration/VirtualHostConfiguration.java | 11 + .../management/ConfigurationManagementMBean.java | 2 - .../server/exchange/DefaultExchangeFactory.java | 1 - .../server/handler/BasicRejectMethodHandler.java | 2 +- .../qpid/server/handler/ChannelOpenHandler.java | 7 + .../qpid/server/logging/actors/AbstractActor.java | 5 + .../qpid/server/logging/actors/BrokerActor.java | 8 + .../logging/messages/LogMessages_en_US.properties | 6 +- .../org/apache/qpid/server/queue/AMQQueue.java | 13 + .../apache/qpid/server/queue/AMQQueueFactory.java | 106 +++ .../apache/qpid/server/queue/QueueEntryImpl.java | 16 +- .../apache/qpid/server/queue/SimpleAMQQueue.java | 278 ++++-- .../qpid/server/registry/ApplicationRegistry.java | 2 +- .../ConfigurationFileApplicationRegistry.java | 10 +- .../qpid/server/registry/IApplicationRegistry.java | 3 +- .../security/access/PrincipalPermissions.java | 1002 ++++++++++---------- .../security/access/plugins/BasicACLPlugin.java | 12 - .../access/plugins/network/FirewallPlugin.java | 1 - .../PropertiesPrincipalDatabaseManager.java | 1 - .../qpid/server/subscription/SubscriptionImpl.java | 10 +- .../qpid/server/txn/LocalTransactionalContext.java | 1 + .../qpid/server/txn/NonTransactionalContext.java | 2 + .../org/apache/qpid/server/queue/MockAMQQueue.java | 37 +- .../registry/ApplicationRegistryShutdownTest.java | 3 +- .../qpid/server/util/NullApplicationRegistry.java | 5 +- .../qpid/server/util/TestApplicationRegistry.java | 5 +- qpid/java/client/src/main/java/log4j.xml | 36 + .../java/org/apache/qpid/client/AMQConnection.java | 12 +- .../apache/qpid/client/AMQConnectionDelegate.java | 9 + .../qpid/client/AMQConnectionDelegate_0_10.java | 13 +- .../qpid/client/AMQConnectionDelegate_8_0.java | 13 +- .../java/org/apache/qpid/client/AMQSession.java | 152 ++- .../org/apache/qpid/client/AMQSession_0_10.java | 3 - .../org/apache/qpid/client/AMQSession_0_8.java | 11 +- .../apache/qpid/client/BasicMessageConsumer.java | 1 + .../apache/qpid/client/BasicMessageProducer.java | 2 +- .../org/apache/qpid/client/XAConnectionImpl.java | 2 +- .../client/configuration/ClientProperties.java | 2 +- .../qpid/client/failover/FailoverHandler.java | 2 + .../client/handler/ClientMethodDispatcherImpl.java | 4 +- .../qpid/client/protocol/AMQProtocolHandler.java | 1 - .../apache/qpid/client/util/BlockingWaiter.java | 2 +- .../qpid/jms/failover/FailoverExchangeMethod.java | 13 +- qpid/java/common/bin/qpid-run | 1 + .../main/java/org/apache/qpid/ConsoleOutput.java | 1 - .../common/mbeans/LoggingManagement.java | 2 +- .../common/mbeans/ServerInformation.java | 2 +- .../qpid/management/ui/ApplicationRegistry.java | 2 +- .../views/logging/ConfigurationFileTabControl.java | 2 +- qpid/java/module.xml | 2 + .../org/apache/qpid/server/BrokerStartupTest.java | 22 +- .../MessageDisappearWithIOExceptionTest.java | 330 +++++++ .../qpid/server/logging/BrokerLoggingTest.java | 2 +- .../server/queue/DeepQueueConsumeWithSelector.java | 5 +- .../qpid/server/queue/ProducerFlowControlTest.java | 393 ++++++++ .../qpid/server/security/acl/SimpleACLTest.java | 123 ++- .../qpid/test/client/QueueBrowserAutoAckTest.java | 6 +- .../apache/qpid/test/client/RollbackOrderTest.java | 170 +++- .../qpid/test/client/failover/FailoverTest.java | 22 +- .../qpid/test/client/message/SelectorTest.java | 271 +++++- .../test/unit/ack/Acknowledge2ConsumersTest.java | 193 ++++ .../ack/AcknowledgeAfterFailoverOnMessageTest.java | 356 +++++++ .../unit/ack/AcknowledgeAfterFailoverTest.java | 306 ++++++ .../test/unit/ack/AcknowledgeOnMessageTest.java | 170 ++++ .../apache/qpid/test/unit/ack/AcknowledgeTest.java | 179 ++-- .../ack/FailoverBeforeConsumingRecoverTest.java | 40 + .../org/apache/qpid/test/unit/ack/QuickAcking.java | 148 +++ .../org/apache/qpid/test/unit/ack/RecoverTest.java | 253 +++-- .../apache/qpid/test/unit/basic/SelectorTest.java | 306 ------ .../qpid/test/unit/message/JMSPropertiesTest.java | 4 +- .../unit/publish/DirtyTrasactedPubilshTest.java | 403 ++++++++ .../apache/qpid/test/utils/FailoverBaseCase.java | 83 +- .../org/apache/qpid/test/utils/QpidTestCase.java | 221 ++++- qpid/java/test-profiles/010Excludes | 9 + qpid/java/test-profiles/08Excludes | 2 - qpid/java/test-profiles/08StandaloneExcludes | 2 - qpid/java/test-profiles/Excludes | 12 + qpid/java/test-profiles/default.testprofile | 3 + qpid/java/test-profiles/log4j-test.xml | 6 +- qpid/java/test-profiles/test-provider.properties | 17 +- 84 files changed, 4656 insertions(+), 1376 deletions(-) create mode 100644 qpid/java/client/src/main/java/log4j.xml create mode 100644 qpid/java/systests/src/main/java/org/apache/qpid/server/failover/MessageDisappearWithIOExceptionTest.java create mode 100644 qpid/java/systests/src/main/java/org/apache/qpid/server/queue/ProducerFlowControlTest.java create mode 100644 qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/Acknowledge2ConsumersTest.java create mode 100644 qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeAfterFailoverOnMessageTest.java create mode 100644 qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeAfterFailoverTest.java create mode 100644 qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeOnMessageTest.java create mode 100644 qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/FailoverBeforeConsumingRecoverTest.java create mode 100644 qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/QuickAcking.java delete mode 100644 qpid/java/systests/src/main/java/org/apache/qpid/test/unit/basic/SelectorTest.java create mode 100644 qpid/java/systests/src/main/java/org/apache/qpid/test/unit/publish/DirtyTrasactedPubilshTest.java mode change 100644 => 100755 qpid/java/test-profiles/010Excludes (limited to 'qpid/java') diff --git a/qpid/java/broker/etc/log4j.xml b/qpid/java/broker/etc/log4j.xml index 8ca43ededd..4b71772a0e 100644 --- a/qpid/java/broker/etc/log4j.xml +++ b/qpid/java/broker/etc/log4j.xml @@ -87,6 +87,10 @@ + + + + diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java index add5e64ee8..644a33db01 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java @@ -27,13 +27,12 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ConcurrentHashMap; import org.apache.log4j.Logger; import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.ContentBody; -import org.apache.qpid.framing.ContentHeaderBody; -import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.framing.*; import org.apache.qpid.framing.abstraction.MessagePublishInfo; import org.apache.qpid.server.ack.UnacknowledgedMessageMap; import org.apache.qpid.server.ack.UnacknowledgedMessageMapImpl; @@ -42,12 +41,7 @@ import org.apache.qpid.server.exchange.NoRouteException; import org.apache.qpid.server.flow.FlowCreditManager; import org.apache.qpid.server.flow.Pre0_10CreditManager; import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.queue.AMQMessage; -import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.queue.IncomingMessage; -import org.apache.qpid.server.queue.MessageHandleFactory; -import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.server.queue.UnauthorizedAccessException; +import org.apache.qpid.server.queue.*; import org.apache.qpid.server.subscription.Subscription; import org.apache.qpid.server.subscription.SubscriptionFactoryImpl; import org.apache.qpid.server.subscription.ClientDeliveryMethod; @@ -59,6 +53,7 @@ import org.apache.qpid.server.txn.NonTransactionalContext; import org.apache.qpid.server.txn.TransactionalContext; import org.apache.qpid.server.logging.LogActor; import org.apache.qpid.server.logging.LogSubject; +import org.apache.qpid.server.logging.LogMessage; import org.apache.qpid.server.logging.messages.ChannelMessages; import org.apache.qpid.server.logging.subjects.ChannelLogSubject; import org.apache.qpid.server.logging.actors.AMQPChannelActor; @@ -119,6 +114,11 @@ public class AMQChannel private final AMQProtocolSession _session; private boolean _closing; + private final ConcurrentMap _blockingQueues = new ConcurrentHashMap(); + + private final AtomicBoolean _blocking = new AtomicBoolean(false); + + private LogActor _actor; private LogSubject _logSubject; @@ -783,16 +783,32 @@ public class AMQChannel return _unacknowledgedMessageMap; } - + /** + * Called from the ChannelFlowHandler to suspend this Channel + * @param suspended boolean, should this Channel be suspended + */ public void setSuspended(boolean suspended) { - - boolean wasSuspended = _suspended.getAndSet(suspended); if (wasSuspended != suspended) { - _actor.message(_logSubject, ChannelMessages.CHN_1002(suspended ? "Stopped" : "Started")); + // Log Flow Started before we start the subscriptions + if (!suspended) + { + _actor.message(_logSubject, ChannelMessages.CHN_1002("Started")); + } + + + // This section takes two different approaches to perform to perform + // the same function. Ensuring that the Subscription has taken note + // of the change in Channel State + // Here we have become unsuspended and so we ask each the queue to + // perform an Async delivery for each of the subscriptions in this + // Channel. The alternative would be to ensure that the subscription + // had received the change in suspension state. That way the logic + // behind decieding to start an async delivery was located with the + // Subscription. if (wasSuspended) { // may need to deliver queued messages @@ -801,6 +817,38 @@ public class AMQChannel s.getQueue().deliverAsync(s); } } + + + // Here we have become suspended so we need to ensure that each of + // the Subscriptions has noticed this change so that we can be sure + // they are not still sending messages. Again the code here is a + // very simplistic approach to ensure that the change of suspension + // has been noticed by each of the Subscriptions. Unlike the above + // case we don't actually need to do anything else. + if (!wasSuspended) + { + // may need to deliver queued messages + for (Subscription s : _tag2SubscriptionMap.values()) + { + try + { + s.getSendLock(); + } + finally + { + s.releaseSendLock(); + } + } + } + + + // Log Suspension only after we have confirmed all suspensions are + // stopped. + if (suspended) + { + _actor.message(_logSubject, ChannelMessages.CHN_1002("Stopped")); + } + } } @@ -931,4 +979,37 @@ public class AMQChannel { return _actor; } + + public void block(AMQQueue queue) + { + if(_blockingQueues.putIfAbsent(queue, Boolean.TRUE) == null) + { + + if(_blocking.compareAndSet(false,true)) + { + _actor.message(_logSubject, ChannelMessages.CHN_1005(queue.getName().toString())); + flow(false); + } + } + } + + public void unblock(AMQQueue queue) + { + if(_blockingQueues.remove(queue)) + { + if(_blocking.compareAndSet(true,false)) + { + _actor.message(_logSubject, ChannelMessages.CHN_1006()); + + flow(true); + } + } + } + + private void flow(boolean flow) + { + MethodRegistry methodRegistry = _session.getMethodRegistry(); + AMQMethodBody responseBody = methodRegistry.createChannelFlowBody(flow); + _session.writeFrame(responseBody.generateFrame(_channelId)); + } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfiguration.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfiguration.java index 74bb7ee969..5c73e353de 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfiguration.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfiguration.java @@ -108,4 +108,14 @@ public class QueueConfiguration return _config.getLong("minimumAlertRepeatGap", _vHostConfig.getMinimumAlertRepeatGap()); } + public long getCapacity() + { + return _config.getLong("capacity", _vHostConfig.getCapacity()); + } + + public long getFlowResumeCapacity() + { + return _config.getLong("flowResumeCapacity", _vHostConfig.getFlowResumeCapacity()); + } + } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java index a72c2889d1..641b44bb18 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java @@ -104,6 +104,8 @@ public class ServerConfiguration implements SignalHandler envVarMap.put("QPID_MAXIMUMQUEUEDEPTH", "maximumQueueDepth"); envVarMap.put("QPID_MAXIMUMMESSAGESIZE", "maximumMessageSize"); envVarMap.put("QPID_MINIMUMALERTREPEATGAP", "minimumAlertRepeatGap"); + envVarMap.put("QPID_QUEUECAPACITY", "capacity"); + envVarMap.put("QPID_FLOWRESUMECAPACITY", "flowResumeCapacity"); envVarMap.put("QPID_SOCKETRECEIVEBUFFER", "connector.socketReceiveBuffer"); envVarMap.put("QPID_SOCKETWRITEBUFFER", "connector.socketWriteBuffer"); envVarMap.put("QPID_TCPNODELAY", "connector.tcpNoDelay"); @@ -290,7 +292,6 @@ public class ServerConfiguration implements SignalHandler return conf; } - @Override public void handle(Signal arg0) { try @@ -508,6 +509,16 @@ public class ServerConfiguration implements SignalHandler return getConfig().getLong("minimumAlertRepeatGap", 0); } + public long getCapacity() + { + return getConfig().getLong("capacity", 0L); + } + + public long getFlowResumeCapacity() + { + return getConfig().getLong("flowResumeCapacity", getCapacity()); + } + public int getProcessors() { return getConfig().getInt("connector.processors", 4); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfiguration.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfiguration.java index 0273a13262..6c72025ec2 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfiguration.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfiguration.java @@ -166,4 +166,15 @@ public class VirtualHostConfiguration return _config.getLong("queues.minimumAlertRepeatGap", 0); } + + public long getCapacity() + { + return _config.getLong("queues.capacity", 0l); + } + + public long getFlowResumeCapacity() + { + return _config.getLong("queues.flowResumeCapacity", getCapacity()); + } + } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/management/ConfigurationManagementMBean.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/management/ConfigurationManagementMBean.java index 1541d3d892..9954719866 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/management/ConfigurationManagementMBean.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/management/ConfigurationManagementMBean.java @@ -35,13 +35,11 @@ public class ConfigurationManagementMBean extends AMQManagedObject implements Co super(ConfigurationManagement.class, ConfigurationManagement.TYPE, ConfigurationManagement.VERSION); } - @Override public String getObjectInstanceName() { return ConfigurationManagement.TYPE; } - @Override public void reloadSecurityConfiguration() throws Exception { ApplicationRegistry.getInstance().getConfiguration().reparseConfigFile(); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeFactory.java index c04b6c559c..620799a81f 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeFactory.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeFactory.java @@ -73,7 +73,6 @@ public class DefaultExchangeFactory implements ExchangeFactory return e; } - @Override public void initialise(VirtualHostConfiguration hostConfig) { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRejectMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRejectMethodHandler.java index f3cab10ed7..fcf3fd4337 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRejectMethodHandler.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRejectMethodHandler.java @@ -71,7 +71,7 @@ public class BasicRejectMethodHandler implements StateAwareMethodListener void setMinimumAlertRepeatGap(long value); + long getCapacity(); + + void setCapacity(long capacity); + + + long getFlowResumeCapacity(); + + void setFlowResumeCapacity(long flowResumeCapacity); + + + void deleteMessageFromTop(StoreContext storeContext) throws AMQException; long clearQueue(StoreContext storeContext) throws AMQException; @@ -180,6 +191,8 @@ public interface AMQQueue extends Managable, Comparable void stop(); + void checkCapacity(AMQChannel channel); + /** * ExistingExclusiveSubscription signals a failure to create a subscription, because an exclusive subscription * already exists. diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java index 7509350e65..267ccf43ea 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java @@ -26,11 +26,105 @@ import org.apache.qpid.framing.FieldTable; import org.apache.qpid.server.configuration.QueueConfiguration; import org.apache.qpid.server.virtualhost.VirtualHost; +import java.util.Map; +import java.util.HashMap; + public class AMQQueueFactory { public static final AMQShortString X_QPID_PRIORITIES = new AMQShortString("x-qpid-priorities"); + private abstract static class QueueProperty + { + + private final AMQShortString _argumentName; + + + public QueueProperty(String argumentName) + { + _argumentName = new AMQShortString(argumentName); + } + + public AMQShortString getArgumentName() + { + return _argumentName; + } + + + public abstract void setPropertyValue(AMQQueue queue, Object value); + + } + + private abstract static class QueueLongProperty extends QueueProperty + { + + public QueueLongProperty(String argumentName) + { + super(argumentName); + } + + public void setPropertyValue(AMQQueue queue, Object value) + { + if(value instanceof Number) + { + setPropertyValue(queue, ((Number)value).longValue()); + } + + } + + abstract void setPropertyValue(AMQQueue queue, long value); + + + } + + private static final QueueProperty[] DECLAREABLE_PROPERTIES = { + new QueueLongProperty("x-qpid-maximum-message-age") + { + public void setPropertyValue(AMQQueue queue, long value) + { + queue.setMaximumMessageAge(value); + } + }, + new QueueLongProperty("x-qpid-maximum-message-size") + { + public void setPropertyValue(AMQQueue queue, long value) + { + queue.setMaximumMessageSize(value); + } + }, + new QueueLongProperty("x-qpid-maximum-message-count") + { + public void setPropertyValue(AMQQueue queue, long value) + { + queue.setMaximumMessageCount(value); + } + }, + new QueueLongProperty("x-qpid-minimum-alert-repeat-gap") + { + public void setPropertyValue(AMQQueue queue, long value) + { + queue.setMinimumAlertRepeatGap(value); + } + }, + new QueueLongProperty("x-qpid-capacity") + { + public void setPropertyValue(AMQQueue queue, long value) + { + queue.setCapacity(value); + } + }, + new QueueLongProperty("x-qpid-flow-resume-capacity") + { + public void setPropertyValue(AMQQueue queue, long value) + { + queue.setFlowResumeCapacity(value); + } + } + + }; + + + public static AMQQueue createAMQQueueImpl(AMQShortString name, boolean durable, AMQShortString owner, @@ -53,6 +147,18 @@ public class AMQQueueFactory //Register the new queue virtualHost.getQueueRegistry().registerQueue(q); q.configure(virtualHost.getConfiguration().getQueueConfiguration(name.asString())); + + if(arguments != null) + { + for(QueueProperty p : DECLAREABLE_PROPERTIES) + { + if(arguments.containsKey(p.getArgumentName())) + { + p.setPropertyValue(q, arguments.get(p.getArgumentName())); + } + } + } + return q; } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java index dbad5438dc..3b58f05f93 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java @@ -42,8 +42,7 @@ public class QueueEntryImpl implements QueueEntry private final SimpleQueueEntryList _queueEntryList; - private AMQMessage _message; - + private final AMQMessage _message; private Set _rejectedBy = null; @@ -177,13 +176,21 @@ public class QueueEntryImpl implements QueueEntry public String debugIdentity() { - return getMessage().debugIdentity(); + AMQMessage message = getMessage(); + if (message == null) + { + return "null"; + } + else + { + return message.debugIdentity(); + } } public boolean immediateAndNotDelivered() { - return _message.immediateAndNotDelivered(); + return getMessage().immediateAndNotDelivered(); } public void setRedelivered(boolean b) @@ -385,4 +392,5 @@ public class QueueEntryImpl implements QueueEntry { return _queueEntryList; } + } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java index b14b92b014..d781dc4dea 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java @@ -1,11 +1,10 @@ package org.apache.qpid.server.queue; -import java.util.ArrayList; -import java.util.EnumSet; -import java.util.List; -import java.util.Set; +import java.util.*; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.Executor; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; @@ -35,6 +34,7 @@ import org.apache.qpid.server.logging.subjects.QueueLogSubject; import org.apache.qpid.server.logging.LogSubject; import org.apache.qpid.server.logging.LogActor; import org.apache.qpid.server.logging.messages.QueueMessages; +import org.apache.qpid.server.AMQChannel; /* * @@ -96,6 +96,8 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener private final Executor _asyncDelivery; private final AtomicLong _totalMessagesReceived = new AtomicLong(); + private final ConcurrentMap _blockedChannels = new ConcurrentHashMap(); + /** max allowed size(KB) of a single message */ public long _maximumMessageSize = ApplicationRegistry.getInstance().getConfiguration().getMaximumMessageSize(); @@ -122,6 +124,11 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener private LogSubject _logSubject; private LogActor _logActor; + + private long _capacity = ApplicationRegistry.getInstance().getConfiguration().getCapacity(); + private long _flowResumeCapacity = ApplicationRegistry.getInstance().getConfiguration().getFlowResumeCapacity(); + private final AtomicBoolean _overfull = new AtomicBoolean(false); + protected SimpleAMQQueue(AMQShortString name, boolean durable, AMQShortString owner, boolean autoDelete, VirtualHost virtualHost) throws AMQException { @@ -508,8 +515,11 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener throws AMQException { _deliveredMessages.incrementAndGet(); + if (_logger.isDebugEnabled()) + { + _logger.debug(sub + ": deliverMessage: " + entry.debugIdentity()); + } sub.send(entry); - } private boolean subscriptionReadyAndHasInterest(final Subscription sub, final QueueEntry entry) @@ -626,6 +636,8 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener throw new FailedDequeueException(_name.toString(), e); } + checkCapacity(); + } private void decrementQueueSize(final QueueEntry entry) @@ -1170,11 +1182,64 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener } } - public void deliverAsync() + public void checkCapacity(AMQChannel channel) { - _stateChangeCount.incrementAndGet(); + if(_capacity != 0l) + { + if(_atomicQueueSize.get() > _capacity) + { + _overfull.set(true); + //Overfull log message + _logActor.message(_logSubject, QueueMessages.QUE_1003(_atomicQueueSize.get(), _capacity)); + + if(_blockedChannels.putIfAbsent(channel, Boolean.TRUE)==null) + { + channel.block(this); + } + + if(_atomicQueueSize.get() <= _flowResumeCapacity) + { + + //Underfull log message + _logActor.message(_logSubject, QueueMessages.QUE_1004(_atomicQueueSize.get(), _flowResumeCapacity)); + + channel.unblock(this); + _blockedChannels.remove(channel); + + } + + } + + + + } + } + + private void checkCapacity() + { + if(_capacity != 0L) + { + if(_overfull.get() && _atomicQueueSize.get() <= _flowResumeCapacity) + { + if(_overfull.compareAndSet(true,false)) + {//Underfull log message + _logActor.message(_logSubject, QueueMessages.QUE_1004(_atomicQueueSize.get(), _flowResumeCapacity)); + } - Runner runner = new Runner(); + + for(AMQChannel c : _blockedChannels.keySet()) + { + c.unblock(this); + _blockedChannels.remove(c); + } + } + } + } + + + public void deliverAsync() + { + Runner runner = new Runner(_stateChangeCount.incrementAndGet()); if (_asynchronousRunner.compareAndSet(null, runner)) { @@ -1187,13 +1252,23 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener _asyncDelivery.execute(new SubFlushRunner(sub)); } + private class Runner implements ReadWriteRunnable { + String _name; + public Runner(long count) + { + _name = "QueueRunner-" + count + "-" + _logActor; + } + public void run() { + String originalName = Thread.currentThread().getName(); try { + Thread.currentThread().setName(_name); CurrentActor.set(_logActor); + processQueue(this); } catch (AMQException e) @@ -1203,9 +1278,8 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener finally { CurrentActor.remove(); + Thread.currentThread().setName(originalName); } - - } public boolean isRead() @@ -1217,6 +1291,11 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener { return true; } + + public String toString() + { + return _name; + } } private class SubFlushRunner implements ReadWriteRunnable @@ -1230,27 +1309,36 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener public void run() { - boolean complete = false; - try - { - CurrentActor.set(_sub.getLogActor()); - complete = flushSubscription(_sub, new Long(MAX_ASYNC_DELIVERIES)); - } - catch (AMQException e) - { - _logger.error(e); + String originalName = Thread.currentThread().getName(); + try{ + Thread.currentThread().setName("SubFlushRunner-"+_sub); + + boolean complete = false; + try + { + CurrentActor.set(_sub.getLogActor()); + complete = flushSubscription(_sub, new Long(MAX_ASYNC_DELIVERIES)); + + } + catch (AMQException e) + { + _logger.error(e); + } + finally + { + CurrentActor.remove(); + } + if (!complete && !_sub.isSuspended()) + { + _asyncDelivery.execute(this); + } } finally { - CurrentActor.remove(); - } - if (!complete && !_sub.isSuspended()) - { - _asyncDelivery.execute(this); + Thread.currentThread().setName(originalName); } - } public boolean isRead() @@ -1278,7 +1366,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener try { sub.getSendLock(); - atTail = attemptDelivery(sub); + atTail = attemptDelivery(sub); if (atTail && sub.isAutoClose()) { unregisterSubscription(sub); @@ -1308,63 +1396,81 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener return atTail; } + /** + * Attempt delivery for the given subscription. + * + * Looks up the next node for the subscription and attempts to deliver it. + * + * @param sub + * @return true if we have completed all possible deliveries for this sub. + * @throws AMQException + */ private boolean attemptDelivery(Subscription sub) throws AMQException { boolean atTail = false; boolean advanced = false; - boolean subActive = sub.isActive(); + boolean subActive = sub.isActive() && !sub.isSuspended(); if (subActive) { QueueEntry node = moveSubscriptionToNextNode(sub); + if (_logger.isDebugEnabled()) + { + _logger.debug(sub + ": attempting Delivery: " + node.debugIdentity()); + } if (!(node.isAcquired() || node.isDeleted())) { - if (!sub.isSuspended()) + if (sub.hasInterest(node)) { - if (sub.hasInterest(node)) + if (!sub.wouldSuspend(node)) { - if (!sub.wouldSuspend(node)) + if (!sub.isBrowser() && !node.acquire(sub)) { - if (!sub.isBrowser() && !node.acquire(sub)) - { - sub.restoreCredit(node); - } - else + sub.restoreCredit(node); + } + else + { + deliverMessage(sub, node); + + if (sub.isBrowser()) { - deliverMessage(sub, node); + QueueEntry newNode = _entries.next(node); - if (sub.isBrowser()) + if (newNode != null) { - QueueEntry newNode = _entries.next(node); - - if (newNode != null) - { - advanced = true; - sub.setLastSeenEntry(node, newNode); - node = sub.getLastSeenEntry(); - } + advanced = true; + sub.setLastSeenEntry(node, newNode); + node = sub.getLastSeenEntry(); } + } - - } - else // Not enough Credit for message and wouldSuspend - { - //QPID-1187 - Treat the subscription as suspended for this message - // and wait for the message to be removed to continue delivery. - subActive = false; - node.addStateChangeListener(new QueueEntryListener(sub, node)); } + } - else + else // Not enough Credit for message and wouldSuspend { - // this subscription is not interested in this node so we can skip over it - QueueEntry newNode = _entries.next(node); - if (newNode != null) - { - sub.setLastSeenEntry(node, newNode); - } + //QPID-1187 - Treat the subscription as suspended for this message + // and wait for the message to be removed to continue delivery. + + // 2009-09-30 : MR : setting subActive = false only causes, this + // particular delivery attempt to end. This is called from + // flushSubscription and processQueue both of which attempt + // delivery a number of times. Won't a bytes limited + // subscriber with not enough credit for the next message + // create a lot of new QELs? How about a browser that calls + // this method LONG.MAX_LONG times! + subActive = false; + node.addStateChangeListener(new QueueEntryListener(sub, node)); + } + } + else + { + // this subscription is not interested in this node so we can skip over it + QueueEntry newNode = _entries.next(node); + if (newNode != null) + { + sub.setLastSeenEntry(node, newNode); } } - } atTail = (_entries.next(node) == null) && !advanced; } @@ -1409,6 +1515,12 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener } } + + if (_logger.isDebugEnabled()) + { + _logger.debug(sub + ": nextNode: " + (node == null ? "null" : node.debugIdentity())); + } + return node; } @@ -1423,6 +1535,11 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener _asynchronousRunner.compareAndSet(runner, null); + // For every message enqueue/requeue the we fire deliveryAsync() which + // increases _stateChangeCount. If _sCC changes whilst we are in our loop + // (detected by setting previousStateChangeCount to stateChangeCount in the loop body) + // then we will continue to run for a maximum of iterations. + // So whilst delivery/rejection is going on a processQueue thread will be running while (iterations != 0 && ((previousStateChangeCount != (stateChangeCount = _stateChangeCount.get())) || deliveryIncomplete) && _asynchronousRunner.compareAndSet(null, runner)) { // we want to have one extra loop after every subscription has reached the point where it cannot move @@ -1442,20 +1559,11 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener //iterate over the subscribers and try to advance their pointer while (subscriptionIter.advance()) { - boolean closeConsumer = false; Subscription sub = subscriptionIter.getNode().getSubscription(); sub.getSendLock(); try { - if (sub != null) - { - - QueueEntry node = moveSubscriptionToNextNode(sub); - if (node != null) - { - done = attemptDelivery(sub); - } - } + done = attemptDelivery(sub); if (done) { if (extraLoops == 0) @@ -1492,11 +1600,14 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener // therefore we should schedule this runner again (unless someone beats us to it :-) ). if (iterations == 0 && _asynchronousRunner.compareAndSet(null, runner)) { + if (_logger.isDebugEnabled()) + { + _logger.debug("Rescheduling runner:" + runner); + } _asyncDelivery.execute(runner); } } - @Override public void checkMessageStatus() throws AMQException { @@ -1604,6 +1715,27 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener } } + public long getCapacity() + { + return _capacity; + } + + public void setCapacity(long capacity) + { + _capacity = capacity; + } + + public long getFlowResumeCapacity() + { + return _flowResumeCapacity; + } + + public void setFlowResumeCapacity(long flowResumeCapacity) + { + _flowResumeCapacity = flowResumeCapacity; + } + + public Set getNotificationChecks() { return _notificationChecks; @@ -1673,6 +1805,8 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener setMaximumMessageSize(config.getMaximumMessageSize()); setMaximumMessageCount(config.getMaximumMessageCount()); setMinimumAlertRepeatGap(config.getMinimumAlertRepeatGap()); + _capacity = config.getCapacity(); + _flowResumeCapacity = config.getFlowResumeCapacity(); } } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java index 9575bfa1ec..1affdd6590 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java @@ -102,7 +102,7 @@ public abstract class ApplicationRegistry implements IApplicationRegistry try { - instance.initialise(); + instance.initialise(instanceID); } catch (Exception e) { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java index a049d1eb09..831f928832 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java @@ -42,18 +42,22 @@ import java.io.File; public class ConfigurationFileApplicationRegistry extends ApplicationRegistry { + private String _registryName; public ConfigurationFileApplicationRegistry(File configurationURL) throws ConfigurationException { super(new ServerConfiguration(configurationURL)); } - public void initialise() throws Exception + public void initialise(int instanceID) throws Exception { _rootMessageLogger = new RootMessageLoggerImpl(_configuration, new Log4jMessageLogger()); + + _registryName = String.valueOf(instanceID); + // Set the Actor for current log messages - CurrentActor.set(new BrokerActor(_rootMessageLogger)); + CurrentActor.set(new BrokerActor(_registryName, _rootMessageLogger)); CurrentActor.get().message(BrokerMessages.BRK_1001(QpidProperties.getReleaseVersion(),QpidProperties.getBuildVersion())); @@ -83,7 +87,7 @@ public class ConfigurationFileApplicationRegistry extends ApplicationRegistry public void close() throws Exception { //Set the Actor for Broker Shutdown - CurrentActor.set(new BrokerActor(_rootMessageLogger)); + CurrentActor.set(new BrokerActor(_registryName, _rootMessageLogger)); try { super.close(); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java index ddb3fce5d2..92accb3499 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java @@ -43,8 +43,9 @@ public interface IApplicationRegistry * Initialise the application registry. All initialisation must be done in this method so that any components * that need access to the application registry itself for initialisation are able to use it. Attempting to * initialise in the constructor will lead to failures since the registry reference will not have been set. + * @param instanceID the instanceID that we can use to identify this AR. */ - void initialise() throws Exception; + void initialise(int instanceID) throws Exception; /** * Shutdown this Registry diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/PrincipalPermissions.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/PrincipalPermissions.java index f852514444..d2bbb795e9 100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/PrincipalPermissions.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/PrincipalPermissions.java @@ -20,16 +20,17 @@ */ package org.apache.qpid.server.security.access; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.QueueBindBody; -import org.apache.qpid.framing.QueueDeclareBody; -import org.apache.qpid.framing.ExchangeDeclareBody; +import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.security.access.ACLPlugin.AuthzResult; -import org.apache.qpid.server.exchange.Exchange; - -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; public class PrincipalPermissions { @@ -41,6 +42,7 @@ public class PrincipalPermissions private static final Object CREATE_QUEUES_KEY = new Object(); private static final Object CREATE_EXCHANGES_KEY = new Object(); + private static final Object CREATE_QUEUE_TEMPORARY_KEY = new Object(); private static final Object CREATE_QUEUE_QUEUES_KEY = new Object(); private static final Object CREATE_QUEUE_EXCHANGES_KEY = new Object(); @@ -80,248 +82,257 @@ public class PrincipalPermissions { switch (permission) { - case ACCESS: - break; // This is a no-op as the existence of this PrincipalPermission object is scoped per VHost for ACCESS - case BIND: - break; // All the details are currently included in the create setup. case CONSUME: // Parameters : AMQShortString queueName, Boolean Temporary, Boolean ownQueueOnly - Map consumeRights = (Map) _permissions.get(permission); - - if (consumeRights == null) - { - consumeRights = new ConcurrentHashMap(); - _permissions.put(permission, consumeRights); - } - - //if we have parametsre - if (parameters.length > 0) - { - AMQShortString queueName = (AMQShortString) parameters[0]; - Boolean temporary = (Boolean) parameters[1]; - Boolean ownQueueOnly = (Boolean) parameters[2]; - - if (temporary) - { - consumeRights.put(CONSUME_TEMPORARY_KEY, true); - } - else - { - consumeRights.put(CONSUME_TEMPORARY_KEY, false); - } - - if (ownQueueOnly) - { - consumeRights.put(CONSUME_OWN_QUEUES_ONLY_KEY, true); - } - else - { - consumeRights.put(CONSUME_OWN_QUEUES_ONLY_KEY, false); - } - - - LinkedList queues = (LinkedList) consumeRights.get(CONSUME_QUEUES_KEY); - if (queues == null) - { - queues = new LinkedList(); - consumeRights.put(CONSUME_QUEUES_KEY, queues); - } - - if (queueName != null) - { - queues.add(queueName); - } - } - - + grantConsume(permission, parameters); break; case CREATEQUEUE: // Parameters : Boolean temporary, AMQShortString queueName // , AMQShortString exchangeName , AMQShortString routingKey - - Map createRights = (Map) _permissions.get(permission); - - if (createRights == null) - { - createRights = new ConcurrentHashMap(); - _permissions.put(permission, createRights); - - } - - //The existence of the empty map mean permission to all. - if (parameters.length == 0) - { - return; - } - - Boolean temporary = (Boolean) parameters[0]; - - AMQShortString queueName = parameters.length > 1 ? (AMQShortString) parameters[1] : null; - AMQShortString exchangeName = parameters.length > 2 ? (AMQShortString) parameters[2] : null; - //Set the routingkey to the specified value or the queueName if present - AMQShortString routingKey = (parameters.length > 3 && null != parameters[3]) ? (AMQShortString) parameters[3] : queueName; - - // Get the queues map - Map create_queues = (Map) createRights.get(CREATE_QUEUES_KEY); - - if (create_queues == null) - { - create_queues = new ConcurrentHashMap(); - createRights.put(CREATE_QUEUES_KEY, create_queues); - } - - //Allow all temp queues to be created - create_queues.put(CREATE_QUEUE_TEMPORARY_KEY, temporary); - - //Create empty list of queues - Map create_queues_queues = (Map) create_queues.get(CREATE_QUEUE_QUEUES_KEY); - - if (create_queues_queues == null) - { - create_queues_queues = new ConcurrentHashMap(); - create_queues.put(CREATE_QUEUE_QUEUES_KEY, create_queues_queues); - } - - // We are granting CREATE rights to all temporary queues only - if (parameters.length == 1) - { - return; - } - - // if we have a queueName then we need to store any associated exchange / rk bindings - if (queueName != null) - { - Map queue = (Map) create_queues_queues.get(queueName); - if (queue == null) - { - queue = new ConcurrentHashMap(); - create_queues_queues.put(queueName, queue); - } - - if (exchangeName != null) - { - queue.put(exchangeName, routingKey); - } - - //If no exchange is specified then the presence of the queueName in the map says any exchange is ok - } - - // Store the exchange that we are being granted rights to. This will be used as part of binding - - //Lookup the list of exchanges - Map create_queues_exchanges = (Map) create_queues.get(CREATE_QUEUE_EXCHANGES_KEY); - - if (create_queues_exchanges == null) - { - create_queues_exchanges = new ConcurrentHashMap(); - create_queues.put(CREATE_QUEUE_EXCHANGES_KEY, create_queues_exchanges); - } - - //if we have an exchange - if (exchangeName != null) - { - //Retrieve the list of permitted exchanges. - Map exchanges = (Map) create_queues_exchanges.get(exchangeName); - - if (exchanges == null) - { - exchanges = new ConcurrentHashMap(); - create_queues_exchanges.put(exchangeName, exchanges); - } - - //Store the temporary setting CREATE_QUEUE_EXCHANGES_ROUTINGKEYS_KEY - exchanges.put(CREATE_QUEUE_EXCHANGES_TEMPORARY_KEY, temporary); - - //Store the binding details of queue/rk for this exchange. - if (queueName != null) - { - //Retrieve the list of permitted routingKeys. - Map rKeys = (Map) exchanges.get(exchangeName); - - if (rKeys == null) - { - rKeys = new ConcurrentHashMap(); - exchanges.put(CREATE_QUEUE_EXCHANGES_ROUTINGKEYS_KEY, rKeys); - } - - rKeys.put(queueName, routingKey); - } - } + grantCreateQueue(permission, parameters); break; case CREATEEXCHANGE: // Parameters AMQShortString exchangeName , AMQShortString Class - Map rights = (Map) _permissions.get(permission); - if (rights == null) - { - rights = new ConcurrentHashMap(); - _permissions.put(permission, rights); - } - - Map create_exchanges = (Map) rights.get(CREATE_EXCHANGES_KEY); - if (create_exchanges == null) - { - create_exchanges = new ConcurrentHashMap(); - rights.put(CREATE_EXCHANGES_KEY, create_exchanges); - } - - //Should perhaps error if parameters[0] is null; - AMQShortString name = parameters.length > 0 ? (AMQShortString) parameters[0] : null; - AMQShortString className = parameters.length > 1 ? (AMQShortString) parameters[1] : new AMQShortString("direct"); - - //Store the exchangeName / class mapping if the mapping is null - rights.put(name, className); - break; - case DELETE: + grantCreateExchange(permission, parameters); break; - case PUBLISH: // Parameters : Exchange exchange, AMQShortString routingKey - Map publishRights = (Map) _permissions.get(permission); - - if (publishRights == null) - { - publishRights = new ConcurrentHashMap(); - _permissions.put(permission, publishRights); - } - - if (parameters == null || parameters.length == 0) - { - //If we have no parameters then allow publish to all destinations - // this is signified by having a null value for publish_exchanges - } - else - { - Map publish_exchanges = (Map) publishRights.get(PUBLISH_EXCHANGES_KEY); - - if (publish_exchanges == null) - { - publish_exchanges = new ConcurrentHashMap(); - publishRights.put(PUBLISH_EXCHANGES_KEY, publish_exchanges); - } - - - HashSet routingKeys = (HashSet) publish_exchanges.get(parameters[0]); - - // Check to see if we have a routing key - if (parameters.length == 2) - { - if (routingKeys == null) - { - routingKeys = new HashSet(); - } - //Add routing key to permitted publish destinations - routingKeys.add(parameters[1]); - } - - // Add the updated routingkey list or null if all values allowed - publish_exchanges.put(parameters[0], routingKeys); - } + grantPublish(permission, parameters); break; + /* The other cases just fall through to no-op */ + case DELETE: + case ACCESS: // This is a no-op as the existence of this PrincipalPermission object is scoped per VHost for ACCESS + case BIND: // All the details are currently included in the create setup. case PURGE: - break; case UNBIND: break; } } + private void grantPublish(Permission permission, Object... parameters) { + Map publishRights = (Map) _permissions.get(permission); + + if (publishRights == null) + { + publishRights = new ConcurrentHashMap(); + _permissions.put(permission, publishRights); + } + + if (parameters == null || parameters.length == 0) + { + //If we have no parameters then allow publish to all destinations + // this is signified by having a null value for publish_exchanges + } + else + { + Map publish_exchanges = (Map) publishRights.get(PUBLISH_EXCHANGES_KEY); + + if (publish_exchanges == null) + { + publish_exchanges = new ConcurrentHashMap(); + publishRights.put(PUBLISH_EXCHANGES_KEY, publish_exchanges); + } + + + HashSet routingKeys = (HashSet) publish_exchanges.get(parameters[0]); + + // Check to see if we have a routing key + if (parameters.length == 2) + { + if (routingKeys == null) + { + routingKeys = new HashSet(); + } + //Add routing key to permitted publish destinations + routingKeys.add(parameters[1]); + } + + // Add the updated routingkey list or null if all values allowed + publish_exchanges.put(parameters[0], routingKeys); + } + } + + private void grantCreateExchange(Permission permission, Object... parameters) { + Map rights = (Map) _permissions.get(permission); + if (rights == null) + { + rights = new ConcurrentHashMap(); + _permissions.put(permission, rights); + } + + Map create_exchanges = (Map) rights.get(CREATE_EXCHANGES_KEY); + if (create_exchanges == null) + { + create_exchanges = new ConcurrentHashMap(); + rights.put(CREATE_EXCHANGES_KEY, create_exchanges); + } + + //Should perhaps error if parameters[0] is null; + AMQShortString name = parameters.length > 0 ? (AMQShortString) parameters[0] : null; + AMQShortString className = parameters.length > 1 ? (AMQShortString) parameters[1] : new AMQShortString("direct"); + + //Store the exchangeName / class mapping if the mapping is null + rights.put(name, className); + } + + private void grantCreateQueue(Permission permission, Object... parameters) { + Map createRights = (Map) _permissions.get(permission); + + if (createRights == null) + { + createRights = new ConcurrentHashMap(); + _permissions.put(permission, createRights); + + } + + //The existence of the empty map mean permission to all. + if (parameters.length == 0) + { + return; + } + + Boolean temporary = (Boolean) parameters[0]; + + AMQShortString queueName = parameters.length > 1 ? (AMQShortString) parameters[1] : null; + AMQShortString exchangeName = parameters.length > 2 ? (AMQShortString) parameters[2] : null; + //Set the routingkey to the specified value or the queueName if present + AMQShortString routingKey = (parameters.length > 3 && null != parameters[3]) ? (AMQShortString) parameters[3] : queueName; + + // Get the queues map + Map create_queues = (Map) createRights.get(CREATE_QUEUES_KEY); + + if (create_queues == null) + { + create_queues = new ConcurrentHashMap(); + createRights.put(CREATE_QUEUES_KEY, create_queues); + } + + //Allow all temp queues to be created + create_queues.put(CREATE_QUEUE_TEMPORARY_KEY, temporary); + + //Create empty list of queues + Map create_queues_queues = (Map) create_queues.get(CREATE_QUEUE_QUEUES_KEY); + + if (create_queues_queues == null) + { + create_queues_queues = new ConcurrentHashMap(); + create_queues.put(CREATE_QUEUE_QUEUES_KEY, create_queues_queues); + } + + // We are granting CREATE rights to all temporary queues only + if (parameters.length == 1) + { + return; + } + + // if we have a queueName then we need to store any associated exchange / rk bindings + if (queueName != null) + { + Map queue = (Map) create_queues_queues.get(queueName); + if (queue == null) + { + queue = new ConcurrentHashMap(); + create_queues_queues.put(queueName, queue); + } + + if (exchangeName != null) + { + queue.put(exchangeName, routingKey); + } + + //If no exchange is specified then the presence of the queueName in the map says any exchange is ok + } + + // Store the exchange that we are being granted rights to. This will be used as part of binding + + //Lookup the list of exchanges + Map create_queues_exchanges = (Map) create_queues.get(CREATE_QUEUE_EXCHANGES_KEY); + + if (create_queues_exchanges == null) + { + create_queues_exchanges = new ConcurrentHashMap(); + create_queues.put(CREATE_QUEUE_EXCHANGES_KEY, create_queues_exchanges); + } + + //if we have an exchange + if (exchangeName != null) + { + //Retrieve the list of permitted exchanges. + Map exchanges = (Map) create_queues_exchanges.get(exchangeName); + + if (exchanges == null) + { + exchanges = new ConcurrentHashMap(); + create_queues_exchanges.put(exchangeName, exchanges); + } + + //Store the temporary setting CREATE_QUEUE_EXCHANGES_ROUTINGKEYS_KEY + exchanges.put(CREATE_QUEUE_EXCHANGES_TEMPORARY_KEY, temporary); + + //Store the binding details of queue/rk for this exchange. + if (queueName != null) + { + //Retrieve the list of permitted routingKeys. + Map rKeys = (Map) exchanges.get(exchangeName); + + if (rKeys == null) + { + rKeys = new ConcurrentHashMap(); + exchanges.put(CREATE_QUEUE_EXCHANGES_ROUTINGKEYS_KEY, rKeys); + } + + rKeys.put(queueName, routingKey); + } + } + } + + private void grantConsume(Permission permission, Object... parameters) { + Map consumeRights = (Map) _permissions.get(permission); + + if (consumeRights == null) + { + consumeRights = new ConcurrentHashMap(); + _permissions.put(permission, consumeRights); + } + + //if we have parametsre + if (parameters.length > 0) + { + AMQShortString queueName = (AMQShortString) parameters[0]; + Boolean temporary = (Boolean) parameters[1]; + Boolean ownQueueOnly = (Boolean) parameters[2]; + + if (temporary) + { + consumeRights.put(CONSUME_TEMPORARY_KEY, true); + } + else + { + consumeRights.put(CONSUME_TEMPORARY_KEY, false); + } + + if (ownQueueOnly) + { + consumeRights.put(CONSUME_OWN_QUEUES_ONLY_KEY, true); + } + else + { + consumeRights.put(CONSUME_OWN_QUEUES_ONLY_KEY, false); + } + + + LinkedList queues = (LinkedList) consumeRights.get(CONSUME_QUEUES_KEY); + if (queues == null) + { + queues = new LinkedList(); + consumeRights.put(CONSUME_QUEUES_KEY, queues); + } + + if (queueName != null) + { + queues.add(queueName); + } + } + } + /** * * @param permission the type of permission to check @@ -346,267 +357,286 @@ public class PrincipalPermissions return AuthzResult.ALLOWED; // This is here for completeness but the SimpleXML ACLManager never calls it. // The existence of this user specific PP can be validated in the map SimpleXML maintains. case BIND: // Parameters : QueueBindMethod , Exchange , AMQQueue, AMQShortString routingKey - - Exchange exchange = (Exchange) parameters[1]; - - AMQQueue bind_queueName = (AMQQueue) parameters[2]; - AMQShortString routingKey = (AMQShortString) parameters[3]; - - //Get all Create Rights for this user - Map bindCreateRights = (Map) _permissions.get(Permission.CREATEQUEUE); - - //Look up the Queue Creation Rights - Map bind_create_queues = (Map) bindCreateRights.get(CREATE_QUEUES_KEY); - - //Lookup the list of queues - Map bind_create_queues_queues = (Map) bindCreateRights.get(CREATE_QUEUE_QUEUES_KEY); - - // Check and see if we have a queue white list to check - if (bind_create_queues_queues != null) - { - //There a white list for queues - Map exchangeDetails = (Map) bind_create_queues_queues.get(bind_queueName); - - if (exchangeDetails == null) //Then all queue can be bound to all exchanges. - { - return AuthzResult.ALLOWED; - } - - // Check to see if we have a white list of routingkeys to check - Map rkeys = (Map) exchangeDetails.get(exchange.getName()); - - // if keys is null then any rkey is allowed on this exchange - if (rkeys == null) - { - // There is no routingkey white list - return AuthzResult.ALLOWED; - } - else - { - // We have routingKeys so a match must be found to allowed binding - Iterator keys = rkeys.keySet().iterator(); - - boolean matched = false; - while (keys.hasNext() && !matched) - { - AMQShortString rkey = (AMQShortString) keys.next(); - if (rkey.endsWith("*")) - { - matched = routingKey.startsWith(rkey.subSequence(0, rkey.length() - 1).toString()); - } - else - { - matched = routingKey.equals(rkey); - } - } - - - return (matched) ? AuthzResult.ALLOWED : AuthzResult.DENIED; - } - - - } - else - { - //There a is no white list for queues - - // So can allow all queues to be bound - // but we should first check and see if we have a temp queue and validate that we are allowed - // to bind temp queues. - - //Check to see if we have a temporary queue - if (bind_queueName.isAutoDelete()) - { - // Check and see if we have an exchange white list. - Map bind_exchanges = (Map) bind_create_queues.get(CREATE_QUEUE_EXCHANGES_KEY); - - // If the exchange exists then we must check to see if temporary queues are allowed here - if (bind_exchanges != null) - { - // Check to see if the requested exchange is allowed. - Map exchangeDetails = (Map) bind_exchanges.get(exchange.getName()); - - return ((Boolean) exchangeDetails.get(CREATE_QUEUE_EXCHANGES_TEMPORARY_KEY)) ? AuthzResult.ALLOWED : AuthzResult.DENIED; - } - - //no white list so all allowed, drop through to return true below. - } - - // not a temporary queue and no white list so all allowed. - return AuthzResult.ALLOWED; - } - + return authoriseBind(parameters); case CREATEQUEUE:// Parameters : boolean autodelete, AMQShortString name - - Map createRights = (Map) _permissions.get(permission); - - // If there are no create rights then deny request - if (createRights == null) - { - return AuthzResult.DENIED; - } - - //Look up the Queue Creation Rights - Map create_queues = (Map) createRights.get(CREATE_QUEUES_KEY); - - //Lookup the list of queues allowed to be created - Map create_queues_queues = (Map) create_queues.get(CREATE_QUEUE_QUEUES_KEY); - - - AMQShortString queueName = (AMQShortString) parameters[1]; - Boolean autoDelete = (Boolean) parameters[0]; - - if (autoDelete)// we have a temporary queue - { - return ((Boolean) create_queues.get(CREATE_QUEUE_TEMPORARY_KEY)) ? AuthzResult.ALLOWED : AuthzResult.DENIED; - } - else - { - // If there is a white list then check - if (create_queues_queues == null || create_queues_queues.containsKey(queueName)) - { - return AuthzResult.ALLOWED; - } - else - { - return AuthzResult.DENIED; - } - - } + return authoriseCreateQueue(permission, parameters); case CREATEEXCHANGE: - Map rights = (Map) _permissions.get(permission); - - AMQShortString exchangeName = (AMQShortString) parameters[0]; - - // If the exchange list is doesn't exist then all is allowed else - // check the valid exchanges - if (rights == null || rights.containsKey(exchangeName)) - { - return AuthzResult.ALLOWED; - } - else - { - return AuthzResult.DENIED; - } + return authoriseCreateExchange(permission, parameters); case CONSUME: // Parameters : AMQQueue - - if (parameters.length == 1 && parameters[0] instanceof AMQQueue) - { - AMQQueue queue = ((AMQQueue) parameters[0]); - Map queuePermissions = (Map) _permissions.get(permission); - - List queues = (List) queuePermissions.get(CONSUME_QUEUES_KEY); - - Boolean temporayQueues = (Boolean) queuePermissions.get(CONSUME_TEMPORARY_KEY); - Boolean ownQueuesOnly = (Boolean) queuePermissions.get(CONSUME_OWN_QUEUES_ONLY_KEY); - - // If user is allowed to publish to temporary queues and this is a temp queue then allow it. - if (temporayQueues) - { - if (queue.isAutoDelete()) - // This will allow consumption from any temporary queue including ones not owned by this user. - // Of course the exclusivity will not be broken. - { - // if not limited to ownQueuesOnly then ok else check queue Owner. - return (!ownQueuesOnly || queue.getOwner().equals(_user)) ? AuthzResult.ALLOWED : AuthzResult.DENIED; - } - else - { - return AuthzResult.DENIED; - } - } - - // if queues are white listed then ensure it is ok - if (queues != null) - { - // if no queues are listed then ALL are ok othereise it must be specified. - if (ownQueuesOnly) - { - if (queue.getOwner().equals(_user)) - { - return (queues.size() == 0 || queues.contains(queue.getName())) ? AuthzResult.ALLOWED : AuthzResult.DENIED; - } - else - { - return AuthzResult.DENIED; - } - } - - // If we are - return (queues.size() == 0 || queues.contains(queue.getName())) ? AuthzResult.ALLOWED : AuthzResult.DENIED; - } - } - - // Can't authenticate without the right parameters - return AuthzResult.DENIED; - case DELETE: - break; - + return authoriseConsume(permission, parameters); case PUBLISH: // Parameters : Exchange exchange, AMQShortString routingKey - Map publishRights = (Map) _permissions.get(permission); - - if (publishRights == null) - { - return AuthzResult.DENIED; - } - - Map exchanges = (Map) publishRights.get(PUBLISH_EXCHANGES_KEY); - - // Having no exchanges listed gives full publish rights to all exchanges - if (exchanges == null) - { - return AuthzResult.ALLOWED; - } - // Otherwise exchange must be listed in the white list - - // If the map doesn't have the exchange then it isn't allowed - if (!exchanges.containsKey(((Exchange) parameters[0]).getName())) - { - return AuthzResult.DENIED; - } - else - { - - // Get valid routing keys - HashSet routingKeys = (HashSet) exchanges.get(((Exchange)parameters[0]).getName()); - - // Having no routingKeys in the map then all are allowed. - if (routingKeys == null) - { - return AuthzResult.ALLOWED; - } - else - { - // We have routingKeys so a match must be found to allowed binding - Iterator keys = routingKeys.iterator(); - - - AMQShortString publishRKey = (AMQShortString)parameters[1]; - - boolean matched = false; - while (keys.hasNext() && !matched) - { - AMQShortString rkey = (AMQShortString) keys.next(); - - if (rkey.endsWith("*")) - { - matched = publishRKey.startsWith(rkey.subSequence(0, rkey.length() - 1)); - } - else - { - matched = publishRKey.equals(rkey); - } - } - return (matched) ? AuthzResult.ALLOWED : AuthzResult.DENIED; - } - } + return authorisePublish(permission, parameters); + /* Fall through */ + case DELETE: case PURGE: - break; case UNBIND: - break; - + default: + return AuthzResult.DENIED; } - return AuthzResult.DENIED; } + + private AuthzResult authoriseConsume(Permission permission, Object... parameters) { + if (parameters.length == 1 && parameters[0] instanceof AMQQueue) + { + AMQQueue queue = ((AMQQueue) parameters[0]); + Map queuePermissions = (Map) _permissions.get(permission); + + if (queuePermissions == null) + { + //if the outer map is null, the user has no CONSUME rights at all + return AuthzResult.DENIED; + } + + List queues = (List) queuePermissions.get(CONSUME_QUEUES_KEY); + + Boolean temporayQueues = (Boolean) queuePermissions.get(CONSUME_TEMPORARY_KEY); + Boolean ownQueuesOnly = (Boolean) queuePermissions.get(CONSUME_OWN_QUEUES_ONLY_KEY); + + // If user is allowed to publish to temporary queues and this is a temp queue then allow it. + if (temporayQueues) + { + if (queue.isAutoDelete()) + // This will allow consumption from any temporary queue including ones not owned by this user. + // Of course the exclusivity will not be broken. + { + // if not limited to ownQueuesOnly then ok else check queue Owner. + return (!ownQueuesOnly || queue.getOwner().equals(_user)) ? AuthzResult.ALLOWED : AuthzResult.DENIED; + } + else + { + return AuthzResult.DENIED; + } + } + + // if queues are white listed then ensure it is ok + if (queues != null) + { + // if no queues are listed then ALL are ok othereise it must be specified. + if (ownQueuesOnly) + { + if (queue.getOwner().equals(_user)) + { + return (queues.size() == 0 || queues.contains(queue.getName())) ? AuthzResult.ALLOWED : AuthzResult.DENIED; + } + else + { + return AuthzResult.DENIED; + } + } + + // If we are + return (queues.size() == 0 || queues.contains(queue.getName())) ? AuthzResult.ALLOWED : AuthzResult.DENIED; + } + } + + // Can't authenticate without the right parameters + return AuthzResult.DENIED; + } + + private AuthzResult authorisePublish(Permission permission, Object... parameters) { + Map publishRights = (Map) _permissions.get(permission); + + if (publishRights == null) + { + return AuthzResult.DENIED; + } + + Map exchanges = (Map) publishRights.get(PUBLISH_EXCHANGES_KEY); + + // Having no exchanges listed gives full publish rights to all exchanges + if (exchanges == null) + { + return AuthzResult.ALLOWED; + } + // Otherwise exchange must be listed in the white list + + // If the map doesn't have the exchange then it isn't allowed + if (!exchanges.containsKey(((Exchange) parameters[0]).getName())) + { + return AuthzResult.DENIED; + } + else + { + + // Get valid routing keys + HashSet routingKeys = (HashSet) exchanges.get(((Exchange)parameters[0]).getName()); + + // Having no routingKeys in the map then all are allowed. + if (routingKeys == null) + { + return AuthzResult.ALLOWED; + } + else + { + // We have routingKeys so a match must be found to allowed binding + Iterator keys = routingKeys.iterator(); + + + AMQShortString publishRKey = (AMQShortString)parameters[1]; + + boolean matched = false; + while (keys.hasNext() && !matched) + { + AMQShortString rkey = (AMQShortString) keys.next(); + + if (rkey.endsWith("*")) + { + matched = publishRKey.startsWith(rkey.subSequence(0, rkey.length() - 1)); + } + else + { + matched = publishRKey.equals(rkey); + } + } + return (matched) ? AuthzResult.ALLOWED : AuthzResult.DENIED; + } + } + } + + private AuthzResult authoriseCreateExchange(Permission permission, Object... parameters) { + Map rights = (Map) _permissions.get(permission); + + AMQShortString exchangeName = (AMQShortString) parameters[0]; + + // If the exchange list is doesn't exist then all is allowed else + // check the valid exchanges + if (rights == null || rights.containsKey(exchangeName)) + { + return AuthzResult.ALLOWED; + } + else + { + return AuthzResult.DENIED; + } + } + + private AuthzResult authoriseCreateQueue(Permission permission, Object... parameters) { + Map createRights = (Map) _permissions.get(permission); + + // If there are no create rights then deny request + if (createRights == null) + { + return AuthzResult.DENIED; + } + + //Look up the Queue Creation Rights + Map create_queues = (Map) createRights.get(CREATE_QUEUES_KEY); + + //Lookup the list of queues allowed to be created + Map create_queues_queues = (Map) create_queues.get(CREATE_QUEUE_QUEUES_KEY); + + + AMQShortString queueName = (AMQShortString) parameters[1]; + Boolean autoDelete = (Boolean) parameters[0]; + + if (autoDelete)// we have a temporary queue + { + return ((Boolean) create_queues.get(CREATE_QUEUE_TEMPORARY_KEY)) ? AuthzResult.ALLOWED : AuthzResult.DENIED; + } + else + { + // If there is a white list then check + if (create_queues_queues == null || create_queues_queues.containsKey(queueName)) + { + return AuthzResult.ALLOWED; + } + else + { + return AuthzResult.DENIED; + } + + } + } + + private AuthzResult authoriseBind(Object... parameters) { + Exchange exchange = (Exchange) parameters[1]; + + AMQQueue bind_queueName = (AMQQueue) parameters[2]; + AMQShortString routingKey = (AMQShortString) parameters[3]; + + //Get all Create Rights for this user + Map bindCreateRights = (Map) _permissions.get(Permission.CREATEQUEUE); + + //Look up the Queue Creation Rights + Map bind_create_queues = (Map) bindCreateRights.get(CREATE_QUEUES_KEY); + + //Lookup the list of queues + Map bind_create_queues_queues = (Map) bindCreateRights.get(CREATE_QUEUE_QUEUES_KEY); + + // Check and see if we have a queue white list to check + if (bind_create_queues_queues != null) + { + //There a white list for queues + Map exchangeDetails = (Map) bind_create_queues_queues.get(bind_queueName); + + if (exchangeDetails == null) //Then all queue can be bound to all exchanges. + { + return AuthzResult.ALLOWED; + } + + // Check to see if we have a white list of routingkeys to check + Map rkeys = (Map) exchangeDetails.get(exchange.getName()); + + // if keys is null then any rkey is allowed on this exchange + if (rkeys == null) + { + // There is no routingkey white list + return AuthzResult.ALLOWED; + } + else + { + // We have routingKeys so a match must be found to allowed binding + Iterator keys = rkeys.keySet().iterator(); + + boolean matched = false; + while (keys.hasNext() && !matched) + { + AMQShortString rkey = (AMQShortString) keys.next(); + if (rkey.endsWith("*")) + { + matched = routingKey.startsWith(rkey.subSequence(0, rkey.length() - 1).toString()); + } + else + { + matched = routingKey.equals(rkey); + } + } + + + return (matched) ? AuthzResult.ALLOWED : AuthzResult.DENIED; + } + + + } + else + { + //There a is no white list for queues + + // So can allow all queues to be bound + // but we should first check and see if we have a temp queue and validate that we are allowed + // to bind temp queues. + + //Check to see if we have a temporary queue + if (bind_queueName.isAutoDelete()) + { + // Check and see if we have an exchange white list. + Map bind_exchanges = (Map) bind_create_queues.get(CREATE_QUEUE_EXCHANGES_KEY); + + // If the exchange exists then we must check to see if temporary queues are allowed here + if (bind_exchanges != null) + { + // Check to see if the requested exchange is allowed. + Map exchangeDetails = (Map) bind_exchanges.get(exchange.getName()); + + return ((Boolean) exchangeDetails.get(CREATE_QUEUE_EXCHANGES_TEMPORARY_KEY)) ? AuthzResult.ALLOWED : AuthzResult.DENIED; + } + + //no white list so all allowed, drop through to return true below. + } + + // not a temporary queue and no white list so all allowed. + return AuthzResult.ALLOWED; + } + } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/BasicACLPlugin.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/BasicACLPlugin.java index a6fae053c2..ca6b68dafa 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/BasicACLPlugin.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/BasicACLPlugin.java @@ -35,28 +35,24 @@ public abstract class BasicACLPlugin implements ACLPlugin // Returns true or false if the plugin should authorise or deny the request protected abstract AuthzResult getResult(); - @Override public AuthzResult authoriseBind(AMQProtocolSession session, Exchange exch, AMQQueue queue, AMQShortString routingKey) { return getResult(); } - @Override public AuthzResult authoriseConnect(AMQProtocolSession session, VirtualHost virtualHost) { return getResult(); } - @Override public AuthzResult authoriseConsume(AMQProtocolSession session, boolean noAck, AMQQueue queue) { return getResult(); } - @Override public AuthzResult authoriseConsume(AMQProtocolSession session, boolean exclusive, boolean noAck, boolean noLocal, boolean nowait, AMQQueue queue) @@ -64,7 +60,6 @@ public abstract class BasicACLPlugin implements ACLPlugin return getResult(); } - @Override public AuthzResult authoriseCreateExchange(AMQProtocolSession session, boolean autoDelete, boolean durable, AMQShortString exchangeName, boolean internal, boolean nowait, boolean passive, @@ -73,7 +68,6 @@ public abstract class BasicACLPlugin implements ACLPlugin return getResult(); } - @Override public AuthzResult authoriseCreateQueue(AMQProtocolSession session, boolean autoDelete, boolean durable, boolean exclusive, boolean nowait, boolean passive, AMQShortString queue) @@ -81,19 +75,16 @@ public abstract class BasicACLPlugin implements ACLPlugin return getResult(); } - @Override public AuthzResult authoriseDelete(AMQProtocolSession session, AMQQueue queue) { return getResult(); } - @Override public AuthzResult authoriseDelete(AMQProtocolSession session, Exchange exchange) { return getResult(); } - @Override public AuthzResult authorisePublish(AMQProtocolSession session, boolean immediate, boolean mandatory, AMQShortString routingKey, Exchange e) @@ -101,20 +92,17 @@ public abstract class BasicACLPlugin implements ACLPlugin return getResult(); } - @Override public AuthzResult authorisePurge(AMQProtocolSession session, AMQQueue queue) { return getResult(); } - @Override public AuthzResult authoriseUnbind(AMQProtocolSession session, Exchange exch, AMQShortString routingKey, AMQQueue queue) { return getResult(); } - @Override public void setConfiguration(Configuration config) { // no-op diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/network/FirewallPlugin.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/network/FirewallPlugin.java index 3a81932123..7450322130 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/network/FirewallPlugin.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/network/FirewallPlugin.java @@ -211,7 +211,6 @@ public class FirewallPlugin extends AbstractACLPlugin } - @Override public void setConfiguration(Configuration config) throws ConfigurationException { // Get default action diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabaseManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabaseManager.java index 4efe381a8b..8658101cd8 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabaseManager.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabaseManager.java @@ -42,7 +42,6 @@ public class PropertiesPrincipalDatabaseManager implements PrincipalDatabaseMana return _databases; } - @Override public void initialiseManagement(ServerConfiguration _configuration) throws ConfigurationException { //todo diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java index 72d6afc65c..2893e916cc 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java @@ -630,11 +630,19 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage public QueueEntry getLastSeenEntry() { - return _queueContext.get(); + QueueEntry entry = _queueContext.get(); + + if(_logger.isDebugEnabled()) + { + _logger.debug(_logActor + ": lastSeenEntry: " + (entry == null ? "null" : entry.debugIdentity())); + } + + return entry; } public boolean setLastSeenEntry(QueueEntry expected, QueueEntry newvalue) { + _logger.debug(debugIdentity() + " Setting Last Seen To:" + (newvalue == null ? "nullNV" : newvalue.debugIdentity())); return _queueContext.compareAndSet(expected,newvalue); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransactionalContext.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransactionalContext.java index 3c71282c57..450852cef7 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransactionalContext.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransactionalContext.java @@ -97,6 +97,7 @@ public class LocalTransactionalContext implements TransactionalContext try { QueueEntry entry = _queue.enqueue(getStoreContext(),_message); + _queue.checkCapacity(_channel); if(entry.immediateAndNotDelivered()) { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/NonTransactionalContext.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/NonTransactionalContext.java index 28af36e3db..10d6021d27 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/NonTransactionalContext.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/NonTransactionalContext.java @@ -91,6 +91,8 @@ public class NonTransactionalContext implements TransactionalContext public void deliver(final AMQQueue queue, AMQMessage message) throws AMQException { QueueEntry entry = queue.enqueue(_storeContext, message); + queue.checkCapacity(_channel); + //following check implements the functionality //required by the 'immediate' flag: diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java index b16a289f0a..a131c2a465 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java @@ -31,6 +31,7 @@ import org.apache.qpid.server.store.StoreContext; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.server.management.ManagedObject; import org.apache.qpid.server.registry.ApplicationRegistry; +import org.apache.qpid.server.AMQChannel; import org.apache.qpid.AMQException; import org.apache.commons.configuration.Configuration; @@ -271,6 +272,15 @@ public class MockAMQQueue implements AMQQueue //To change body of implemented methods use File | Settings | File Templates. } + public boolean getBlockOnQueueFull() + { + return false; + } + + public void setBlockOnQueueFull(boolean block) + { + } + public long getMinimumAlertRepeatGap() { return 0; //To change body of implemented methods use File | Settings | File Templates. @@ -285,8 +295,8 @@ public class MockAMQQueue implements AMQQueue { return 0; //To change body of implemented methods use File | Settings | File Templates. } + - @Override public void checkMessageStatus() throws AMQException { //To change body of implemented methods use File | Settings | File Templates. @@ -317,6 +327,10 @@ public class MockAMQQueue implements AMQQueue //To change body of implemented methods use File | Settings | File Templates. } + public void checkCapacity(AMQChannel channel) + { + } + public ManagedObject getManagedObject() { return null; //To change body of implemented methods use File | Settings | File Templates. @@ -327,12 +341,31 @@ public class MockAMQQueue implements AMQQueue return 0; //To change body of implemented methods use File | Settings | File Templates. } - @Override public void setMinimumAlertRepeatGap(long value) { } + public long getCapacity() + { + return 0; //To change body of implemented methods use File | Settings | File Templates. + } + + public void setCapacity(long capacity) + { + //To change body of implemented methods use File | Settings | File Templates. + } + + public long getFlowResumeCapacity() + { + return 0; //To change body of implemented methods use File | Settings | File Templates. + } + + public void setFlowResumeCapacity(long flowResumeCapacity) + { + //To change body of implemented methods use File | Settings | File Templates. + } + public void configure(QueueConfiguration config) { diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/registry/ApplicationRegistryShutdownTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/registry/ApplicationRegistryShutdownTest.java index e75ed640aa..4c8ff01be0 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/registry/ApplicationRegistryShutdownTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/registry/ApplicationRegistryShutdownTest.java @@ -22,7 +22,6 @@ package org.apache.qpid.server.registry; import junit.framework.TestCase; import org.apache.qpid.server.util.TestApplicationRegistry; -import org.apache.qpid.AMQException; import java.security.Security; import java.security.Provider; @@ -69,7 +68,7 @@ public class ApplicationRegistryShutdownTest extends TestCase // Register new providers try { - _registry.initialise(); + _registry.initialise(ApplicationRegistry.DEFAULT_INSTANCE); } catch (Exception e) { diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/util/NullApplicationRegistry.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/util/NullApplicationRegistry.java index 8fef8baa02..6b8201eefb 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/util/NullApplicationRegistry.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/util/NullApplicationRegistry.java @@ -27,6 +27,7 @@ import org.apache.qpid.server.configuration.VirtualHostConfiguration; import org.apache.qpid.server.logging.RootMessageLoggerImpl; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.actors.TestLogActor; +import org.apache.qpid.server.logging.actors.BrokerActor; import org.apache.qpid.server.logging.rawloggers.Log4jMessageLogger; import org.apache.qpid.server.management.NoopManagedObjectRegistry; import org.apache.qpid.server.plugins.PluginManager; @@ -50,7 +51,7 @@ public class NullApplicationRegistry extends ApplicationRegistry super(new ServerConfiguration(new PropertiesConfiguration())); } - public void initialise() throws Exception + public void initialise(int instanceID) throws Exception { _logger.info("Initialising NullApplicationRegistry"); @@ -92,6 +93,8 @@ public class NullApplicationRegistry extends ApplicationRegistry @Override public void close() throws Exception { + CurrentActor.set(new BrokerActor(_rootMessageLogger)); + try { super.close(); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/util/TestApplicationRegistry.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/util/TestApplicationRegistry.java index 43948c05c4..7b7c86bb80 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/util/TestApplicationRegistry.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/util/TestApplicationRegistry.java @@ -21,7 +21,6 @@ package org.apache.qpid.server.util; import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.MapConfiguration; import org.apache.commons.configuration.PropertiesConfiguration; import org.apache.qpid.server.configuration.ServerConfiguration; import org.apache.qpid.server.configuration.VirtualHostConfiguration; @@ -31,7 +30,6 @@ import org.apache.qpid.server.management.NoopManagedObjectRegistry; import org.apache.qpid.server.queue.QueueRegistry; import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.security.access.ACLManager; -import org.apache.qpid.server.security.access.ACLPlugin; import org.apache.qpid.server.security.access.plugins.AllowAll; import org.apache.qpid.server.security.auth.database.PropertiesPrincipalDatabaseManager; import org.apache.qpid.server.security.auth.manager.PrincipalDatabaseAuthenticationManager; @@ -45,7 +43,6 @@ import org.apache.qpid.server.logging.actors.TestLogActor; import org.apache.qpid.server.logging.rawloggers.Log4jMessageLogger; import java.util.Collection; -import java.util.HashMap; import java.util.Properties; import java.util.Arrays; @@ -75,7 +72,7 @@ public class TestApplicationRegistry extends ApplicationRegistry _config = config; } - public void initialise() throws Exception + public void initialise(int instanceID) throws Exception { _rootMessageLogger = new RootMessageLoggerImpl(_configuration, new Log4jMessageLogger()); diff --git a/qpid/java/client/src/main/java/log4j.xml b/qpid/java/client/src/main/java/log4j.xml new file mode 100644 index 0000000000..c27acba818 --- /dev/null +++ b/qpid/java/client/src/main/java/log4j.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java index 0d2adcec8a..ed122a772e 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java @@ -313,7 +313,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect protected AMQConnectionDelegate _delegate; // this connection maximum number of prefetched messages - protected int _maxPrefetch; + private int _maxPrefetch; //Indicates whether persistent messages are synchronized private boolean _syncPersistence; @@ -450,7 +450,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect } else { - // use the defaul value set for all connections + // use the default value set for all connections _syncPublish = System.getProperty((ClientProperties.SYNC_ACK_PROP_NAME),_syncPublish); } @@ -512,7 +512,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect boolean retryAllowed = true; Exception connectionException = null; - while (!_connected && retryAllowed) + while (!_connected && retryAllowed && brokerDetails != null) { ProtocolVersion pe = null; try @@ -691,12 +691,12 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect public boolean attemptReconnection() { - while (_failoverPolicy.failoverAllowed()) + BrokerDetails broker = null; + while (_failoverPolicy.failoverAllowed() && (broker = _failoverPolicy.getNextBrokerDetails()) != null) { try { - makeBrokerConnection(_failoverPolicy.getNextBrokerDetails()); - + makeBrokerConnection(broker); return true; } catch (Exception e) diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate.java b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate.java index e5980d8b7d..e6c3473cb1 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate.java @@ -39,6 +39,15 @@ public interface AMQConnectionDelegate Session createSession(final boolean transacted, final int acknowledgeMode, final int prefetchHigh, final int prefetchLow) throws JMSException; + /** + * Create an XASession with default prefetch values of: + * High = MaxPrefetch + * Low = MaxPrefetch / 2 + * @return XASession + * @throws JMSException thrown if there is a problem creating the session. + */ + XASession createXASession() throws JMSException; + XASession createXASession(int prefetchHigh, int prefetchLow) throws JMSException; void failoverPrep(); diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_0_10.java b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_0_10.java index 927929c94a..4d10180667 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_0_10.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_0_10.java @@ -99,6 +99,18 @@ public class AMQConnectionDelegate_0_10 implements AMQConnectionDelegate, Connec return session; } + /** + * Create an XASession with default prefetch values of: + * High = MaxPrefetch + * Low = MaxPrefetch / 2 + * @return XASession + * @throws JMSException + */ + public XASession createXASession() throws JMSException + { + return createXASession((int) _conn.getMaxPrefetch(), (int) _conn.getMaxPrefetch() / 2); + } + /** * create an XA Session and start it if required. */ @@ -285,7 +297,6 @@ public class AMQConnectionDelegate_0_10 implements AMQConnectionDelegate, Connec _qpidConnection.setIdleTimeout(l); } - @Override public int getMaxChannelID() { return Integer.MAX_VALUE; diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_8_0.java b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_8_0.java index 9876393d4c..97d0d0516e 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_8_0.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_8_0.java @@ -191,6 +191,18 @@ public class AMQConnectionDelegate_8_0 implements AMQConnectionDelegate }, _conn).execute(); } + /** + * Create an XASession with default prefetch values of: + * High = MaxPrefetch + * Low = MaxPrefetch / 2 + * @return XASession + * @throws JMSException thrown if there is a problem creating the session. + */ + public XASession createXASession() throws JMSException + { + return createXASession((int) _conn.getMaxPrefetch(), (int) _conn.getMaxPrefetch() / 2); + } + private void createChannelOverWire(int channelId, int prefetchHigh, int prefetchLow, boolean transacted) throws AMQException, FailoverException { @@ -290,7 +302,6 @@ public class AMQConnectionDelegate_8_0 implements AMQConnectionDelegate public void setIdleTimeout(long l){} - @Override public int getMaxChannelID() { return (int) (Math.pow(2, 16)-1); diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession.java b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession.java index 2e3e417c95..dd9a00ce10 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession.java @@ -21,7 +21,6 @@ package org.apache.qpid.client; import java.io.Serializable; -import java.io.IOException; import java.net.URISyntaxException; import java.text.MessageFormat; import java.util.ArrayList; @@ -60,6 +59,7 @@ import javax.jms.Topic; import javax.jms.TopicPublisher; import javax.jms.TopicSession; import javax.jms.TopicSubscriber; +import javax.jms.TransactionRolledBackException; import org.apache.qpid.AMQDisconnectedException; import org.apache.qpid.AMQException; @@ -113,7 +113,6 @@ import org.slf4j.LoggerFactory; public abstract class AMQSession extends Closeable implements Session, QueueSession, TopicSession { - public static final class IdToConsumerMap { private final BasicMessageConsumer[] _fastAccessConsumers = new BasicMessageConsumer[16]; @@ -198,16 +197,32 @@ public abstract class AMQSession= System.currentTimeMillis() ) + { + + _flowControl.wait(FLOW_CONTROL_WAIT_PERIOD); + _logger.warn("Message send delayed by " + (System.currentTimeMillis() + FLOW_CONTROL_WAIT_FAILURE - expiryTime)/1000 + "s due to broker enforced flow control"); + } + if(!_flowControl.getFlowControl()) { - _flowControl.wait(); + _logger.error("Message send failed due to timeout waiting on broker enforced flow control"); + throw new JMSException("Unable to send message for " + FLOW_CONTROL_WAIT_FAILURE/1000 + " seconds due to broker enforced flow control"); } } diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java index 0644bd88a8..1587d6a6bf 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java @@ -414,9 +414,6 @@ public class AMQSession_0_10 extends AMQSession extends Closeable implements Messa else { _session.addDeliveredMessage(msg.getDeliveryTag()); + _session.markDirty(); } break; diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java b/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java index 5ff6066ddc..44ce59975a 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java @@ -60,7 +60,7 @@ public abstract class BasicMessageProducer extends Closeable implements org.apac /** * Priority of messages created by this producer. */ - private int _messagePriority; + private int _messagePriority = Message.DEFAULT_PRIORITY; /** * Time to live of messages. Specified in milliseconds but AMQ has 1 second resolution. diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/XAConnectionImpl.java b/qpid/java/client/src/main/java/org/apache/qpid/client/XAConnectionImpl.java index 20fa68605a..43025bd724 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/XAConnectionImpl.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/XAConnectionImpl.java @@ -47,7 +47,7 @@ public class XAConnectionImpl extends AMQConnection implements XAConnection, XAQ public synchronized XASession createXASession() throws JMSException { checkNotClosed(); - return _delegate.createXASession(_maxPrefetch, _maxPrefetch / 2); + return _delegate.createXASession(); } //-- Interface XAQueueConnection diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/configuration/ClientProperties.java b/qpid/java/client/src/main/java/org/apache/qpid/client/configuration/ClientProperties.java index 3627618e68..be0d283470 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/configuration/ClientProperties.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/configuration/ClientProperties.java @@ -39,7 +39,7 @@ public class ClientProperties * type: long */ public static final String MAX_PREFETCH_PROP_NAME = "max_prefetch"; - public static final String MAX_PREFETCH_DEFAULT = "5000"; + public static final String MAX_PREFETCH_DEFAULT = "500"; /** * When true a sync command is sent after every persistent messages. diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/failover/FailoverHandler.java b/qpid/java/client/src/main/java/org/apache/qpid/client/failover/FailoverHandler.java index 8223cd5394..7761215450 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/failover/FailoverHandler.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/failover/FailoverHandler.java @@ -21,6 +21,7 @@ package org.apache.qpid.client.failover; import org.apache.qpid.AMQDisconnectedException; +import org.apache.qpid.AMQException; import org.apache.qpid.client.protocol.AMQProtocolHandler; import org.apache.qpid.client.state.AMQStateManager; @@ -134,6 +135,7 @@ public class FailoverHandler implements Runnable // a slightly more complex state model therefore I felt it was worthwhile doing this. AMQStateManager existingStateManager = _amqProtocolHandler.getStateManager(); + // Use a fresh new StateManager for the reconnection attempts _amqProtocolHandler.setStateManager(new AMQStateManager()); diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/handler/ClientMethodDispatcherImpl.java b/qpid/java/client/src/main/java/org/apache/qpid/client/handler/ClientMethodDispatcherImpl.java index 9c791730ca..0e3333940a 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/handler/ClientMethodDispatcherImpl.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/handler/ClientMethodDispatcherImpl.java @@ -39,6 +39,7 @@ public class ClientMethodDispatcherImpl implements MethodDispatcher private static final BasicReturnMethodHandler _basicReturnMethodHandler = BasicReturnMethodHandler.getInstance(); private static final ChannelCloseMethodHandler _channelCloseMethodHandler = ChannelCloseMethodHandler.getInstance(); private static final ChannelFlowOkMethodHandler _channelFlowOkMethodHandler = ChannelFlowOkMethodHandler.getInstance(); + private static final ChannelFlowMethodHandler _channelFlowMethodHandler = ChannelFlowMethodHandler.getInstance(); private static final ConnectionCloseMethodHandler _connectionCloseMethodHandler = ConnectionCloseMethodHandler.getInstance(); private static final ConnectionOpenOkMethodHandler _connectionOpenOkMethodHandler = ConnectionOpenOkMethodHandler.getInstance(); private static final ConnectionRedirectMethodHandler _connectionRedirectMethodHandler = ConnectionRedirectMethodHandler.getInstance(); @@ -159,7 +160,8 @@ public class ClientMethodDispatcherImpl implements MethodDispatcher public boolean dispatchChannelFlow(ChannelFlowBody body, int channelId) throws AMQException { - return false; + _channelFlowMethodHandler.methodReceived(_session, body, channelId); + return true; } public boolean dispatchChannelFlowOk(ChannelFlowOkBody body, int channelId) throws AMQException diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java b/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java index 06a1fe2696..e645f4f214 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java @@ -308,7 +308,6 @@ public class AMQProtocolHandler implements ProtocolEngine */ public void exception(Throwable cause) { - _logger.info("AS: HELLO"); if (_failoverState == FailoverState.NOT_STARTED) { // if (!(cause instanceof AMQUndeliveredException) && (!(cause instanceof AMQAuthenticationException))) diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/util/BlockingWaiter.java b/qpid/java/client/src/main/java/org/apache/qpid/client/util/BlockingWaiter.java index 67cda957fb..a3d015eadc 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/util/BlockingWaiter.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/util/BlockingWaiter.java @@ -253,7 +253,7 @@ public abstract class BlockingWaiter } else { - System.err.println("WARNING: new error arrived while old one not yet processed"); + System.err.println("WARNING: new error '" + e == null ? "null" : e.getMessage() + "' arrived while old one not yet processed:" + _error.getMessage()); } try diff --git a/qpid/java/client/src/main/java/org/apache/qpid/jms/failover/FailoverExchangeMethod.java b/qpid/java/client/src/main/java/org/apache/qpid/jms/failover/FailoverExchangeMethod.java index e05a7ab6e2..960661daea 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/jms/failover/FailoverExchangeMethod.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/jms/failover/FailoverExchangeMethod.java @@ -189,7 +189,8 @@ public class FailoverExchangeMethod implements FailoverMethod, MessageListener { synchronized (_brokerListLock) { - return _connectionDetails.getBrokerDetails(_currentBrokerIndex); + _currentBrokerDetail = _connectionDetails.getBrokerDetails(_currentBrokerIndex); + return _currentBrokerDetail; } } @@ -214,7 +215,15 @@ public class FailoverExchangeMethod implements FailoverMethod, MessageListener broker.getHost().equals(_currentBrokerDetail.getHost()) && broker.getPort() == _currentBrokerDetail.getPort()) { - return getNextBrokerDetails(); + if (_connectionDetails.getBrokerCount() > 1) + { + return getNextBrokerDetails(); + } + else + { + _failedAttemps ++; + return null; + } } String delayStr = broker.getProperty(BrokerDetails.OPTIONS_CONNECT_DELAY); diff --git a/qpid/java/common/bin/qpid-run b/qpid/java/common/bin/qpid-run index 0b5070d937..63bb648fd8 100755 --- a/qpid/java/common/bin/qpid-run +++ b/qpid/java/common/bin/qpid-run @@ -111,6 +111,7 @@ if [ -n "$QPID_LOG_SUFFIX" ]; then fi log $INFO System Properties set to $SYSTEM_PROPS +log $INFO QPID_OPTS set to $QPID_OPTS program=$(basename $0) sourced=${BASH_SOURCE[0]} diff --git a/qpid/java/common/src/main/java/org/apache/qpid/ConsoleOutput.java b/qpid/java/common/src/main/java/org/apache/qpid/ConsoleOutput.java index 3c1ea22595..7d8a5b7b36 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/ConsoleOutput.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/ConsoleOutput.java @@ -51,7 +51,6 @@ public class ConsoleOutput implements Sender System.out.println("CLOSED"); } - @Override public void setIdleTimeout(long l) { // TODO Auto-generated method stub diff --git a/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/LoggingManagement.java b/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/LoggingManagement.java index 98dba9fed1..cb3387c6d3 100644 --- a/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/LoggingManagement.java +++ b/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/LoggingManagement.java @@ -110,7 +110,7 @@ public interface LoggingManagement * Reloads the log4j configuration file, applying any changes made. * * @throws IOException - * @since Qpid JMX API 1.3 + * @since Qpid JMX API 1.4 */ @MBeanOperation(name = "reloadConfigFile", description = "Reload the log4j xml configuration file", impact = MBeanOperationInfo.ACTION) void reloadConfigFile() throws IOException; diff --git a/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ServerInformation.java b/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ServerInformation.java index c158c26857..5819631dba 100644 --- a/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ServerInformation.java +++ b/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ServerInformation.java @@ -43,7 +43,7 @@ public interface ServerInformation * Qpid JMX API 1.1 can be assumed. */ int QPID_JMX_API_MAJOR_VERSION = 1; - int QPID_JMX_API_MINOR_VERSION = 3; + int QPID_JMX_API_MINOR_VERSION = 4; /** diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationRegistry.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationRegistry.java index cd6f7ff808..9259d36d79 100644 --- a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationRegistry.java +++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationRegistry.java @@ -48,7 +48,7 @@ public abstract class ApplicationRegistry //max supported broker management interface supported by this release of the management console public static final int SUPPORTED_QPID_JMX_API_MAJOR_VERSION = 1; - public static final int SUPPORTED_QPID_JMX_API_MINOR_VERSION = 3; + public static final int SUPPORTED_QPID_JMX_API_MINOR_VERSION = 4; public static final String DATA_DIR = System.getProperty("user.home") + File.separator + ".qpidmc"; diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/ConfigurationFileTabControl.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/ConfigurationFileTabControl.java index 1b1d08aa67..536033368f 100644 --- a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/ConfigurationFileTabControl.java +++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/ConfigurationFileTabControl.java @@ -349,7 +349,7 @@ public class ConfigurationFileTabControl extends TabControl _logWatchIntervalLabel.setFont(ApplicationRegistry.getFont(FONT_BOLD)); _logWatchIntervalLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, true)); - if(_ApiVersion.greaterThanOrEqualTo(1, 3)) + if(_ApiVersion.greaterThanOrEqualTo(1, 4)) { Group reloadConfigFileGroup = new Group(attributesComposite, SWT.SHADOW_NONE); reloadConfigFileGroup.setBackground(attributesComposite.getBackground()); diff --git a/qpid/java/module.xml b/qpid/java/module.xml index 0c32414647..5796af928a 100644 --- a/qpid/java/module.xml +++ b/qpid/java/module.xml @@ -261,6 +261,7 @@ + @@ -269,6 +270,7 @@ + diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/BrokerStartupTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/BrokerStartupTest.java index 52120019f5..e7975f8d24 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/server/BrokerStartupTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/BrokerStartupTest.java @@ -78,15 +78,23 @@ public class BrokerStartupTest extends AbstractTestLogging // Add an invalid value _broker += " -l invalid"; - // The release-bin build of the broker uses this log4j configuration - // so set up the broker environment to use it for this test. - // Also include -Dlog4j.debug so we can validate that it picked up this config - setBrokerEnvironment("QPID_OPTS", "-Dlog4j.debug -Dlog4j.configuration=file:" + System.getProperty(QPID_HOME) + "/../broker/src/main/java/log4j.properties"); + // The broker has a built in default log4j configuration set up + // so if the the broker cannot load the -l value it will use default + // use this default. Test that this is correctly loaded, by + // including -Dlog4j.debug so we can validate. + setBrokerEnvironment("QPID_OPTS", "-Dlog4j.debug"); // Disable all client logging so we can test for broker DEBUG only. - Logger.getRootLogger().setLevel(Level.WARN); - Logger.getLogger("qpid.protocol").setLevel(Level.WARN); - Logger.getLogger("org.apache.qpid").setLevel(Level.WARN); + setLoggerLevel(Logger.getRootLogger(), Level.WARN); + setLoggerLevel(Logger.getLogger("qpid.protocol"), Level.WARN); + setLoggerLevel(Logger.getLogger("org.apache.qpid"), Level.WARN); + + // Set the broker to use info level logging, which is the qpid-server + // default. Rather than debug which is the test default. + setBrokerOnlySystemProperty("amqj.server.logging.level", "info"); + // Set the logging defaults to info for this test. + setBrokerOnlySystemProperty("amqj.logging.level", "info"); + setBrokerOnlySystemProperty("root.logging.level", "info"); startBroker(); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/failover/MessageDisappearWithIOExceptionTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/failover/MessageDisappearWithIOExceptionTest.java new file mode 100644 index 0000000000..f1a1c1a9a8 --- /dev/null +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/failover/MessageDisappearWithIOExceptionTest.java @@ -0,0 +1,330 @@ +/* + * + * 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.failover; + +import org.apache.mina.common.WriteTimeoutException; +import org.apache.qpid.client.AMQConnection; +import org.apache.qpid.client.protocol.AMQProtocolSession; +import org.apache.qpid.jms.ConnectionListener; +import org.apache.qpid.test.utils.QpidTestCase; +import org.apache.qpid.test.utils.FailoverBaseCase; +import org.apache.qpid.AMQConnectionClosedException; + +import javax.jms.Destination; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Queue; +import javax.jms.Session; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +/** + * Test case based on user reported error. + * + * Summary: + * A user has reported message loss from their application. On bouncing of + * the broker the 'lost' messages are delivered to the broker. + * + * Note: + * The client was using Spring so that may influence the situation. + * + * Issue: + * The log files show 7 instances of the following which result in 7 + * missing messages. + * + * The client log files show: + * + * The broker log file show: + * + * + * 7 missing messages have delivery tags 5-11. Which says that they are + * sequentially the next message from the broker. + * + * The only way for the 'without a handler' log to occur is if the consumer + * has been removed from the look up table of the dispatcher. + * And the only way for the 'null message' log to occur on the broker is is + * if the message does not exist in the unacked-map + * + * The consumer is only removed from the list during session + * closure and failover. + * + * If the session was closed then the broker would requeue the unacked + * messages so the potential exists to have an empty map but the broker + * will not send a message out after the unacked map has been cleared. + * + * When failover occurs the _consumer map is cleared and the consumers are + * resubscribed. This is down without first stopping any existing + * dispatcher so there exists the potential to receive a message after + * the _consumer map has been cleared which is how the 'without a handler' + * log statement occurs. + * + * Scenario: + * + * Looking over logs the sequence that best fits the events is as follows: + * - Something causes Mina to be delayed causing the WriteTimoutException. + * - This exception is recevied by AMQProtocolHandler#exceptionCaught + * - As the WriteTimeoutException is an IOException this will cause + * sessionClosed to be called to start failover. + * + This is potentially the issues here. All IOExceptions are treated + * as connection failure events. + * - Failover Runs + * + Failover assumes that the previous connection has been closed. + * + Failover binds the existing objects (AMQConnection/Session) to the + * new connection objects. + * - Everything is reported as being successfully failed over. + * However, what is neglected is that the original connection has not + * been closed. + * + So what occurs is that the broker sends a message to the consumer on + * the original connection, as it was not notified of the client + * failing over. + * As the client failover reuses the original AMQSession and Dispatcher + * the new messages the broker sends to the old consumer arrives at the + * client and is processed by the same AMQSession and Dispatcher. + * However, as the failover process cleared the _consumer map and + * resubscribe the consumers the Dispatcher does not recognise the + * delivery tag and so logs the 'without a handler' message. + * - The Dispatcher then attempts to reject the message, however, + * + The AMQSession/Dispatcher pair have been swapped to using a new Mina + * ProtocolSession as part of the failover process so the reject is + * sent down the second connection. The broker receives the Reject + * request but as the Message was sent on a different connection the + * unacknowledgemap is empty and a 'message is null' log message + * produced. + * + * Test Strategy: + * + * It should be easy to demonstrate if we can send an IOException to + * AMQProtocolHandler#exceptionCaught and then try sending a message. + * + * The current unknowns here are the type of consumers that are in use. + * If it was an exclusive queue(Durable Subscription) then why did the + * resubscribe not fail. + * + * If it was not exclusive then why did the messages not round robin? + */ +public class MessageDisappearWithIOExceptionTest extends FailoverBaseCase implements ConnectionListener +{ + private CountDownLatch _failoverOccured = new CountDownLatch(1); + AMQConnection _connection; + Session _session; + Queue _queue; + MessageConsumer _consumer; + + public void setUp() throws Exception + { + super.setUp(); + stopBroker(getFailingPort()); + + } + + /** + * Test Summary: + * + * Create a queue consumer and send 10 messages to the broker. + * + * Consume the first message. + * This will pull the rest into the prefetch + * + * Send an IOException to the MinaProtocolHandler. + * + * This will force failover to occur. + * + * 9 messages would normally be expected but it is expected that none will + * arrive. As they are still in the prefetch of the first session. + * + * To free the messages we need to close all connections. + * - Simply doing connection.close() and retesting will not be enough as + * the original connection's IO layer will still exist and is nolonger + * connected to the connection object as a result of failover. + * + * - Test will need to retain a reference to the original connection IO so + * that it can be closed releasing the messages to validate that the + * messages have indeed been 'lost' on that sesssion. + */ + public void test() throws Exception + { + initialiseConnection(); + + // Create Producer + // Send 10 messages + List messages = sendNumberedBytesMessage(_session, _queue, 10); + + // Consume first messasge + Message received = _consumer.receive(2000); + + // Verify received messages + assertNotNull("First message not received.", received); + assertEquals("Incorrect message Received", + messages.remove(0).getIntProperty("count"), + received.getIntProperty("count")); + + // Allow ack to be sent to broker, by performing a synchronous command + // along the session. +// _session.createConsumer(_session.createTemporaryQueue()).close(); + + //Retain IO Layer + AMQProtocolSession protocolSession = _connection.getProtocolHandler().getProtocolSession(); + + // Send IO Exception - causing failover + _connection.getProtocolHandler(). + exception(new WriteTimeoutException("WriteTimeoutException to cause failover.")); + + // Verify Failover occured through ConnectionListener + assertTrue("Failover did not occur", + _failoverOccured.await(4000, TimeUnit.MILLISECONDS)); + + //Verify new protocolSession is not the same as the original + assertNotSame("Protocol Session has not changed", + protocolSession, + _connection.getProtocolHandler().getProtocolSession()); + + /***********************************/ + // This verifies that the bug has been resolved + + // Attempt to consume again. Expect 9 messages + for (int count = 1; count < 10; count++) + { + received = _consumer.receive(2000); + assertNotNull("Expected message not received:" + count, received); + assertEquals(messages.remove(0).getIntProperty("count"), + received.getIntProperty("count")); + } + + //Verify there are no more messages + received = _consumer.receive(1000); + assertNull("Message receieved when there should be none:" + received, + received); + +// /***********************************/ +// // This verifies that the bug exists +// +// // Attempt to consume remaining 9 messages.. Expecting NONE. +// // receiving just one message should fail so no need to fail 9 times +// received = _consumer.receive(1000); +// assertNull("Message receieved when it should be null:" + received, received); +// +//// //Close the Connection which you would assume would free the messages +//// _connection.close(); +//// +//// // Reconnect +//// initialiseConnection(); +//// +//// // We should still be unable to receive messages +//// received = _consumer.receive(1000); +//// assertNull("Message receieved when it should be null:" + received, received); +//// +//// _connection.close(); +// +// // Close original IO layer. Expecting messages to be released +// protocolSession.closeProtocolSession(); +// +// // Reconnect and all should be good. +//// initialiseConnection(); +// +// // Attempt to consume again. Expect 9 messages +// for (int count = 1; count < 10; count++) +// { +// received = _consumer.receive(2000); +// assertNotNull("Expected message not received:" + count, received); +// assertEquals(messages.remove(0).getIntProperty("count"), +// received.getIntProperty("count")); +// } +// +// //Verify there are no more messages +// received = _consumer.receive(1000); +// assertNull("Message receieved when there should be none:" + received, +// received); + } + + private void initialiseConnection() + throws Exception + { + //Create Connection + _connection = (AMQConnection) getConnection(); + _connection.setConnectionListener(this); + + _session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + + _queue = _session.createQueue(getTestQueueName()); + + // Create Consumer + _consumer = _session.createConsumer(_queue); + + //Start connection + _connection.start(); + } + + /** QpidTestCase back port to this release */ + + // modified from QTC as sendMessage is not testable. + // - should be renamed sendBlankBytesMessage + // - should be renamed sendNumberedBytesMessage + public List sendNumberedBytesMessage(Session session, Destination destination, + int count) throws Exception + { + List messages = new ArrayList(count); + + MessageProducer producer = session.createProducer(destination); + + for (int i = 0; i < count; i++) + { + Message next = session.createMessage(); + + next.setIntProperty("count", i); + + producer.send(next); + + messages.add(next); + } + + producer.close(); + return messages; + } + + public void bytesSent(long count) + { + //To change body of implemented methods use File | Settings | File Templates. + } + + public void bytesReceived(long count) + { + } + + public boolean preFailover(boolean redirect) + { + //Allow failover to occur + return true; + } + + public boolean preResubscribe() + { + //Allow failover to occur + return true; + } + + public void failoverComplete() + { + _failoverOccured.countDown(); + } +} diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/BrokerLoggingTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/BrokerLoggingTest.java index 4f50aba61d..b00a71315e 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/BrokerLoggingTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/BrokerLoggingTest.java @@ -160,7 +160,7 @@ public class BrokerLoggingTest extends AbstractTestLogging // Set the broker.ready string to check for the _log4j default that // is still present on standard out. - System.setProperty(BROKER_READY, "Qpid Broker Ready"); + setTestClientSystemProperty(BROKER_READY, "Qpid Broker Ready"); startBroker(); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/DeepQueueConsumeWithSelector.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/DeepQueueConsumeWithSelector.java index dfb5cde247..83f0f87bc5 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/DeepQueueConsumeWithSelector.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/DeepQueueConsumeWithSelector.java @@ -63,7 +63,6 @@ import java.util.concurrent.TimeUnit; */ public class DeepQueueConsumeWithSelector extends QpidTestCase implements MessageListener { - private static final String INDEX = "index"; private static final int MESSAGE_COUNT = 10000; private static final int BATCH_SIZE = MESSAGE_COUNT / 10; @@ -129,9 +128,7 @@ public class DeepQueueConsumeWithSelector extends QpidTestCase implements Messag @Override public Message createNextMessage(Session session, int msgCount) throws JMSException { - Message message = session.createTextMessage("Message :" + msgCount); - - message.setIntProperty(INDEX, msgCount); + Message message = super.createNextMessage(session,msgCount); if ((msgCount % BATCH_SIZE) == 0 ) { diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/ProducerFlowControlTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/ProducerFlowControlTest.java new file mode 100644 index 0000000000..f220760511 --- /dev/null +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/ProducerFlowControlTest.java @@ -0,0 +1,393 @@ +/* +* +* 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.queue; + +import org.apache.log4j.Logger; +import org.apache.qpid.client.AMQSession; +import org.apache.qpid.client.AMQQueue; +import org.apache.qpid.client.AMQDestination; +import org.apache.qpid.test.utils.QpidTestCase; +import org.apache.qpid.AMQException; +import org.apache.qpid.server.logging.AbstractTestLogging; +import org.apache.qpid.framing.AMQShortString; + +import javax.jms.*; +import javax.naming.NamingException; +import java.util.HashMap; +import java.util.Map; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; +import java.io.IOException; + +public class ProducerFlowControlTest extends AbstractTestLogging +{ + private static final int TIMEOUT = 1500; + + + private static final Logger _logger = Logger.getLogger(ProducerFlowControlTest.class); + + protected final String QUEUE = "ProducerFlowControl"; + + private static final int MSG_COUNT = 50; + + private Connection producerConnection; + private MessageProducer producer; + private Session producerSession; + private Queue queue; + private Connection consumerConnection; + private Session consumerSession; + + + private MessageConsumer consumer; + private final AtomicInteger _sentMessages = new AtomicInteger(); + + public void setUp() throws Exception + { + super.setUp(); + + _monitor.reset(); + + producerConnection = getConnection(); + producerSession = producerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE); + + producerConnection.start(); + + consumerConnection = getConnection(); + consumerSession = consumerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE); + + } + + public void tearDown() throws Exception + { + producerConnection.close(); + consumerConnection.close(); + super.tearDown(); + } + + public void testCapacityExceededCausesBlock() + throws JMSException, NamingException, AMQException, InterruptedException + { + final Map arguments = new HashMap(); + arguments.put("x-qpid-capacity",1000); + arguments.put("x-qpid-flow-resume-capacity",800); + ((AMQSession) producerSession).createQueue(new AMQShortString(QUEUE), true, false, false, arguments); + queue = new AMQQueue("amq.direct",QUEUE); + ((AMQSession) producerSession).declareAndBind((AMQDestination)queue); + producer = producerSession.createProducer(queue); + + _sentMessages.set(0); + + + // try to send 5 messages (should block after 4) + sendMessagesAsync(producer, producerSession, 5, 50L); + + Thread.sleep(5000); + + assertEquals("Incorrect number of message sent before blocking", 4, _sentMessages.get()); + + consumer = consumerSession.createConsumer(queue); + consumerConnection.start(); + + + consumer.receive(); + + Thread.sleep(1000); + + assertEquals("Message incorrectly sent after one message received", 4, _sentMessages.get()); + + + consumer.receive(); + + Thread.sleep(1000); + + assertEquals("Message not sent after two messages received", 5, _sentMessages.get()); + + } + + public void testBrokerLogMessages() + throws JMSException, NamingException, AMQException, InterruptedException, IOException + { + final Map arguments = new HashMap(); + arguments.put("x-qpid-capacity",1000); + arguments.put("x-qpid-flow-resume-capacity",800); + ((AMQSession) producerSession).createQueue(new AMQShortString(QUEUE), true, false, false, arguments); + queue = new AMQQueue("amq.direct",QUEUE); + ((AMQSession) producerSession).declareAndBind((AMQDestination)queue); + producer = producerSession.createProducer(queue); + + _sentMessages.set(0); + + + // try to send 5 messages (should block after 4) + sendMessagesAsync(producer, producerSession, 5, 50L); + + Thread.sleep(5000); + List results = _monitor.findMatches("QUE-1003"); + + assertEquals("Did not find correct number of QUE-1003 queue overfull messages", 1, results.size()); + + consumer = consumerSession.createConsumer(queue); + consumerConnection.start(); + + + while(consumer.receive(1000) != null); + + results = _monitor.findMatches("QUE-1004"); + + assertEquals("Did not find correct number of QUE_1004 queue underfull messages", 1, results.size()); + + + + } + + + public void testClientLogMessages() + throws JMSException, NamingException, AMQException, InterruptedException, IOException + { + setTestClientSystemProperty("qpid.flow_control_wait_failure","3000"); + setTestClientSystemProperty("qpid.flow_control_wait_notify_period","1000"); + + Session session = producerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE); + + + final Map arguments = new HashMap(); + arguments.put("x-qpid-capacity",1000); + arguments.put("x-qpid-flow-resume-capacity",800); + ((AMQSession) session).createQueue(new AMQShortString(QUEUE), true, false, false, arguments); + queue = new AMQQueue("amq.direct",QUEUE); + ((AMQSession) session).declareAndBind((AMQDestination)queue); + producer = session.createProducer(queue); + + _sentMessages.set(0); + + + // try to send 5 messages (should block after 4) + MessageSender sender = sendMessagesAsync(producer, producerSession, 5, 50L); + + Thread.sleep(10000); + List results = _monitor.findMatches("Message send delayed by"); + assertEquals("Incorrect number of delay messages logged by client",3,results.size()); + results = _monitor.findMatches("Message send failed due to timeout waiting on broker enforced flow control"); + assertEquals("Incorrect number of send failure messages logged by client",1,results.size()); + + + + } + + + public void testFlowControlOnCapacityResumeEqual() + throws JMSException, NamingException, AMQException, InterruptedException + { + final Map arguments = new HashMap(); + arguments.put("x-qpid-capacity",1000); + arguments.put("x-qpid-flow-resume-capacity",1000); + ((AMQSession) producerSession).createQueue(new AMQShortString(QUEUE), true, false, false, arguments); + queue = new AMQQueue("amq.direct",QUEUE); + ((AMQSession) producerSession).declareAndBind((AMQDestination)queue); + producer = producerSession.createProducer(queue); + + _sentMessages.set(0); + + // try to send 5 messages (should block after 4) + sendMessagesAsync(producer, producerSession, 5, 50L); + + Thread.sleep(5000); + + assertEquals("Incorrect number of message sent before blocking", 4, _sentMessages.get()); + + consumer = consumerSession.createConsumer(queue); + consumerConnection.start(); + + + consumer.receive(); + + Thread.sleep(1000); + + assertEquals("Message incorrectly sent after one message received", 5, _sentMessages.get()); + + + } + + + public void testFlowControlSoak() + throws Exception, NamingException, AMQException, InterruptedException + { + _sentMessages.set(0); + final int numProducers = 10; + final int numMessages = 100; + + final Map arguments = new HashMap(); + arguments.put("x-qpid-capacity",6000); + arguments.put("x-qpid-flow-resume-capacity",3000); + + ((AMQSession) consumerSession).createQueue(new AMQShortString(QUEUE), false, false, false, arguments); + + queue = new AMQQueue("amq.direct",QUEUE); + ((AMQSession) consumerSession).declareAndBind((AMQDestination)queue); + consumerConnection.start(); + + Connection[] producers = new Connection[numProducers]; + for(int i = 0 ; i < numProducers; i ++) + { + + producers[i] = getConnection(); + producers[i].start(); + Session session = producers[i].createSession(false, Session.AUTO_ACKNOWLEDGE); + + MessageProducer myproducer = session.createProducer(queue); + MessageSender sender = sendMessagesAsync(myproducer, session, numMessages, 50L); + } + + consumer = consumerSession.createConsumer(queue); + consumerConnection.start(); + + for(int j = 0; j < numProducers * numMessages; j++) + { + + Message msg = consumer.receive(5000); + Thread.sleep(50L); + assertNotNull("Message not received("+j+"), sent: "+_sentMessages.get(), msg); + + } + + + + Message msg = consumer.receive(500); + assertNull("extra message received", msg); + + + for(int i = 0; i < numProducers; i++) + { + producers[i].close(); + } + + } + + + + public void testSendTimeout() + throws JMSException, NamingException, AMQException, InterruptedException + { + setTestClientSystemProperty("qpid.flow_control_wait_failure","3000"); + Session session = producerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE); + + + final Map arguments = new HashMap(); + arguments.put("x-qpid-capacity",1000); + arguments.put("x-qpid-flow-resume-capacity",800); + ((AMQSession) session).createQueue(new AMQShortString(QUEUE), true, false, false, arguments); + queue = new AMQQueue("amq.direct",QUEUE); + ((AMQSession) session).declareAndBind((AMQDestination)queue); + producer = session.createProducer(queue); + + _sentMessages.set(0); + + + // try to send 5 messages (should block after 4) + MessageSender sender = sendMessagesAsync(producer, producerSession, 5, 50L); + + Thread.sleep(10000); + + Exception e = sender.getException(); + + assertNotNull("No timeout exception on sending", e); + + } + + private MessageSender sendMessagesAsync(final MessageProducer producer, + final Session producerSession, + final int numMessages, + long sleepPeriod) + { + MessageSender sender = new MessageSender(producer, producerSession, numMessages,sleepPeriod); + new Thread(sender).start(); + return sender; + } + + private void sendMessages(MessageProducer producer, Session producerSession, int numMessages, long sleepPeriod) + throws JMSException + { + + for (int msg = 0; msg < numMessages; msg++) + { + producer.send(nextMessage(msg, producerSession)); + _sentMessages.incrementAndGet(); + + try + { + Thread.sleep(sleepPeriod); + } + catch (InterruptedException e) + { + } + } + } + + private static final byte[] BYTE_300 = new byte[300]; + + + private Message nextMessage(int msg, Session producerSession) throws JMSException + { + BytesMessage send = producerSession.createBytesMessage(); + send.writeBytes(BYTE_300); + send.setIntProperty("msg", msg); + + return send; + } + + + private class MessageSender implements Runnable + { + private final MessageProducer _producer; + private final Session _producerSession; + private final int _numMessages; + + + + private JMSException _exception; + private long _sleepPeriod; + + public MessageSender(MessageProducer producer, Session producerSession, int numMessages, long sleepPeriod) + { + _producer = producer; + _producerSession = producerSession; + _numMessages = numMessages; + _sleepPeriod = sleepPeriod; + } + + public void run() + { + try + { + sendMessages(_producer, _producerSession, _numMessages, _sleepPeriod); + } + catch (JMSException e) + { + _exception = e; + } + } + + public JMSException getException() + { + return _exception; + } + } +} \ No newline at end of file diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/SimpleACLTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/SimpleACLTest.java index bb7b5efc75..3e5470d5cb 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/SimpleACLTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/SimpleACLTest.java @@ -21,27 +21,34 @@ package org.apache.qpid.server.security.acl; - -import junit.framework.TestCase; - -import org.apache.log4j.BasicConfigurator; -import org.apache.log4j.Logger; -import org.apache.qpid.client.transport.TransportConnection; -import org.apache.qpid.client.*; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.registry.ConfigurationFileApplicationRegistry; -import org.apache.qpid.AMQConnectionFailureException; +import org.apache.commons.configuration.ConfigurationException; import org.apache.qpid.AMQException; -import org.apache.qpid.test.utils.QpidTestCase; +import org.apache.qpid.AMQConnectionFailureException; +import org.apache.qpid.client.AMQAuthenticationException; +import org.apache.qpid.client.AMQConnection; +import org.apache.qpid.client.AMQSession; +import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.jms.ConnectionListener; +import org.apache.qpid.test.utils.QpidTestCase; import org.apache.qpid.url.URLSyntaxException; +import org.apache.qpid.server.registry.ApplicationRegistry; +import org.apache.qpid.server.registry.ConfigurationFileApplicationRegistry; + -import javax.jms.*; +import javax.jms.Connection; +import javax.jms.DeliveryMode; +import javax.jms.ExceptionListener; import javax.jms.IllegalStateException; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Queue; +import javax.jms.Session; +import javax.jms.TextMessage; import javax.naming.NamingException; - import java.io.File; +import java.io.IOException; import java.util.ArrayList; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -53,6 +60,14 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E private CountDownLatch _awaitError = new CountDownLatch(51); 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 + } + + private void setUpACLTest() throws Exception { final String QPID_HOME = System.getProperty("QPID_HOME"); @@ -73,8 +88,10 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E return "amqp://" + username + ":" + password + "@clientid/test?brokerlist='" + getBroker() + "?retries='0''"; } - public void testAccessAuthorized() throws AMQException, URLSyntaxException + public void testAccessAuthorized() throws AMQException, URLSyntaxException, Exception { + setUpACLTest(); + try { Connection conn = getConnection("client", "guest"); @@ -96,6 +113,8 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E public void testAccessNoRights() throws Exception { + setUpACLTest(); + try { Connection conn = getConnection("guest", "guest"); @@ -120,8 +139,40 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E } } - public void testClientConsumeFromTempQueueValid() throws AMQException, URLSyntaxException + public void testGuestConsumeWithCreateRightsAndWithoutConsumeRights() throws NamingException, ConfigurationException, IOException, Exception + { + //Customise the ACL config to give the guest user some create (could be any, non-consume) rights to + //force creation of a PrincipalPermissions instance to perform the consume rights check against. + setConfigurationProperty("virtualhosts.virtualhost.test.security.access_control_list.create.queues.queue.users.user", "guest"); + + setUpACLTest(); + + try + { + Connection conn = getConnection("guest", "guest"); + + Session sesh = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + + conn.start(); + + sesh.createConsumer(sesh.createQueue("example.RequestQueue")); + + conn.close(); + } + 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()); + } + } + + public void testClientConsumeFromTempQueueValid() throws AMQException, URLSyntaxException, Exception { + setUpACLTest(); + try { Connection conn = getConnection("client", "guest"); @@ -142,6 +193,8 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E public void testClientConsumeFromNamedQueueInvalid() throws NamingException, Exception { + setUpACLTest(); + try { Connection conn = getConnection("client", "guest"); @@ -167,8 +220,10 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E } } - public void testClientCreateTemporaryQueue() throws JMSException, URLSyntaxException + public void testClientCreateTemporaryQueue() throws JMSException, URLSyntaxException, Exception { + setUpACLTest(); + try { Connection conn = getConnection("client", "guest"); @@ -191,6 +246,8 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E public void testClientCreateNamedQueue() throws NamingException, JMSException, AMQException, Exception { + setUpACLTest(); + try { Connection conn = getConnection("client", "guest"); @@ -212,8 +269,10 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E } } - public void testClientPublishUsingTransactionSuccess() throws AMQException, URLSyntaxException + public void testClientPublishUsingTransactionSuccess() throws AMQException, URLSyntaxException, Exception { + setUpACLTest(); + try { Connection conn = getConnection("client", "guest"); @@ -239,8 +298,10 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E } } - public void testClientPublishValidQueueSuccess() throws AMQException, URLSyntaxException + public void testClientPublishValidQueueSuccess() throws AMQException, URLSyntaxException, Exception { + setUpACLTest(); + try { Connection conn = getConnection("client", "guest"); @@ -271,6 +332,8 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E public void testClientPublishInvalidQueueSuccess() throws AMQException, URLSyntaxException, JMSException, NamingException, Exception { + setUpACLTest(); + try { Connection conn = getConnection("client", "guest"); @@ -311,8 +374,10 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E assertTrue("Did not get AMQAuthenticationException thrown", foundCorrectException); } - public void testServerConsumeFromNamedQueueValid() throws AMQException, URLSyntaxException + public void testServerConsumeFromNamedQueueValid() throws AMQException, URLSyntaxException, Exception { + setUpACLTest(); + try { Connection conn = getConnection("server", "guest"); @@ -333,6 +398,8 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E public void testServerConsumeFromNamedQueueInvalid() throws AMQException, URLSyntaxException, NamingException, Exception { + setUpACLTest(); + try { Connection conn = getConnection("client", "guest"); @@ -358,6 +425,8 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E public void testServerConsumeFromTemporaryQueue() throws AMQException, URLSyntaxException, NamingException, Exception { + setUpACLTest(); + try { Connection conn = getConnection("server", "guest"); @@ -391,8 +460,10 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E return (Connection) connection; } - public void testServerCreateNamedQueueValid() throws JMSException, URLSyntaxException + public void testServerCreateNamedQueueValid() throws JMSException, URLSyntaxException, Exception { + setUpACLTest(); + try { Connection conn = getConnection("server", "guest"); @@ -414,6 +485,8 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E public void testServerCreateNamedQueueInvalid() throws JMSException, URLSyntaxException, AMQException, NamingException, Exception { + setUpACLTest(); + try { Connection conn = getConnection("server", "guest"); @@ -436,6 +509,8 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E public void testServerCreateTemporaryQueueInvalid() throws NamingException, Exception { + setUpACLTest(); + try { Connection conn = getConnection("server", "guest"); @@ -461,6 +536,8 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E public void testServerCreateAutoDeleteQueueInvalid() throws NamingException, JMSException, AMQException, Exception { + setUpACLTest(); + Connection connection = null; try { @@ -492,6 +569,8 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E */ public void testServerPublishUsingTransactionSuccess() throws AMQException, URLSyntaxException, JMSException, NamingException, Exception { + setUpACLTest(); + //Set up the Server Connection serverConnection = getConnection("server", "guest"); @@ -572,6 +651,8 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E public void testServerPublishInvalidQueueSuccess() throws AMQException, URLSyntaxException, JMSException, NamingException, Exception { + setUpACLTest(); + try { Connection conn = getConnection("server", "guest"); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/client/QueueBrowserAutoAckTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/client/QueueBrowserAutoAckTest.java index 62b54d3086..f9cf48a2b1 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/client/QueueBrowserAutoAckTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/client/QueueBrowserAutoAckTest.java @@ -61,7 +61,7 @@ public class QueueBrowserAutoAckTest extends FailoverBaseCase setupSession(); - _queue = _clientSession.createQueue(getName()+System.currentTimeMillis()); + _queue = _clientSession.createQueue(getTestQueueName()); _clientSession.createConsumer(_queue).close(); //Ensure there are no messages on the queue to start with. @@ -497,7 +497,7 @@ public class QueueBrowserAutoAckTest extends FailoverBaseCase if (msgCount == failPoint) { - failBroker(); + failBroker(getFailingPort()); } } @@ -529,7 +529,7 @@ public class QueueBrowserAutoAckTest extends FailoverBaseCase sendMessages("connection2", messages); } - failBroker(); + failBroker(getFailingPort()); checkQueueDepth(messages); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/client/RollbackOrderTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/client/RollbackOrderTest.java index 39e2b892a9..ff766c907d 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/client/RollbackOrderTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/client/RollbackOrderTest.java @@ -22,64 +22,172 @@ package org.apache.qpid.test.client; import org.apache.qpid.test.utils.*; import javax.jms.*; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicBoolean; +import junit.framework.ComparisonFailure; +import junit.framework.AssertionFailedError; /** - * RollbackOrderTest + * RollbackOrderTest, QPID-1864, QPID-1871 + * + * Description: + * + * The problem that this test is exposing is that the dispatcher used to be capable + * of holding on to a message when stopped. This ment that when the rollback was + * called and the dispatcher stopped it may have hold of a message. So after all + * the local queues(preDeliveryQueue, SynchronousQueue, PostDeliveryTagQueue) + * have been cleared the client still had a single message, the one the + * dispatcher was holding on to. + * + * As a result the TxRollback operation would run and then release the dispatcher. + * Whilst the dispatcher would then proceed to reject the message it was holiding + * the Broker would already have resent that message so the rejection would silently + * fail. + * + * And the client would receieve that single message 'early', depending on the + * number of messages already recevied when rollback was called. + * + * + * Aims: + * + * The tests puts 50 messages on to the queue. + * + * The test then tries to cause the dispatcher to stop whilst it is in the process + * of moving a message from the preDeliveryQueue to a consumers sychronousQueue. + * + * To exercise this path we have 50 message flowing to the client to give the + * dispatcher a bit of work to do moving messages. + * + * Then we loop - 10 times + * - Validating that the first message received is always message 1. + * - Receive a few more so that there are a few messages to reject. + * - call rollback, to try and catch the dispatcher mid process. + * + * Outcome: + * + * The hope is that we catch the dispatcher mid process and cause a BasicReject + * to fail. Which will be indicated in the log but will also cause that failed + * rejected message to be the next to be delivered which will not be message 1 + * as expected. + * + * We are testing a race condition here but we can check through the log file if + * the race condition occured. However, performing that check will only validate + * the problem exists and will not be suitable as part of a system test. * */ - public class RollbackOrderTest extends QpidTestCase { - private Connection conn; - private Queue queue; - private Session ssn; - private MessageProducer prod; - private MessageConsumer cons; + private Connection _connection; + private Queue _queue; + private Session _session; + private MessageConsumer _consumer; @Override public void setUp() throws Exception { super.setUp(); - conn = getConnection(); - conn.start(); - ssn = conn.createSession(true, Session.AUTO_ACKNOWLEDGE); - queue = ssn.createQueue("rollback-order-test-queue"); - prod = ssn.createProducer(queue); - cons = ssn.createConsumer(queue); - for (int i = 0; i < 5; i++) - { - TextMessage msg = ssn.createTextMessage("message " + (i+1)); - prod.send(msg); - } - ssn.commit(); + _connection = getConnection(); + + _session = _connection.createSession(true, Session.SESSION_TRANSACTED); + _queue = _session.createQueue(getTestQueueName()); + _consumer = _session.createConsumer(_queue); + + //Send more messages so it is more likely that the dispatcher is + // processing on rollback. + sendMessage(_session, _queue, 50); + _session.commit(); + } public void testOrderingAfterRollback() throws Exception { - for (int i = 0; i < 10; i++) + //Start the session now so we + _connection.start(); + + for (int i = 0; i < 20; i++) { - TextMessage msg = (TextMessage) cons.receive(); - assertEquals("message 1", msg.getText()); - ssn.rollback(); + Message msg = _consumer.receive(); + assertEquals("Incorrect Message Received", 0, msg.getIntProperty(INDEX)); + + // Pull additional messages through so we have some reject work to do + for (int m=0; m < 5 ; m++) + { + _consumer.receive(); + } + + System.err.println("ROT-Rollback"); + _logger.warn("ROT-Rollback"); + _session.rollback(); } } - @Override public void tearDown() throws Exception + public void testOrderingAfterRollbackOnMessage() throws Exception { - while (true) + final CountDownLatch count= new CountDownLatch(20); + final Exception exceptions[] = new Exception[20]; + final AtomicBoolean failed = new AtomicBoolean(false); + + _consumer.setMessageListener(new MessageListener() { - Message msg = cons.receiveNoWait(); - if (msg == null) + + public void onMessage(Message message) { - break; + + Message msg = message; + try + { + count.countDown(); + assertEquals("Incorrect Message Received", 0, msg.getIntProperty(INDEX)); + + _session.rollback(); + } + catch (JMSException e) + { + System.out.println("Error:" + e.getMessage()); + exceptions[(int)count.getCount()] = e; + } + catch (AssertionFailedError cf) + { + // End Test if Equality test fails + while (count.getCount() != 0) + { + count.countDown(); + } + + System.out.println("Error:" + cf.getMessage()); + System.err.println(cf.getMessage()); + cf.printStackTrace(); + failed.set(true); + } } - else + }); + //Start the session now so we + _connection.start(); + + count.await(); + + for (Exception e : exceptions) + { + if (e != null) { - msg.acknowledge(); + System.err.println(e.getMessage()); + e.printStackTrace(); + failed.set(true); } } - ssn.commit(); + +// _consumer.close(); + _connection.close(); + + assertFalse("Exceptions thrown during test run, Check Std.err.", failed.get()); + } + + @Override public void tearDown() throws Exception + { + + drainQueue(_queue); + super.tearDown(); } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/client/failover/FailoverTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/client/failover/FailoverTest.java index dfc3bb7b42..c307176f3f 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/client/failover/FailoverTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/client/failover/FailoverTest.java @@ -37,7 +37,6 @@ import javax.naming.NamingException; import org.apache.log4j.Logger; import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.client.AMQSession_0_10; import org.apache.qpid.jms.BrokerDetails; import org.apache.qpid.jms.ConnectionListener; import org.apache.qpid.jms.ConnectionURL; @@ -58,13 +57,12 @@ public class FailoverTest extends FailoverBaseCase implements ConnectionListener private Session consumerSession; private MessageConsumer consumer; - private static int usedBrokers = 0; private CountDownLatch failoverComplete; - private static final long DEFAULT_FAILOVER_TIME = 10000L; private boolean CLUSTERED = Boolean.getBoolean("profile.clustered"); private int seed; private Random rand; - + private int _currentPort = getFailingPort(); + @Override protected void setUp() throws Exception { @@ -227,7 +225,7 @@ public class FailoverTest extends FailoverBaseCase implements ConnectionListener _logger.info("Failing over"); - causeFailure(DEFAULT_FAILOVER_TIME); + causeFailure(_currentPort, DEFAULT_FAILOVER_TIME); // Check that you produce and consume the rest of messages. _logger.debug("=================="); @@ -242,10 +240,10 @@ public class FailoverTest extends FailoverBaseCase implements ConnectionListener _logger.debug("=================="); } - private void causeFailure(long delay) + private void causeFailure(int port, long delay) { - failBroker(); + failBroker(port); _logger.info("Awaiting Failover completion"); try @@ -268,7 +266,7 @@ public class FailoverTest extends FailoverBaseCase implements ConnectionListener Message msg = consumer.receive(); assertNotNull("Expected msgs not received", msg); - causeFailure(DEFAULT_FAILOVER_TIME); + causeFailure(getFailingPort(), DEFAULT_FAILOVER_TIME); Exception failure = null; try @@ -314,7 +312,7 @@ public class FailoverTest extends FailoverBaseCase implements ConnectionListener long failTime = System.nanoTime() + FAILOVER_DELAY * 1000000; //Fail the first broker - causeFailure(FAILOVER_DELAY + DEFAULT_FAILOVER_TIME); + causeFailure(getFailingPort(), FAILOVER_DELAY + DEFAULT_FAILOVER_TIME); //Reconnection should occur assertTrue("Failover did not take long enough", System.nanoTime() > failTime); @@ -344,15 +342,15 @@ public class FailoverTest extends FailoverBaseCase implements ConnectionListener _logger.debug("==================================================================="); runP2PFailover(numMessages, false,false, false); - startBroker(getFailingPort()); + startBroker(_currentPort); if (useAltPort) { - setFailingPort(altPort); + _currentPort = altPort; useAltPort = false; } else { - setFailingPort(stdPort); + _currentPort = stdPort; useAltPort = true; } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/client/message/SelectorTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/client/message/SelectorTest.java index 5a5e23baa5..a09589b121 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/client/message/SelectorTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/client/message/SelectorTest.java @@ -1,31 +1,248 @@ +/* + * + * 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.test.client.message; -import javax.jms.Connection; -import javax.jms.Destination; +import java.util.concurrent.CountDownLatch; + +import javax.jms.DeliveryMode; +import javax.jms.InvalidSelectorException; +import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageConsumer; +import javax.jms.MessageListener; import javax.jms.MessageProducer; import javax.jms.Session; import junit.framework.Assert; -import org.apache.log4j.Logger; +import org.apache.qpid.AMQException; +import org.apache.qpid.client.AMQConnection; +import org.apache.qpid.client.AMQDestination; +import org.apache.qpid.client.AMQQueue; +import org.apache.qpid.client.AMQSession; +import org.apache.qpid.client.BasicMessageProducer; import org.apache.qpid.test.utils.QpidTestCase; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -public class SelectorTest extends QpidTestCase +public class SelectorTest extends QpidTestCase implements MessageListener { - private static final Logger _logger = Logger.getLogger(SelectorTest.class); + private static final Logger _logger = LoggerFactory.getLogger(SelectorTest.class); - public void testSelectorWithJMSMessageID() throws Exception + private AMQConnection _connection; + private AMQDestination _destination; + private int count; + public String _connectionString = "vm://:1"; + private static final String INVALID_SELECTOR = "Cost LIKE 5"; + CountDownLatch _responseLatch = new CountDownLatch(1); + + private static final String BAD_MATHS_SELECTOR = " 1 % 5"; + + private static final long RECIEVE_TIMEOUT = 1000; + + protected void setUp() throws Exception + { + super.setUp(); + init((AMQConnection) getConnection("guest", "guest")); + } + + private void init(AMQConnection connection) throws JMSException + { + init(connection, new AMQQueue(connection, getTestQueueName(), true)); + } + + private void init(AMQConnection connection, AMQDestination destination) throws JMSException + { + _connection = connection; + _destination = destination; + connection.start(); + } + + public void onMessage(Message message) + { + count++; + _logger.info("Got Message:" + message); + _responseLatch.countDown(); + } + + public void testUsingOnMessage() throws Exception + { + String selector = "Cost = 2 AND \"property-with-hyphen\" = 'wibble'"; + // selector = "JMSType = Special AND Cost = 2 AND AMQMessageID > 0 AND JMSDeliveryMode=" + DeliveryMode.NON_PERSISTENT; + + Session session = (AMQSession) _connection.createSession(false, AMQSession.NO_ACKNOWLEDGE); + // _session.createConsumer(destination).setMessageListener(this); + session.createConsumer(_destination, selector).setMessageListener(this); + + try + { + Message msg = session.createTextMessage("Message"); + msg.setJMSPriority(1); + msg.setIntProperty("Cost", 2); + msg.setStringProperty("property-with-hyphen", "wibble"); + msg.setJMSType("Special"); + + _logger.info("Sending Message:" + msg); + + ((BasicMessageProducer) session.createProducer(_destination)).send(msg, DeliveryMode.NON_PERSISTENT); + _logger.info("Message sent, waiting for response..."); + + _responseLatch.await(); + + if (count > 0) + { + _logger.info("Got message"); + } + + if (count == 0) + { + fail("Did not get message!"); + // throw new RuntimeException("Did not get message!"); + } + } + catch (JMSException e) + { + _logger.debug("JMS:" + e.getClass().getSimpleName() + ":" + e.getMessage()); + if (!(e instanceof InvalidSelectorException)) + { + fail("Wrong exception:" + e.getMessage()); + } + else + { + System.out.println("SUCCESS!!"); + } + } + catch (InterruptedException e) + { + _logger.debug("IE :" + e.getClass().getSimpleName() + ":" + e.getMessage()); + } + + } + + public void testUnparsableSelectors() throws Exception { - Connection conn = getConnection(); - conn.start(); - Session session = conn.createSession(true, Session.AUTO_ACKNOWLEDGE); + AMQSession session = (AMQSession) _connection.createSession(false, AMQSession.NO_ACKNOWLEDGE); + boolean caught = false; - Destination dest = session.createQueue("SelectorQueue"); + //Try Creating a Browser + try + { + session.createBrowser(session.createQueue("Ping"), INVALID_SELECTOR); + } + catch (JMSException e) + { + _logger.debug("JMS:" + e.getClass().getSimpleName() + ":" + e.getMessage()); + if (!(e instanceof InvalidSelectorException)) + { + fail("Wrong exception:" + e.getMessage()); + } + caught = true; + } + assertTrue("No exception thrown!", caught); + caught = false; + + //Try Creating a Consumer + try + { + session.createConsumer(session.createQueue("Ping"), INVALID_SELECTOR); + } + catch (JMSException e) + { + _logger.debug("JMS:" + e.getClass().getSimpleName() + ":" + e.getMessage()); + if (!(e instanceof InvalidSelectorException)) + { + fail("Wrong exception:" + e.getMessage()); + } + caught = true; + } + assertTrue("No exception thrown!", caught); + caught = false; + + //Try Creating a Receiever + try + { + session.createReceiver(session.createQueue("Ping"), INVALID_SELECTOR); + } + catch (JMSException e) + { + _logger.debug("JMS:" + e.getClass().getSimpleName() + ":" + e.getMessage()); + if (!(e instanceof InvalidSelectorException)) + { + fail("Wrong exception:" + e.getMessage()); + } + caught = true; + } + assertTrue("No exception thrown!", caught); + caught = false; + + try + { + session.createReceiver(session.createQueue("Ping"), BAD_MATHS_SELECTOR); + } + catch (JMSException e) + { + _logger.debug("JMS:" + e.getClass().getSimpleName() + ":" + e.getMessage()); + if (!(e instanceof InvalidSelectorException)) + { + fail("Wrong exception:" + e.getMessage()); + } + caught = true; + } + assertTrue("No exception thrown!", caught); + caught = false; - MessageProducer prod = session.createProducer(dest); - MessageConsumer consumer = session.createConsumer(dest,"JMSMessageID IS NOT NULL"); + } + + public void testRuntimeSelectorError() throws JMSException + { + Session session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + MessageConsumer consumer = session.createConsumer(_destination , "testproperty % 5 = 1"); + MessageProducer producer = session.createProducer(_destination); + Message sentMsg = session.createTextMessage(); + + sentMsg.setIntProperty("testproperty", 1); // 1 % 5 + producer.send(sentMsg); + Message recvd = consumer.receive(RECIEVE_TIMEOUT); + assertNotNull(recvd); + + sentMsg.setStringProperty("testproperty", "hello"); // "hello" % 5 makes no sense + producer.send(sentMsg); + try + { + recvd = consumer.receive(RECIEVE_TIMEOUT); + assertNull(recvd); + } + catch (Exception e) + { + + } + assertTrue("Connection should be closed", _connection.isClosed()); + } + + public void testSelectorWithJMSMessageID() throws Exception + { + Session session = _connection.createSession(true, Session.SESSION_TRANSACTED); + + MessageProducer prod = session.createProducer(_destination); + MessageConsumer consumer = session.createConsumer(_destination,"JMSMessageID IS NOT NULL"); for (int i=0; i<2; i++) { @@ -54,7 +271,7 @@ public class SelectorTest extends QpidTestCase Message msg3 = consumer.receive(1000); Assert.assertNull("Msg3 should be null", msg3); session.commit(); - consumer = session.createConsumer(dest,"JMSMessageID IS NULL"); + consumer = session.createConsumer(_destination,"JMSMessageID IS NULL"); Message msg4 = consumer.receive(1000); Message msg5 = consumer.receive(1000); @@ -62,4 +279,32 @@ public class SelectorTest extends QpidTestCase Assert.assertNotNull("Msg4 should not be null", msg4); Assert.assertNotNull("Msg5 should not be null", msg5); } + + public static void main(String[] argv) throws Exception + { + SelectorTest test = new SelectorTest(); + test._connectionString = (argv.length == 0) ? "localhost:3000" : argv[0]; + + try + { + while (true) + { + if (test._connectionString.contains("vm://:1")) + { + test.setUp(); + } + test.testUsingOnMessage(); + + if (test._connectionString.contains("vm://:1")) + { + test.tearDown(); + } + } + } + catch (Exception e) + { + System.err.println(e.getMessage()); + e.printStackTrace(); + } + } } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/Acknowledge2ConsumersTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/Acknowledge2ConsumersTest.java new file mode 100644 index 0000000000..4b45a96c20 --- /dev/null +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/Acknowledge2ConsumersTest.java @@ -0,0 +1,193 @@ +/* + * + * 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.test.unit.ack; + +import org.apache.qpid.client.AMQDestination; +import org.apache.qpid.client.AMQSession; +import org.apache.qpid.test.utils.FailoverBaseCase; + +import javax.jms.Connection; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.Queue; +import javax.jms.Session; + +public class Acknowledge2ConsumersTest extends FailoverBaseCase +{ + protected static int NUM_MESSAGES = 100; + protected Connection _con; + protected Queue _queue; + private Session _producerSession; + private Session _consumerSession; + private MessageConsumer _consumerA; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + + _queue = (Queue) getInitialContext().lookup("queue"); + + //Create Producer put some messages on the queue + _con = getConnection(); + } + + private void init(boolean transacted, int mode) throws JMSException + { + _producerSession = _con.createSession(true, Session.SESSION_TRANSACTED); + _consumerSession = _con.createSession(transacted, mode); + _consumerA = _consumerSession.createConsumer(_queue); + _con.start(); + } + + /** + * Produces Messages that + * + * @param transacted + * @param mode + * + * @throws Exception + */ + private void test2ConsumersAcking(boolean transacted, int mode) throws Exception + { + init(transacted, mode); + + // These should all end up being prefetched by sessionA + sendMessage(_producerSession, _queue, NUM_MESSAGES / 2); + + //Create a second consumer (consumerB) to consume some of the messages + MessageConsumer consumerB = _consumerSession.createConsumer(_queue); + + // These messages should be roundrobined between A and B + sendMessage(_producerSession, _queue, NUM_MESSAGES / 2); + + int count = 0; + //Use consumerB to receive messages it has + Message msg = consumerB.receive(1500); + while (msg != null) + { + if (mode == Session.CLIENT_ACKNOWLEDGE) + { + msg.acknowledge(); + } + count++; + msg = consumerB.receive(1500); + } + if (transacted) + { + _consumerSession.commit(); + } + + // Close the consumers + _consumerA.close(); + consumerB.close(); + + // and close the session to release any prefetched messages. + _consumerSession.close(); + assertEquals("Wrong number of messages on queue", NUM_MESSAGES - count, + ((AMQSession) _producerSession).getQueueDepth((AMQDestination) _queue)); + + // Clean up messages that may be left on the queue + _consumerSession = _con.createSession(transacted, mode); + _consumerA = _consumerSession.createConsumer(_queue); + msg = _consumerA.receive(1500); + while (msg != null) + { + if (mode == Session.CLIENT_ACKNOWLEDGE) + { + msg.acknowledge(); + } + msg = _consumerA.receive(1500); + } + _consumerA.close(); + if (transacted) + { + _consumerSession.commit(); + } + _consumerSession.close(); + } + + public void test2ConsumersAutoAck() throws Exception + { + test2ConsumersAcking(false, Session.AUTO_ACKNOWLEDGE); + } + + public void test2ConsumersClientAck() throws Exception + { + test2ConsumersAcking(false, Session.CLIENT_ACKNOWLEDGE); + } + + public void test2ConsumersTx() throws Exception + { + test2ConsumersAcking(true, Session.SESSION_TRANSACTED); + } + + + +// +// /** +// * Check that session level acknowledge does correctly ack all previous +// * values. Send 3 messages(0,1,2) then ack 1 and 2. If session ack is +// * working correctly then acking 1 will also ack 0. Acking 2 will not +// * attempt to re-ack 0 and 1. +// * +// * @throws Exception +// */ +// public void testSessionAck() throws Exception +// { +// init(false, Session.CLIENT_ACKNOWLEDGE); +// +// sendMessage(_producerSession, _queue, 3); +// Message msg; +// +// // Drop msg 0 +// _consumerA.receive(RECEIVE_TIMEOUT); +// +// // Take msg 1 +// msg = _consumerA.receive(RECEIVE_TIMEOUT); +// +// assertNotNull("Message 1 not correctly received.", msg); +// assertEquals("Incorrect message received", 1, msg.getIntProperty(INDEX)); +// +// // This should also ack msg 0 +// msg.acknowledge(); +// +// // Take msg 2 +// msg = _consumerA.receive(RECEIVE_TIMEOUT); +// +// assertNotNull("Message 2 not correctly received.", msg); +// assertEquals("Incorrect message received", 2, msg.getIntProperty(INDEX)); +// +// // This should just ack msg 2 +// msg.acknowledge(); +// +// _consumerA.close(); +// _consumerSession.close(); +// +// assertEquals("Queue not empty.", 0, +// ((AMQSession) _producerSession).getQueueDepth((AMQDestination) _queue)); +// _con.close(); +// +// +// } +} diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeAfterFailoverOnMessageTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeAfterFailoverOnMessageTest.java new file mode 100644 index 0000000000..f22a405fc3 --- /dev/null +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeAfterFailoverOnMessageTest.java @@ -0,0 +1,356 @@ +/* + * + * 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.test.unit.ack; + +import org.apache.qpid.client.AMQConnection; +import org.apache.qpid.client.AMQDestination; +import org.apache.qpid.client.AMQSession; +import org.apache.qpid.jms.ConnectionListener; + +import javax.jms.Connection; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageListener; +import javax.jms.Session; +import javax.jms.TransactionRolledBackException; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +public class AcknowledgeAfterFailoverOnMessageTest extends AcknowledgeOnMessageTest implements ConnectionListener +{ + + protected CountDownLatch _failoverCompleted = new CountDownLatch(1); + private MessageListener _listener = null; + + @Override + public void setUp() throws Exception + { + super.setUp(); + NUM_MESSAGES = 10; + } + + /** + * Override default init to add connectionListener so we can verify that + * failover took place + * + * @param transacted create a transacted session for this test + * @param mode if not transacted what ack mode to use for this test + * + * @throws Exception if a problem occured during test setup. + */ + @Override + public void init(boolean transacted, int mode) throws Exception + { + super.init(transacted, mode); + ((AMQConnection) _connection).setConnectionListener(this); + // Override the listener for the dirtyAck testing. + if (_listener != null) + { + _consumer.setMessageListener(_listener); + } + } + + protected void prepBroker(int count) throws Exception + { + //Stop the connection whilst we repopulate the broker, or the no_ack + // test will drain the msgs before we can check we put the right number + // back on again. +// _connection.stop(); + + Connection connection = getConnection(); + Session session = connection.createSession(true, Session.SESSION_TRANSACTED); + // ensure destination is created. + session.createConsumer(_queue).close(); + + sendMessage(session, _queue, count, NUM_MESSAGES - count, 0); + + if (_consumerSession.getAcknowledgeMode() != AMQSession.NO_ACKNOWLEDGE) + { + assertEquals("Wrong number of messages on queue", count, + ((AMQSession) session).getQueueDepth((AMQDestination) _queue)); + } + + connection.close(); + +// _connection.start(); + } + + @Override + public void doAcknowlegement(Message msg) throws JMSException + { + //Acknowledge current message + super.doAcknowlegement(msg); + + int msgCount = msg.getIntProperty(INDEX); + + if (msgCount % 2 == 0) + { + failBroker(getFailingPort()); + } + else + { + failBroker(getPort()); + } + + try + { + prepBroker(NUM_MESSAGES - msgCount - 1); + } + catch (Exception e) + { + fail("Unable to prep new broker," + e.getMessage()); + } + + try + { + + if (msgCount % 2 == 0) + { + startBroker(getFailingPort()); + } + else + { + startBroker(getPort()); + } + } + catch (Exception e) + { + fail("Unable to start failover broker," + e.getMessage()); + } + + } + + int msgCount = 0; + boolean cleaned = false; + + class DirtyAckingHandler implements MessageListener + { + /** + * Validate first message but do nothing with it. + * + * Failover + * + * The receive the message again + * + * @param message + */ + public void onMessage(Message message) + { + // Stop processing if we have an error and had to stop running. + if (_receviedAll.getCount() == 0) + { + _logger.debug("Dumping msgs due to error(" + _causeOfFailure.get().getMessage() + "):" + message); + return; + } + + try + { + // Check we have the next message as expected + assertNotNull("Message " + msgCount + " not correctly received.", message); + assertEquals("Incorrect message received", msgCount, message.getIntProperty(INDEX)); + + if (msgCount == 0 && _failoverCompleted.getCount() != 0) + { + // This is the first message we've received so lets fail the broker + + failBroker(getFailingPort()); + + repopulateBroker(); + + _logger.error("Received first msg so failing over"); + + return; + } + + msgCount++; + + // Don't acknowlege the first message after failover so we can commit + // them together + if (msgCount == 1) + { + _logger.error("Received first msg after failover ignoring:" + msgCount); + + // Acknowledge the first message if we are now on the cleaned pass + if (cleaned) + { + _receviedAll.countDown(); + } + + return; + } + + if (_consumerSession.getTransacted()) + { + try + { + _consumerSession.commit(); + if (!cleaned) + { + fail("Session is dirty we should get an TransactionRolledBackException"); + } + } + catch (TransactionRolledBackException trbe) + { + //expected path + } + } + else + { + try + { + message.acknowledge(); + if (!cleaned) + { + fail("Session is dirty we should get an IllegalStateException"); + } + } + catch (javax.jms.IllegalStateException ise) + { + assertEquals("Incorrect Exception thrown", "has failed over", ise.getMessage()); + // Recover the sesion and try again. + _consumerSession.recover(); + } + } + + // Acknowledge the last message if we are in a clean state + // this will then trigger test teardown. + if (cleaned) + { + _receviedAll.countDown(); + } + + //Reset message count so we can try again. + msgCount = 0; + cleaned = true; + } + catch (Exception e) + { + // If something goes wrong stop and notifiy main thread. + fail(e); + } + } + } + + /** + * Test that Acking/Committing a message received before failover causes + * an exception at commit/ack time. + * + * Expected behaviour is that in: + * * tx mode commit() throws a transacted RolledBackException + * * client ack mode throws an IllegalStateException + * + * @param transacted is this session trasacted + * @param mode What ack mode should be used if not trasacted + * + * @throws Exception if something goes wrong. + */ + protected void testDirtyAcking(boolean transacted, int mode) throws Exception + { + NUM_MESSAGES = 2; + _listener = new DirtyAckingHandler(); + + super.testAcking(transacted, mode); + } + + public void testDirtyClientAck() throws Exception + { + testDirtyAcking(false, Session.CLIENT_ACKNOWLEDGE); + } + + public void testDirtyAckingTransacted() throws Exception + { + testDirtyAcking(true, Session.SESSION_TRANSACTED); + } + + private void repopulateBroker() throws Exception + { + // Repopulate this new broker so we can test what happends after failover + + //Get the connection to the first (main port) broker. + Connection connection = getConnection(); + // Use a transaction to send messages so we can be sure they arrive. + Session session = connection.createSession(true, Session.SESSION_TRANSACTED); + // ensure destination is created. + session.createConsumer(_queue).close(); + + sendMessage(session, _queue, NUM_MESSAGES); + + assertEquals("Wrong number of messages on queue", NUM_MESSAGES, + ((AMQSession) session).getQueueDepth((AMQDestination) _queue)); + + connection.close(); + } + + // AMQConnectionListener Interface.. used so we can validate that we + // actually failed over. + + public void bytesSent(long count) + { + } + + public void bytesReceived(long count) + { + } + + public boolean preFailover(boolean redirect) + { + //Allow failover + return true; + } + + public boolean preResubscribe() + { + //Allow failover + return true; + } + + public void failoverComplete() + { + _failoverCompleted.countDown(); + } + + /** + * Override so we can block until failover has completd + * + * @param port + */ + @Override + public void failBroker(int port) + { + super.failBroker(port); + + try + { + if (!_failoverCompleted.await(DEFAULT_FAILOVER_TIME, TimeUnit.MILLISECONDS)) + { + // Use an exception so that we use our local fail() that notifies the main thread of failure + throw new Exception("Failover did not occur in specified time:" + DEFAULT_FAILOVER_TIME); + } + + } + catch (Exception e) + { + // Use an exception so that we use our local fail() that notifies the main thread of failure + fail(e); + } + } + +} diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeAfterFailoverTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeAfterFailoverTest.java new file mode 100644 index 0000000000..eb36522fac --- /dev/null +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeAfterFailoverTest.java @@ -0,0 +1,306 @@ +/* + * + * 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.test.unit.ack; + +import org.apache.qpid.client.AMQConnection; +import org.apache.qpid.client.AMQDestination; +import org.apache.qpid.client.AMQSession; +import org.apache.qpid.jms.ConnectionListener; + +import javax.jms.Connection; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageProducer; +import javax.jms.Session; +import javax.jms.TransactionRolledBackException; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +/** + * + */ +public class AcknowledgeAfterFailoverTest extends AcknowledgeTest implements ConnectionListener +{ + + protected CountDownLatch _failoverCompleted = new CountDownLatch(1); + + @Override + public void setUp() throws Exception + { + super.setUp(); + // This must be even for the test to run correctly. + // Otherwise we will kill the standby broker + // not the one we are connected to. + // The test will still pass but it will not be exactly + // as described. + NUM_MESSAGES = 6; + } + + /** + * Override default init to add connectionListener so we can verify that + * failover took place + * + * @param transacted create a transacted session for this test + * @param mode if not transacted what ack mode to use for this test + * @throws Exception if a problem occured during test setup. + */ + @Override + protected void init(boolean transacted, int mode) throws Exception + { + super.init(transacted, mode); + ((AMQConnection) _connection).setConnectionListener(this); + } + + protected void prepBroker(int count) throws Exception + { + if (count % 2 == 1) + { + failBroker(getFailingPort()); + } + else + { + failBroker(getPort()); + } + + Connection connection = getConnection(); + Session session = connection.createSession(true, Session.SESSION_TRANSACTED); + // ensure destination is created. + session.createConsumer(_queue).close(); + + sendMessage(session, _queue, count, NUM_MESSAGES - count, 0); + + if (_consumerSession.getAcknowledgeMode() != AMQSession.NO_ACKNOWLEDGE) + { + assertEquals("Wrong number of messages on queue", count, + ((AMQSession) session).getQueueDepth((AMQDestination) _queue)); + } + + connection.close(); + + try + { + if (count % 2 == 1) + { + startBroker(getFailingPort()); + } + else + { + startBroker(getPort()); + } + } + catch (Exception e) + { + fail("Unable to start failover broker," + e.getMessage()); + } + } + + @Override + public void doAcknowlegement(Message msg) throws JMSException + { + //Acknowledge current message + super.doAcknowlegement(msg); + + try + { + prepBroker(NUM_MESSAGES - msg.getIntProperty(INDEX) - 1); + } + catch (Exception e) + { + fail("Unable to prep new broker," + e.getMessage()); + } + + } + + /** + * Test that Acking/Committing a message received before failover causes + * an exception at commit/ack time. + * + * Expected behaviour is that in: + * * tx mode commit() throws a transacted RolledBackException + * * client ack mode throws an IllegalStateException + * + * @param transacted is this session trasacted + * @param mode What ack mode should be used if not trasacted + * + * @throws Exception if something goes wrong. + */ + protected void testDirtyAcking(boolean transacted, int mode) throws Exception + { + NUM_MESSAGES = 2; + //Test Dirty Failover Fails + init(transacted, mode); + + _connection.start(); + + Message msg = _consumer.receive(1500); + + int count = 0; + assertNotNull("Message " + count + " not correctly received.", msg); + assertEquals("Incorrect message received", count, msg.getIntProperty(INDEX)); + + //Don't acknowledge just prep the next broker. Without changing count + // Prep the new broker to have all all the messages so we can validate + // that they can all be correctly received. + try + { + + //Stop the connection so we can validate the number of message count + // on the queue is correct after failover + _connection.stop(); + failBroker(getFailingPort()); + + //Get the connection to the first (main port) broker. + Connection connection = getConnection();//getConnectionFactory("connection1").getConnectionURL()); + // Use a transaction to send messages so we can be sure they arrive. + Session session = connection.createSession(true, Session.SESSION_TRANSACTED); + // ensure destination is created. + session.createConsumer(_queue).close(); + + sendMessage(session, _queue, NUM_MESSAGES); + + assertEquals("Wrong number of messages on queue", NUM_MESSAGES, + ((AMQSession) session).getQueueDepth((AMQDestination) _queue)); + + connection.close(); + + //restart connection + _connection.start(); + } + catch (Exception e) + { + fail("Unable to prep new broker," + e.getMessage()); + } + + // Consume the next message - don't check what it is as a normal would + // assume it is msg 1 but as we've fallen over it is msg 0 again. + msg = _consumer.receive(1500); + + if (_consumerSession.getTransacted()) + { + try + { + _consumerSession.commit(); + fail("Session is dirty we should get an TransactionRolledBackException"); + } + catch (TransactionRolledBackException trbe) + { + //expected path + } + } + else + { + try + { + msg.acknowledge(); + fail("Session is dirty we should get an IllegalStateException"); + } + catch (javax.jms.IllegalStateException ise) + { + assertEquals("Incorrect Exception thrown", "has failed over", ise.getMessage()); + // Recover the sesion and try again. + _consumerSession.recover(); + } + } + + msg = _consumer.receive(1500); + // Validate we now get the first message back + assertEquals(0, msg.getIntProperty(INDEX)); + + msg = _consumer.receive(1500); + // and the second message + assertEquals(1, msg.getIntProperty(INDEX)); + + // And now verify that we can now commit the clean session + if (_consumerSession.getTransacted()) + { + _consumerSession.commit(); + } + else + { + msg.acknowledge(); + } + + assertEquals("Wrong number of messages on queue", 0, + ((AMQSession) _consumerSession).getQueueDepth((AMQDestination) _queue)); + } + + public void testDirtyClientAck() throws Exception + { + testDirtyAcking(false, Session.CLIENT_ACKNOWLEDGE); + } + + public void testDirtyAckingTransacted() throws Exception + { + testDirtyAcking(true, Session.SESSION_TRANSACTED); + } + + // AMQConnectionListener Interface.. used so we can validate that we + // actually failed over. + + public void bytesSent(long count) + { + } + + public void bytesReceived(long count) + { + } + + public boolean preFailover(boolean redirect) + { + //Allow failover + return true; + } + + public boolean preResubscribe() + { + //Allow failover + return true; + } + + public void failoverComplete() + { + _failoverCompleted.countDown(); + } + + /** + * Override so we can block until failover has completd + * + * @param port + */ + @Override + public void failBroker(int port) + { + super.failBroker(port); + + try + { + if (!_failoverCompleted.await(DEFAULT_FAILOVER_TIME, TimeUnit.MILLISECONDS)) + { + fail("Failover did not occur in specified time:" + DEFAULT_FAILOVER_TIME); + } + } + catch (InterruptedException e) + { + fail("Failover was interuppted"); + } + } + +} diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeOnMessageTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeOnMessageTest.java new file mode 100644 index 0000000000..4254727d36 --- /dev/null +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeOnMessageTest.java @@ -0,0 +1,170 @@ +/* + * + * 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.test.unit.ack; + +import org.apache.qpid.client.AMQDestination; +import org.apache.qpid.client.AMQSession; +import org.apache.qpid.client.JMSAMQException; +import org.apache.qpid.client.failover.FailoverException; + +import javax.jms.Message; +import javax.jms.MessageListener; +import javax.jms.Session; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; + +public class AcknowledgeOnMessageTest extends AcknowledgeTest implements MessageListener +{ + protected CountDownLatch _receviedAll; + protected AtomicReference _causeOfFailure = new AtomicReference(null); + + @Override + public void setUp() throws Exception + { + super.setUp(); + } + + @Override + public void init(boolean transacted, int mode) throws Exception + { + _receviedAll = new CountDownLatch(NUM_MESSAGES); + + super.init(transacted, mode); + _consumer.setMessageListener(this); + } + + /** + * @param transacted + * @param mode + * + * @throws Exception + */ + protected void testAcking(boolean transacted, int mode) throws Exception + { + init(transacted, mode); + + _connection.start(); + + int lastCount = (int) _receviedAll.getCount(); + + boolean complete = _receviedAll.await(5000L, TimeUnit.MILLISECONDS); + + while (!complete) + { + int currentCount = (int) _receviedAll.getCount(); + + // make sure we have received a message in the last cycle. + if (lastCount == currentCount) + { + break; + } + // Remember the currentCount as the lastCount for the next cycle. + // so we can exit if things get locked up. + lastCount = currentCount; + + complete = _receviedAll.await(5000L, TimeUnit.MILLISECONDS); + } + + if (!complete) + { + // Check to see if we ended due to an exception in the onMessage handler + Exception cause = _causeOfFailure.get(); + if (cause != null) + { + cause.printStackTrace(); + fail(cause.getMessage()); + } + else + { + fail("All messages not received missing:" + _receviedAll.getCount() + "/" + NUM_MESSAGES); + } + } + + // Check to see if we ended due to an exception in the onMessage handler + Exception cause = _causeOfFailure.get(); + if (cause != null) + { + cause.printStackTrace(); + fail(cause.getMessage()); + } + + try + { + _consumer.close(); + } + catch (JMSAMQException amqe) + { + if (amqe.getLinkedException() instanceof FailoverException) + { + fail("QPID-143 : Auto Ack can acknowledge message from previous session after failver. If failover occurs between deliver and ack."); + } + // else Rethrow for TestCase to catch. + throw amqe; + } + + _consumerSession.close(); + + assertEquals("Wrong number of messages on queue", 0, + ((AMQSession) getConnection().createSession(false, Session.AUTO_ACKNOWLEDGE)).getQueueDepth((AMQDestination) _queue)); + } + + public void onMessage(Message message) + { + try + { + int count = NUM_MESSAGES - (int) _receviedAll.getCount(); + + assertEquals("Incorrect message received", count, message.getIntProperty(INDEX)); + + count++; + if (count < NUM_MESSAGES) + { + //Send the next message + _producer.send(createNextMessage(_consumerSession, count)); + } + + doAcknowlegement(message); + + _receviedAll.countDown(); + } + catch (Exception e) + { + // This will end the test run by counting down _receviedAll + fail(e); + } + } + + /** + * Pass the given exception back to the waiting thread to fail the test run. + * + * @param e The exception that is causing the test to fail. + */ + protected void fail(Exception e) + { + _causeOfFailure.set(e); + // End the test. + while (_receviedAll.getCount() != 0) + { + _receviedAll.countDown(); + } + } +} diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeTest.java index c367a0856c..7c9a77eb53 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeTest.java @@ -1,7 +1,5 @@ -package org.apache.qpid.test.unit.ack; - /* - * + * * 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 @@ -21,133 +19,138 @@ package org.apache.qpid.test.unit.ack; * */ +package org.apache.qpid.test.unit.ack; + +import org.apache.qpid.client.AMQDestination; +import org.apache.qpid.client.AMQSession; +import org.apache.qpid.test.utils.FailoverBaseCase; + import javax.jms.Connection; import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageConsumer; -import javax.jms.MessageProducer; import javax.jms.Queue; import javax.jms.Session; +import javax.jms.MessageProducer; -import org.apache.qpid.client.AMQDestination; -import org.apache.qpid.client.AMQSession; -import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.client.message.AbstractJMSMessage; -import org.apache.qpid.test.utils.QpidTestCase; - -public class AcknowledgeTest extends QpidTestCase +public class AcknowledgeTest extends FailoverBaseCase { - protected static int NUM_MESSAGES = 100; - protected Connection _con; + protected int NUM_MESSAGES; + protected Connection _connection; protected Queue _queue; - private MessageProducer _producer; - private Session _producerSession; - private Session _consumerSession; - private MessageConsumer _consumerA; + protected Session _consumerSession; + protected MessageConsumer _consumer; + protected MessageProducer _producer; @Override protected void setUp() throws Exception { super.setUp(); - _queue = (Queue) getInitialContext().lookup("queue"); + NUM_MESSAGES = 5; + + _queue = getTestQueue(); //Create Producer put some messages on the queue - _con = getConnection(); - _con.start(); + _connection = getConnection(); } - private void init(boolean transacted, int mode) throws JMSException { - _producerSession = _con.createSession(true, Session.AUTO_ACKNOWLEDGE); - _consumerSession = _con.createSession(transacted, mode); - _producer = _producerSession.createProducer(_queue); - _consumerA = _consumerSession.createConsumer(_queue); - } + protected void init(boolean transacted, int mode) throws Exception + { + _consumerSession = _connection.createSession(transacted, mode); + _consumer = _consumerSession.createConsumer(_queue); + _producer = _consumerSession.createProducer(_queue); + + // These should all end up being prefetched by session + sendMessage(_consumerSession, _queue, 1); + + assertEquals("Wrong number of messages on queue", 1, + ((AMQSession) _consumerSession).getQueueDepth((AMQDestination) _queue)); + } /** - * Produces and consumes messages an either ack or commit the receipt of those messages - * * @param transacted * @param mode + * * @throws Exception */ - private void testMessageAck(boolean transacted, int mode) throws Exception + protected void testAcking(boolean transacted, int mode) throws Exception { - init(transacted, mode); - sendMessage(_producerSession, _queue, NUM_MESSAGES/2); - _producerSession.commit(); - MessageConsumer consumerB = _consumerSession.createConsumer(_queue); - sendMessage(_producerSession, _queue, NUM_MESSAGES/2); - _producerSession.commit(); + init(transacted, mode); + + _connection.start(); + + Message msg = _consumer.receive(1500); + int count = 0; - Message msg = consumerB.receive(1500); - while (msg != null) + while (count < NUM_MESSAGES) { - if (mode == Session.CLIENT_ACKNOWLEDGE) + assertNotNull("Message " + count + " not correctly received.", msg); + assertEquals("Incorrect message received", count, msg.getIntProperty(INDEX)); + count++; + + if (count < NUM_MESSAGES) { - msg.acknowledge(); + //Send the next message + _producer.send(createNextMessage(_consumerSession, count)); } - count++; - msg = consumerB.receive(1500); + + doAcknowlegement(msg); + + msg = _consumer.receive(1500); } - if (transacted) - { - _consumerSession.commit(); - } - _consumerA.close(); - consumerB.close(); - _consumerSession.close(); - assertEquals("Wrong number of messages on queue", NUM_MESSAGES - count, - ((AMQSession) _producerSession).getQueueDepth((AMQDestination) _queue)); - - // Clean up messages that may be left on the queue - _consumerSession = _con.createSession(transacted, mode); - _consumerA = _consumerSession.createConsumer(_queue); - msg = _consumerA.receive(1500); - while (msg != null) + + assertEquals("Wrong number of messages on queue", 0, + ((AMQSession) _consumerSession).getQueueDepth((AMQDestination) _queue)); + } + + /** + * Perform the acknowledgement of messages if additionally required. + * + * @param msg + * + * @throws JMSException + */ + protected void doAcknowlegement(Message msg) throws JMSException + { + if (_consumerSession.getTransacted()) { - if (mode == Session.CLIENT_ACKNOWLEDGE) - { - msg.acknowledge(); - } - msg = _consumerA.receive(1500); + _consumerSession.commit(); } - _consumerA.close(); - if (transacted) + + if (_consumerSession.getAcknowledgeMode() == Session.CLIENT_ACKNOWLEDGE) { - _consumerSession.commit(); + msg.acknowledge(); } - _consumerSession.close(); } - - public void test2ConsumersAutoAck() throws Exception + + public void testClientAck() throws Exception { - testMessageAck(false, Session.AUTO_ACKNOWLEDGE); + testAcking(false, Session.CLIENT_ACKNOWLEDGE); } - public void test2ConsumersClientAck() throws Exception + public void testAutoAck() throws Exception { - testMessageAck(true, Session.CLIENT_ACKNOWLEDGE); + testAcking(false, Session.AUTO_ACKNOWLEDGE); } - - public void test2ConsumersTx() throws Exception + + public void testTransacted() throws Exception { - testMessageAck(true, Session.AUTO_ACKNOWLEDGE); + testAcking(true, Session.SESSION_TRANSACTED); } - - public void testIndividualAck() throws Exception + + public void testDupsOk() throws Exception { - init(false, Session.CLIENT_ACKNOWLEDGE); - sendMessage(_producerSession, _queue, 3); - _producerSession.commit(); - Message msg = null; - for (int i = 0; i < 2; i++) - { - msg = _consumerA.receive(RECEIVE_TIMEOUT); - ((AbstractJMSMessage)msg).acknowledgeThis(); - } - msg = _consumerA.receive(RECEIVE_TIMEOUT); - msg.acknowledge(); - _con.close(); + testAcking(false, Session.DUPS_OK_ACKNOWLEDGE); } - + + public void testNoAck() throws Exception + { + testAcking(false, AMQSession.NO_ACKNOWLEDGE); + } + + public void testPreAck() throws Exception + { + testAcking(false, AMQSession.PRE_ACKNOWLEDGE); + } + } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/FailoverBeforeConsumingRecoverTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/FailoverBeforeConsumingRecoverTest.java new file mode 100644 index 0000000000..834b17430b --- /dev/null +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/FailoverBeforeConsumingRecoverTest.java @@ -0,0 +1,40 @@ +/* + * + * 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.test.unit.ack; + +import org.apache.qpid.jms.Session; + +import javax.jms.Message; +import javax.jms.Queue; + +public class FailoverBeforeConsumingRecoverTest extends RecoverTest +{ + + @Override + protected void initTest() throws Exception + { + super.initTest(); + failBroker(getFailingPort()); + + Queue queue = _consumerSession.createQueue(getTestQueueName()); + sendMessage(_connection.createSession(false, Session.AUTO_ACKNOWLEDGE), queue, SENT_COUNT); + } +} diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/QuickAcking.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/QuickAcking.java new file mode 100644 index 0000000000..6c4b7ba01b --- /dev/null +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/QuickAcking.java @@ -0,0 +1,148 @@ +/* + * + * 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.test.unit.ack; + +import edu.emory.mathcs.backport.java.util.concurrent.CountDownLatch; +import org.apache.qpid.client.AMQConnection; +import org.apache.qpid.jms.ConnectionListener; +import org.apache.qpid.test.utils.QpidTestCase; + +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Queue; +import javax.jms.Session; + +/** + * This is a quick manual test to validate acking after failover with a + * transacted session. + * + * Start an external broker then run this test. Std Err will print. + * Sent Message: 1 + * Received Message: 1 + * + * You can then restart the external broker, which will cause failover, which + * will be complete when the following appears. + * + * Failover Complete + * + * A second message send/receive cycle is then done to validate that the + * connection/session are still working. + * + */ +public class QuickAcking extends QpidTestCase implements ConnectionListener +{ + protected AMQConnection _connection; + protected Queue _queue; + protected Session _session; + protected MessageConsumer _consumer; + private CountDownLatch _failedOver; + private static final String INDEX = "INDEX"; + private int _count = 0; + + public void setUp() + { + // Prevent broker startup. Broker must be run manually. + } + + public void test() throws Exception + { + _failedOver = new CountDownLatch(1); + + _connection = new AMQConnection("amqp://guest:guest@client/test?brokerlist='localhost?retries='20'&connectdelay='2000''"); + + _session = _connection.createSession(true, Session.SESSION_TRANSACTED); + _queue = _session.createQueue("QAtest"); + _consumer = _session.createConsumer(_queue); + _connection.setConnectionListener(this); + _connection.start(); + + sendAndReceive(); + + _failedOver.await(); + + sendAndReceive(); + + } + + private void sendAndReceive() + throws Exception + { + sendMessage(); + + Message message = _consumer.receive(); + + if (message.getIntProperty(INDEX) != _count) + { + throw new Exception("Incorrect message recieved:" + _count); + } + + if (_session.getTransacted()) + { + _session.commit(); + } + System.err.println("Recevied Message:" + _count); + } + + private void sendMessage() throws JMSException + { + MessageProducer producer = _session.createProducer(_queue); + Message message = _session.createMessage(); + _count++; + message.setIntProperty(INDEX, _count); + + producer.send(message); + if (_session.getTransacted()) + { + _session.commit(); + } + producer.close(); + + System.err.println("Sent Message:" + _count); + } + + public void bytesSent(long count) + { + //To change body of implemented methods use File | Settings | File Templates. + } + + public void bytesReceived(long count) + { + //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean preFailover(boolean redirect) + { + return true; + } + + public boolean preResubscribe() + { + return true; + } + + public void failoverComplete() + { + System.err.println("Failover Complete"); + _failedOver.countDown(); + } +} diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/RecoverTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/RecoverTest.java index 7434fcbb30..4a123cb1dc 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/RecoverTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/RecoverTest.java @@ -23,8 +23,7 @@ import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.AMQQueue; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.jms.Session; -import org.apache.qpid.test.utils.QpidTestCase; - +import org.apache.qpid.test.utils.FailoverBaseCase; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -35,16 +34,21 @@ import javax.jms.MessageListener; import javax.jms.MessageProducer; import javax.jms.Queue; import javax.jms.TextMessage; - import java.util.concurrent.atomic.AtomicInteger; -public class RecoverTest extends QpidTestCase +public class RecoverTest extends FailoverBaseCase { - private static final Logger _logger = LoggerFactory.getLogger(RecoverTest.class); + static final Logger _logger = LoggerFactory.getLogger(RecoverTest.class); private Exception _error; private AtomicInteger count; + protected AMQConnection _connection; + protected Session _consumerSession; + protected MessageConsumer _consumer; + static final int SENT_COUNT = 4; + + @Override protected void setUp() throws Exception { super.setUp(); @@ -52,134 +56,110 @@ public class RecoverTest extends QpidTestCase count = new AtomicInteger(); } - protected void tearDown() throws Exception + protected void initTest() throws Exception { - super.tearDown(); - count = null; - } + _connection = (AMQConnection) getConnection("guest", "guest"); - public void testRecoverResendsMsgs() throws Exception - { - AMQConnection con = (AMQConnection) getConnection("guest", "guest"); - - Session consumerSession = con.createSession(false, Session.CLIENT_ACKNOWLEDGE); - Queue queue = - new AMQQueue(consumerSession.getDefaultQueueExchangeName(), new AMQShortString("someQ"), - new AMQShortString("someQ"), false, true); - MessageConsumer consumer = consumerSession.createConsumer(queue); - // force synch to ensure the consumer has resulted in a bound queue - // ((AMQSession) consumerSession).declareExchangeSynch(ExchangeDefaults.DIRECT_EXCHANGE_NAME, ExchangeDefaults.DIRECT_EXCHANGE_CLASS); - // This is the default now + _consumerSession = _connection.createSession(false, Session.CLIENT_ACKNOWLEDGE); + Queue queue = _consumerSession.createQueue(getTestQueueName()); - AMQConnection con2 = (AMQConnection) getConnection("guest", "guest"); - Session producerSession = con2.createSession(false, Session.CLIENT_ACKNOWLEDGE); - MessageProducer producer = producerSession.createProducer(queue); + _consumer = _consumerSession.createConsumer(queue); _logger.info("Sending four messages"); - producer.send(producerSession.createTextMessage("msg1")); - producer.send(producerSession.createTextMessage("msg2")); - producer.send(producerSession.createTextMessage("msg3")); - producer.send(producerSession.createTextMessage("msg4")); - - con2.close(); - + sendMessage(_connection.createSession(false, Session.AUTO_ACKNOWLEDGE), queue, SENT_COUNT); _logger.info("Starting connection"); - con.start(); - TextMessage tm = (TextMessage) consumer.receive(); - tm.acknowledge(); - _logger.info("Received and acknowledged first message"); - consumer.receive(); - consumer.receive(); - consumer.receive(); - _logger.info("Received all four messages. Calling recover with three outstanding messages"); - // no ack for last three messages so when I call recover I expect to get three messages back - consumerSession.recover(); - tm = (TextMessage) consumer.receive(3000); - assertEquals("msg2", tm.getText()); + _connection.start(); + } - tm = (TextMessage) consumer.receive(3000); - assertEquals("msg3", tm.getText()); + protected Message validateNextMessages(int nextCount, int startIndex) throws JMSException + { + Message message = null; + for (int index = 0; index < nextCount; index++) + { + message = _consumer.receive(3000); + assertEquals(startIndex + index, message.getIntProperty(INDEX)); + } + return message; + } - tm = (TextMessage) consumer.receive(3000); - assertEquals("msg4", tm.getText()); + protected void validateRemainingMessages(int remaining) throws JMSException + { + int index = SENT_COUNT - remaining; - _logger.info("Received redelivery of three messages. Acknowledging last message"); - tm.acknowledge(); + Message message = null; + while (index != SENT_COUNT) + { + message = _consumer.receive(3000); + assertEquals(index++, message.getIntProperty(INDEX)); + } + + if (message != null) + { + _logger.info("Received redelivery of three messages. Acknowledging last message"); + message.acknowledge(); + } _logger.info("Calling acknowledge with no outstanding messages"); // all acked so no messages to be delivered - consumerSession.recover(); + _consumerSession.recover(); - tm = (TextMessage) consumer.receiveNoWait(); - assertNull(tm); + message = _consumer.receiveNoWait(); + assertNull(message); _logger.info("No messages redelivered as is expected"); - - con.close(); } - public void testRecoverResendsMsgsAckOnEarlier() throws Exception + public void testRecoverResendsMsgs() throws Exception { - AMQConnection con = (AMQConnection) getConnection("guest", "guest"); + initTest(); - Session consumerSession = con.createSession(false, Session.CLIENT_ACKNOWLEDGE); - Queue queue = - new AMQQueue(consumerSession.getDefaultQueueExchangeName(), new AMQShortString("someQ"), - new AMQShortString("someQ"), false, true); - MessageConsumer consumer = consumerSession.createConsumer(queue); - // force synch to ensure the consumer has resulted in a bound queue - // ((AMQSession) consumerSession).declareExchangeSynch(ExchangeDefaults.DIRECT_EXCHANGE_NAME, ExchangeDefaults.DIRECT_EXCHANGE_CLASS); - // This is the default now + Message message = validateNextMessages(1, 0); + message.acknowledge(); + _logger.info("Received and acknowledged first message"); - AMQConnection con2 = (AMQConnection) getConnection("guest", "guest"); - Session producerSession = con2.createSession(false, Session.CLIENT_ACKNOWLEDGE); - MessageProducer producer = producerSession.createProducer(queue); + _consumer.receive(); + _consumer.receive(); + _consumer.receive(); + _logger.info("Received all four messages. Calling recover with three outstanding messages"); + // no ack for last three messages so when I call recover I expect to get three messages back - _logger.info("Sending four messages"); - producer.send(producerSession.createTextMessage("msg1")); - producer.send(producerSession.createTextMessage("msg2")); - producer.send(producerSession.createTextMessage("msg3")); - producer.send(producerSession.createTextMessage("msg4")); + _consumerSession.recover(); - con2.close(); + validateRemainingMessages(3); + } - _logger.info("Starting connection"); - con.start(); - TextMessage tm = (TextMessage) consumer.receive(); - consumer.receive(); - tm.acknowledge(); + public void testRecoverResendsMsgsAckOnEarlier() throws Exception + { + initTest(); + + Message message = validateNextMessages(2, 0); + message.acknowledge(); _logger.info("Received 2 messages, acknowledge() first message, should acknowledge both"); - consumer.receive(); - consumer.receive(); + _consumer.receive(); + _consumer.receive(); _logger.info("Received all four messages. Calling recover with two outstanding messages"); // no ack for last three messages so when I call recover I expect to get three messages back - consumerSession.recover(); - TextMessage tm3 = (TextMessage) consumer.receive(3000); - assertEquals("msg3", tm3.getText()); + _consumerSession.recover(); + + Message message2 = _consumer.receive(3000); + assertEquals(2, message2.getIntProperty(INDEX)); - TextMessage tm4 = (TextMessage) consumer.receive(3000); - assertEquals("msg4", tm4.getText()); + Message message3 = _consumer.receive(3000); + assertEquals(3, message3.getIntProperty(INDEX)); _logger.info("Received redelivery of two messages. calling acknolwedgeThis() first of those message"); - ((org.apache.qpid.jms.Message) tm3).acknowledgeThis(); + ((org.apache.qpid.jms.Message) message2).acknowledgeThis(); _logger.info("Calling recover"); // all acked so no messages to be delivered - consumerSession.recover(); + _consumerSession.recover(); - tm4 = (TextMessage) consumer.receive(3000); - assertEquals("msg4", tm4.getText()); - ((org.apache.qpid.jms.Message) tm4).acknowledgeThis(); + message3 = _consumer.receive(3000); + assertEquals(3, message3.getIntProperty(INDEX)); + ((org.apache.qpid.jms.Message) message3).acknowledgeThis(); - _logger.info("Calling recover"); // all acked so no messages to be delivered - consumerSession.recover(); - - tm = (TextMessage) consumer.receiveNoWait(); - assertNull(tm); - _logger.info("No messages redelivered as is expected"); - - con.close(); + validateRemainingMessages(0); } public void testAcknowledgePerConsumer() throws Exception @@ -188,11 +168,11 @@ public class RecoverTest extends QpidTestCase Session consumerSession = con.createSession(false, Session.CLIENT_ACKNOWLEDGE); Queue queue = - new AMQQueue(consumerSession.getDefaultQueueExchangeName(), new AMQShortString("Q1"), new AMQShortString("Q1"), - false, true); + new AMQQueue(consumerSession.getDefaultQueueExchangeName(), new AMQShortString("Q1"), new AMQShortString("Q1"), + false, true); Queue queue2 = - new AMQQueue(consumerSession.getDefaultQueueExchangeName(), new AMQShortString("Q2"), new AMQShortString("Q2"), - false, true); + new AMQQueue(consumerSession.getDefaultQueueExchangeName(), new AMQShortString("Q2"), new AMQShortString("Q2"), + false, true); MessageConsumer consumer = consumerSession.createConsumer(queue); MessageConsumer consumer2 = consumerSession.createConsumer(queue2); @@ -231,8 +211,8 @@ public class RecoverTest extends QpidTestCase final Session consumerSession = con.createSession(false, Session.AUTO_ACKNOWLEDGE); Queue queue = - new AMQQueue(consumerSession.getDefaultQueueExchangeName(), new AMQShortString("Q3"), new AMQShortString("Q3"), - false, true); + new AMQQueue(consumerSession.getDefaultQueueExchangeName(), new AMQShortString("Q3"), new AMQShortString("Q3"), + false, true); MessageConsumer consumer = consumerSession.createConsumer(queue); MessageProducer producer = consumerSession.createProducer(queue); producer.send(consumerSession.createTextMessage("hello")); @@ -240,50 +220,50 @@ public class RecoverTest extends QpidTestCase final Object lock = new Object(); consumer.setMessageListener(new MessageListener() - { + { - public void onMessage(Message message) + public void onMessage(Message message) + { + try { - try + count.incrementAndGet(); + if (count.get() == 1) { - count.incrementAndGet(); - if (count.get() == 1) + if (message.getJMSRedelivered()) { - if (message.getJMSRedelivered()) - { - setError( + setError( new Exception("Message marked as redilvered on what should be first delivery attempt")); - } - - consumerSession.recover(); } - else if (count.get() == 2) + + consumerSession.recover(); + } + else if (count.get() == 2) + { + if (!message.getJMSRedelivered()) { - if (!message.getJMSRedelivered()) - { - setError( + setError( new Exception( - "Message not marked as redilvered on what should be second delivery attempt")); - } - } - else - { - System.err.println(message); - fail("Message delivered too many times!: " + count); + "Message not marked as redilvered on what should be second delivery attempt")); } } - catch (JMSException e) + else { - _logger.error("Error recovering session: " + e, e); - setError(e); + System.err.println(message); + fail("Message delivered too many times!: " + count); } + } + catch (JMSException e) + { + _logger.error("Error recovering session: " + e, e); + setError(e); + } - synchronized (lock) - { - lock.notify(); - } + synchronized (lock) + { + lock.notify(); } - }); + } + }); con.start(); @@ -323,9 +303,4 @@ public class RecoverTest extends QpidTestCase { _error = e; } - - public static junit.framework.Test suite() - { - return new junit.framework.TestSuite(RecoverTest.class); - } } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/basic/SelectorTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/basic/SelectorTest.java deleted file mode 100644 index c42e4c7582..0000000000 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/basic/SelectorTest.java +++ /dev/null @@ -1,306 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.unit.basic; - -import org.apache.qpid.AMQException; -import org.apache.qpid.test.utils.QpidTestCase; -import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.client.AMQDestination; -import org.apache.qpid.client.AMQQueue; -import org.apache.qpid.client.AMQSession; -import org.apache.qpid.client.BasicMessageProducer; -import org.apache.qpid.client.state.StateWaiter; -import org.apache.qpid.url.URLSyntaxException; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.jms.Connection; -import javax.jms.DeliveryMode; -import javax.jms.InvalidSelectorException; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.MessageListener; -import java.util.concurrent.CountDownLatch; - -public class SelectorTest extends QpidTestCase implements MessageListener -{ - private static final Logger _logger = LoggerFactory.getLogger(SelectorTest.class); - - private AMQConnection _connection; - private AMQDestination _destination; - private AMQSession _session; - private int count; - public String _connectionString = "vm://:1"; - private static final String INVALID_SELECTOR = "Cost LIKE 5"; - CountDownLatch _responseLatch = new CountDownLatch(1); - - protected void setUp() throws Exception - { - super.setUp(); - init((AMQConnection) getConnection("guest", "guest")); - } - - protected void tearDown() throws Exception - { - super.tearDown(); - } - - private void init(AMQConnection connection) throws JMSException - { - init(connection, new AMQQueue(connection, randomize("SessionStartTest"), true)); - } - - private void init(AMQConnection connection, AMQDestination destination) throws JMSException - { - _connection = connection; - _destination = destination; - connection.start(); - - String selector = null; - selector = "Cost = 2 AND \"property-with-hyphen\" = 'wibble'"; - // selector = "JMSType = Special AND Cost = 2 AND AMQMessageID > 0 AND JMSDeliveryMode=" + DeliveryMode.NON_PERSISTENT; - - _session = (AMQSession) connection.createSession(false, AMQSession.NO_ACKNOWLEDGE); - // _session.createConsumer(destination).setMessageListener(this); - _session.createConsumer(destination, selector).setMessageListener(this); - } - - public void test() throws Exception - { - try - { - - init((AMQConnection) getConnection("guest", "guest", randomize("Client"))); - - Message msg = _session.createTextMessage("Message"); - msg.setJMSPriority(1); - msg.setIntProperty("Cost", 2); - msg.setStringProperty("property-with-hyphen", "wibble"); - msg.setJMSType("Special"); - - _logger.info("Sending Message:" + msg); - - ((BasicMessageProducer) _session.createProducer(_destination)).send(msg, DeliveryMode.NON_PERSISTENT); - _logger.info("Message sent, waiting for response..."); - - _responseLatch.await(); - - if (count > 0) - { - _logger.info("Got message"); - } - - if (count == 0) - { - fail("Did not get message!"); - // throw new RuntimeException("Did not get message!"); - } - } - catch (JMSException e) - { - _logger.debug("JMS:" + e.getClass().getSimpleName() + ":" + e.getMessage()); - if (!(e instanceof InvalidSelectorException)) - { - fail("Wrong exception:" + e.getMessage()); - } - else - { - System.out.println("SUCCESS!!"); - } - } - catch (InterruptedException e) - { - _logger.debug("IE :" + e.getClass().getSimpleName() + ":" + e.getMessage()); - } - catch (URLSyntaxException e) - { - _logger.debug("URL:" + e.getClass().getSimpleName() + ":" + e.getMessage()); - fail("Wrong exception"); - } - catch (AMQException e) - { - _logger.debug("AMQ:" + e.getClass().getSimpleName() + ":" + e.getMessage()); - fail("Wrong exception"); - } - - finally - { - if (_session != null) - { - _session.close(); - } - if (_connection != null) - { - _connection.close(); - } - } - } - - - public void testInvalidSelectors() throws Exception - { - Connection connection = null; - - try - { - connection = getConnection("guest", "guest", randomize("Client")); - _session = (AMQSession) connection.createSession(false, AMQSession.NO_ACKNOWLEDGE); - } - catch (JMSException e) - { - fail(e.getMessage()); - } - catch (AMQException e) - { - fail(e.getMessage()); - } - catch (URLSyntaxException e) - { - fail("Error:" + e.getMessage()); - } - - //Try Creating a Browser - try - { - _session.createBrowser(_session.createQueue("Ping"), INVALID_SELECTOR); - } - catch (JMSException e) - { - _logger.debug("JMS:" + e.getClass().getSimpleName() + ":" + e.getMessage()); - if (!(e instanceof InvalidSelectorException)) - { - fail("Wrong exception:" + e.getMessage()); - } - else - { - _logger.debug("SUCCESS!!"); - } - } - - //Try Creating a Consumer - try - { - _session.createConsumer(_session.createQueue("Ping"), INVALID_SELECTOR); - } - catch (JMSException e) - { - _logger.debug("JMS:" + e.getClass().getSimpleName() + ":" + e.getMessage()); - if (!(e instanceof InvalidSelectorException)) - { - fail("Wrong exception:" + e.getMessage()); - } - else - { - _logger.debug("SUCCESS!!"); - } - } - - //Try Creating a Receiever - try - { - _session.createReceiver(_session.createQueue("Ping"), INVALID_SELECTOR); - } - catch (JMSException e) - { - _logger.debug("JMS:" + e.getClass().getSimpleName() + ":" + e.getMessage()); - if (!(e instanceof InvalidSelectorException)) - { - fail("Wrong exception:" + e.getMessage()); - } - else - { - _logger.debug("SUCCESS!!"); - } - } - - finally - { - if (_session != null) - { - try - { - _session.close(); - } - catch (JMSException e) - { - fail("Error cleaning up:" + e.getMessage()); - } - } - if (_connection != null) - { - try - { - _connection.close(); - } - catch (JMSException e) - { - fail("Error cleaning up:" + e.getMessage()); - } - } - } - } - - public void onMessage(Message message) - { - count++; - _logger.info("Got Message:" + message); - _responseLatch.countDown(); - } - - private static String randomize(String in) - { - return in + System.currentTimeMillis(); - } - - public static void main(String[] argv) throws Exception - { - SelectorTest test = new SelectorTest(); - test._connectionString = (argv.length == 0) ? "localhost:3000" : argv[0]; - - try - { - while (true) - { - if (test._connectionString.contains("vm://:1")) - { - test.setUp(); - } - test.test(); - - if (test._connectionString.contains("vm://:1")) - { - test.tearDown(); - } - } - } - catch (Exception e) - { - System.err.println(e.getMessage()); - e.printStackTrace(); - } - } - - public static junit.framework.Test suite() - { - return new junit.framework.TestSuite(SelectorTest.class); - } -} diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/message/JMSPropertiesTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/message/JMSPropertiesTest.java index 1f90f1e29f..6b69ccab6c 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/message/JMSPropertiesTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/message/JMSPropertiesTest.java @@ -31,6 +31,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.jms.Destination; +import javax.jms.Message; import javax.jms.MessageConsumer; import javax.jms.MessageProducer; import javax.jms.ObjectMessage; @@ -105,7 +106,8 @@ public class JMSPropertiesTest extends QpidTestCase assertEquals("JMS Type mismatch", sentMsg.getJMSType(), rm.getJMSType()); assertEquals("JMS Reply To mismatch", sentMsg.getJMSReplyTo(), rm.getJMSReplyTo()); assertTrue("JMSMessageID Does not start ID:", rm.getJMSMessageID().startsWith("ID:")); - + assertEquals("JMS Default priority should be 4",Message.DEFAULT_PRIORITY,rm.getJMSPriority()); + //Validate that the JMSX values are correct assertEquals("JMSXGroupID is not as expected:", JMSXGroupID_VALUE, rm.getStringProperty("JMSXGroupID")); assertEquals("JMSXGroupSeq is not as expected:", JMSXGroupSeq_VALUE, rm.getIntProperty("JMSXGroupSeq")); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/publish/DirtyTrasactedPubilshTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/publish/DirtyTrasactedPubilshTest.java new file mode 100644 index 0000000000..248042d2c4 --- /dev/null +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/publish/DirtyTrasactedPubilshTest.java @@ -0,0 +1,403 @@ +/* + * + * 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.test.unit.publish; + +import org.apache.qpid.client.AMQConnection; +import org.apache.qpid.client.AMQDestination; +import org.apache.qpid.client.AMQSession; +import org.apache.qpid.jms.ConnectionListener; +import org.apache.qpid.test.utils.FailoverBaseCase; + +import javax.jms.Connection; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageListener; +import javax.jms.MessageProducer; +import javax.jms.Queue; +import javax.jms.Session; +import javax.jms.TransactionRolledBackException; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; + +/** + * QPID-1816 : Whilst testing Acknoledgement after failover this completes testing + * of the client after failover. When we have a dirty session we should receive + * an error if we attempt to publish. This test ensures that both in the synchronous + * and asynchronous message delivery paths we receive the expected exceptions at + * the expected time. + */ +public class DirtyTrasactedPubilshTest extends FailoverBaseCase implements ConnectionListener +{ + protected CountDownLatch _failoverCompleted = new CountDownLatch(1); + + protected int NUM_MESSAGES; + protected Connection _connection; + protected Queue _queue; + protected Session _consumerSession; + protected MessageConsumer _consumer; + protected MessageProducer _producer; + + private static final String MSG = "MSG"; + private static final String SEND_FROM_ON_MESSAGE_TEXT = "sendFromOnMessage"; + protected CountDownLatch _receviedAll; + protected AtomicReference _causeOfFailure = new AtomicReference(null); + + @Override + protected void setUp() throws Exception + { + super.setUp(); + NUM_MESSAGES = 10; + + _queue = getTestQueue(); + + //Create Producer put some messages on the queue + _connection = getConnection(); + } + + /** + * Initialise the test variables + * @param transacted is this a transacted test + * @param mode if not trasacted then what ack mode to use + * @throws Exception if there is a setup issue. + */ + protected void init(boolean transacted, int mode) throws Exception + { + _consumerSession = _connection.createSession(transacted, mode); + _consumer = _consumerSession.createConsumer(_queue); + _producer = _consumerSession.createProducer(_queue); + + // These should all end up being prefetched by session + sendMessage(_consumerSession, _queue, 1); + + assertEquals("Wrong number of messages on queue", 1, + ((AMQSession) _consumerSession).getQueueDepth((AMQDestination) _queue)); + } + + /** + * If a transacted session has failed over whilst it has uncommitted sent + * data then we need to throw a TransactedRolledbackException on commit() + * + * The alternative would be to maintain a replay buffer so that the message + * could be resent. This is not currently implemented + * + * @throws Exception if something goes wrong. + */ + public void testDirtySendingSynchronousTransacted() throws Exception + { + Session producerSession = _connection.createSession(true, Session.SESSION_TRANSACTED); + + // Ensure we get failover notifications + ((AMQConnection) _connection).setConnectionListener(this); + + MessageProducer producer = producerSession.createProducer(_queue); + + // Create and send message 0 + Message msg = producerSession.createMessage(); + msg.setIntProperty(INDEX, 0); + producer.send(msg); + + // DON'T commit message .. fail connection + + failBroker(getFailingPort()); + + // Ensure destination exists for sending + producerSession.createConsumer(_queue).close(); + + // Send the next message + msg.setIntProperty(INDEX, 1); + try + { + producer.send(msg); + fail("Should fail with Qpid as we provide early warning of the dirty session via a JMSException."); + } + catch (JMSException jmse) + { + assertEquals("Early warning of dirty session not correct", + "Failover has occurred and session is dirty so unable to send.", jmse.getMessage()); + } + + // Ignore that the session is dirty and attempt to commit to validate the + // exception is thrown. AND that the above failure notification did NOT + // clean up the session. + + try + { + producerSession.commit(); + fail("Session is dirty we should get an TransactionRolledBackException"); + } + catch (TransactionRolledBackException trbe) + { + // Normal path. + } + + // Resending of messages should now work ok as the commit was forcilbly rolledback + msg.setIntProperty(INDEX, 0); + producer.send(msg); + msg.setIntProperty(INDEX, 1); + producer.send(msg); + + producerSession.commit(); + + assertEquals("Wrong number of messages on queue", 2, + ((AMQSession) producerSession).getQueueDepth((AMQDestination) _queue)); + } + + /** + * If a transacted session has failed over whilst it has uncommitted sent + * data then we need to throw a TransactedRolledbackException on commit() + * + * The alternative would be to maintain a replay buffer so that the message + * could be resent. This is not currently implemented + * + * @throws Exception if something goes wrong. + */ + public void testDirtySendingOnMessageTransacted() throws Exception + { + NUM_MESSAGES = 1; + _receviedAll = new CountDownLatch(NUM_MESSAGES); + ((AMQConnection) _connection).setConnectionListener(this); + + init(true, Session.SESSION_TRANSACTED); + + _consumer.setMessageListener(new MessageListener() + { + + public void onMessage(Message message) + { + try + { + // Create and send message 0 + Message msg = _consumerSession.createMessage(); + msg.setIntProperty(INDEX, 0); + _producer.send(msg); + + // DON'T commit message .. fail connection + + failBroker(getFailingPort()); + + // rep + repopulateBroker(); + + // Destination will exist as this failBroker will populate + // the queue with 1 message + + // Send the next message + msg.setIntProperty(INDEX, 1); + try + { + _producer.send(msg); + fail("Should fail with Qpid as we provide early warning of the dirty session via a JMSException."); + } + catch (JMSException jmse) + { + assertEquals("Early warning of dirty session not correct", + "Failover has occurred and session is dirty so unable to send.", jmse.getMessage()); + } + + // Ignore that the session is dirty and attempt to commit to validate the + // exception is thrown. AND that the above failure notification did NOT + // clean up the session. + + try + { + _consumerSession.commit(); + fail("Session is dirty we should get an TransactionRolledBackException"); + } + catch (TransactionRolledBackException trbe) + { + // Normal path. + } + + // Resend messages + msg.setIntProperty(INDEX, 0); + msg.setStringProperty(MSG, SEND_FROM_ON_MESSAGE_TEXT); + _producer.send(msg); + msg.setIntProperty(INDEX, 1); + msg.setStringProperty(MSG, SEND_FROM_ON_MESSAGE_TEXT); + _producer.send(msg); + + _consumerSession.commit(); + + // Stop this consumer .. can't do _consumer.stop == DEADLOCK + // this doesn't seem to stop dispatcher running + _connection.stop(); + + // Signal that the onMessage send part of test is complete + // main thread can validate that messages are correct + _receviedAll.countDown(); + + } + catch (Exception e) + { + fail(e); + } + + } + + }); + + _connection.start(); + + if (!_receviedAll.await(10000L, TimeUnit.MILLISECONDS)) + { + // Check to see if we ended due to an exception in the onMessage handler + Exception cause = _causeOfFailure.get(); + if (cause != null) + { + cause.printStackTrace(); + fail(cause.getMessage()); + } + else + { + fail("All messages not received:" + _receviedAll.getCount() + "/" + NUM_MESSAGES); + } + } + + // Check to see if we ended due to an exception in the onMessage handler + Exception cause = _causeOfFailure.get(); + if (cause != null) + { + cause.printStackTrace(); + fail(cause.getMessage()); + } + + _consumer.close(); + _consumerSession.close(); + + _consumerSession = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + + _connection.start(); + + // Validate that we could send the messages as expected. + assertEquals("Wrong number of messages on queue", 3, + ((AMQSession) _consumerSession).getQueueDepth((AMQDestination) _queue)); + + MessageConsumer consumer = _consumerSession.createConsumer(_queue); + + //Validate the message sent to setup the failed over broker. + Message message = consumer.receive(1000); + assertNotNull("Message " + 0 + " not received.", message); + assertEquals("Incorrect message received", 0, message.getIntProperty(INDEX)); + + // Validate the two messages sent from within the onMessage + for (int index = 0; index <= 1; index++) + { + message = consumer.receive(1000); + assertNotNull("Message " + index + " not received.", message); + assertEquals("Incorrect message received", index, message.getIntProperty(INDEX)); + assertEquals("Incorrect message text for message:" + index, SEND_FROM_ON_MESSAGE_TEXT, message.getStringProperty(MSG)); + } + + assertNull("Extra message received.", consumer.receiveNoWait()); + + _consumerSession.close(); + + assertEquals("Wrong number of messages on queue", 0, + ((AMQSession) getConnection().createSession(false, Session.AUTO_ACKNOWLEDGE)).getQueueDepth((AMQDestination) _queue)); + } + + private void repopulateBroker() throws Exception + { + // Repopulate this new broker so we can test what happends after failover + + //Get the connection to the first (main port) broker. + Connection connection = getConnection(); + // Use a transaction to send messages so we can be sure they arrive. + Session session = connection.createSession(true, Session.SESSION_TRANSACTED); + // ensure destination is created. + session.createConsumer(_queue).close(); + + sendMessage(session, _queue, NUM_MESSAGES); + + assertEquals("Wrong number of messages on queue", NUM_MESSAGES, + ((AMQSession) session).getQueueDepth((AMQDestination) _queue)); + + connection.close(); + } + + // AMQConnectionListener Interface.. used so we can validate that we + // actually failed over. + + public void bytesSent(long count) + { + } + + public void bytesReceived(long count) + { + } + + public boolean preFailover(boolean redirect) + { + //Allow failover + return true; + } + + public boolean preResubscribe() + { + //Allow failover + return true; + } + + public void failoverComplete() + { + _failoverCompleted.countDown(); + } + + /** + * Override so we can block until failover has completd + * + * @param port int the port of the broker to fail. + */ + @Override + public void failBroker(int port) + { + super.failBroker(port); + + try + { + if (!_failoverCompleted.await(DEFAULT_FAILOVER_TIME, TimeUnit.MILLISECONDS)) + { + fail("Failover did not occur in specified time:" + DEFAULT_FAILOVER_TIME); + } + } + catch (InterruptedException e) + { + fail("Failover was interuppted"); + } + } + + /** + * Pass the given exception back to the waiting thread to fail the test run. + * + * @param e The exception that is causing the test to fail. + */ + protected void fail(Exception e) + { + _causeOfFailure.set(e); + // End the test. + while (_receviedAll.getCount() != 0) + { + _receviedAll.countDown(); + } + } +} diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/FailoverBaseCase.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/FailoverBaseCase.java index 64bd1503ba..0426c4f45f 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/FailoverBaseCase.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/FailoverBaseCase.java @@ -20,44 +20,43 @@ */ package org.apache.qpid.test.utils; -import javax.jms.Connection; -import javax.jms.JMSException; +import org.apache.qpid.util.FileUtils; + import javax.naming.NamingException; -import org.apache.qpid.util.FileUtils; +import org.apache.qpid.client.AMQConnectionFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class FailoverBaseCase extends QpidTestCase { + protected static final Logger _logger = LoggerFactory.getLogger(FailoverBaseCase.class); public static int FAILING_VM_PORT = 2; - public static int FAILING_PORT = DEFAULT_PORT + 100; + public static int FAILING_PORT = Integer.parseInt(System.getProperty("test.port.alt")); + public static final long DEFAULT_FAILOVER_TIME = 10000L; protected int failingPort; - - private boolean failedOver = false; - public FailoverBaseCase() + protected int getFailingPort() { if (_broker.equals(VM)) { - failingPort = FAILING_VM_PORT; + return FAILING_VM_PORT; } else { - failingPort = FAILING_PORT; + return FAILING_PORT; } } - - protected int getFailingPort() - { - return failingPort; - } protected void setUp() throws java.lang.Exception { super.setUp(); - setSystemProperty("QPID_WORK", System.getProperty("java.io.tmpdir")+"/"+getFailingPort()); - startBroker(failingPort); + // Set QPID_WORK to $QPID_WORK/ + // or /tmp/ if QPID_WORK not set. + setSystemProperty("QPID_WORK", System.getProperty("QPID_WORK") + "/" + getFailingPort()); + startBroker(getFailingPort()); } /** @@ -66,42 +65,52 @@ public class FailoverBaseCase extends QpidTestCase * @return a connection * @throws Exception */ - public Connection getConnection() throws JMSException, NamingException + @Override + public AMQConnectionFactory getConnectionFactory() throws NamingException { - Connection conn = - (Boolean.getBoolean("profile.use_ssl"))? - getConnectionFactory("failover.ssl").createConnection("guest", "guest"): - getConnectionFactory("failover").createConnection("guest", "guest"); - _connections.add(conn); - return conn; + _logger.info("get ConnectionFactory"); + if (_connectionFactory == null) + { + if (Boolean.getBoolean("profile.use_ssl")) + { + _connectionFactory = getConnectionFactory("failover.ssl"); + } + else + { + _connectionFactory = getConnectionFactory("failover"); + } + } + return _connectionFactory; } + public void tearDown() throws Exception { - stopBroker(_broker.equals(VM)?FAILING_PORT:FAILING_PORT); - super.tearDown(); - FileUtils.deleteDirectory(System.getProperty("java.io.tmpdir")+"/"+getFailingPort()); + try + { + super.tearDown(); + } + finally + { + // Ensure we shutdown any secondary brokers, even if we are unable + // to cleanly tearDown the QTC. + stopBroker(getFailingPort()); + FileUtils.deleteDirectory(System.getProperty("QPID_WORK") + "/" + getFailingPort()); + } } - /** - * Only used of VM borker. - */ - public void failBroker() + public void failBroker(int port) { - failedOver = true; try { - stopBroker(getFailingPort()); + stopBroker(port); } catch (Exception e) { throw new RuntimeException(e); } } - - protected void setFailingPort(int p) - { - failingPort = p; - } + + } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidTestCase.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidTestCase.java index 76e4118c96..6c1b1c7b8d 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidTestCase.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidTestCase.java @@ -22,8 +22,10 @@ import junit.framework.TestResult; import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.XMLConfiguration; import org.apache.qpid.AMQException; +import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.AMQConnectionFactory; +import org.apache.qpid.client.AMQQueue; import org.apache.qpid.client.transport.TransportConnection; import org.apache.qpid.jms.BrokerDetails; import org.apache.qpid.jms.ConnectionURL; @@ -32,6 +34,7 @@ import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.registry.ConfigurationFileApplicationRegistry; import org.apache.qpid.server.store.DerbyMessageStore; import org.apache.qpid.url.URLSyntaxException; +import org.apache.log4j.Level; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -70,13 +73,18 @@ public class QpidTestCase extends TestCase protected final String QpidHome = System.getProperty("QPID_HOME"); protected File _configFile = new File(System.getProperty("broker.config")); - private static final Logger _logger = LoggerFactory.getLogger(QpidTestCase.class); + protected static final Logger _logger = LoggerFactory.getLogger(QpidTestCase.class); protected long RECEIVE_TIMEOUT = 1000l; - private Map _setProperties = new HashMap(); + private Map _propertiesSetForTestOnly = new HashMap(); + private Map _propertiesSetForBroker = new HashMap(); + private Map _loggerLevelSetForTest = new HashMap(); + private XMLConfiguration _testConfiguration = new XMLConfiguration(); + protected static final String INDEX = "index"; + /** * 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 @@ -147,6 +155,7 @@ public class QpidTestCase extends TestCase private static final String BROKER_LANGUAGE = "broker.language"; private static final String BROKER = "broker"; private static final String BROKER_CLEAN = "broker.clean"; + private static final String BROKER_CLEAN_BETWEEN_TESTS = "broker.clean.between.tests"; private static final String BROKER_VERSION = "broker.version"; protected static final String BROKER_READY = "broker.ready"; private static final String BROKER_STOPPED = "broker.stopped"; @@ -169,6 +178,7 @@ public class QpidTestCase extends TestCase protected String _brokerLanguage = System.getProperty(BROKER_LANGUAGE, JAVA); protected String _broker = System.getProperty(BROKER, VM); 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); @@ -177,7 +187,7 @@ public class QpidTestCase extends TestCase private Map _brokers = new HashMap(); private InitialContext _initialContext; - private AMQConnectionFactory _connectionFactory; + protected AMQConnectionFactory _connectionFactory; private String _testName; @@ -235,6 +245,19 @@ public class QpidTestCase extends TestCase { _logger.error("exception stopping broker", e); } + + if(_brokerCleanBetweenTests) + { + try + { + cleanBroker(); + } + catch (Exception e) + { + _logger.error("exception cleaning up broker", e); + } + } + _logger.info("========== stop " + _testName + " =========="); if (redirected) @@ -451,6 +474,15 @@ public class QpidTestCase extends TestCase env.put("QPID_PNAME", "-DPNAME=QPBRKR -DTNAME=\"" + _testName + "\""); env.put("QPID_WORK", System.getProperty("QPID_WORK")); + + // Use the environment variable to set amqj.logging.level for the broker + // The value used is a 'server' value in the test configuration to + // allow a differentiation between the client and broker logging levels. + if (System.getProperty("amqj.server.logging.level") != null) + { + setBrokerEnvironment("AMQJ_LOGGING_LEVEL", System.getProperty("amqj.server.logging.level")); + } + // Add all the environment settings the test requested if (!_env.isEmpty()) { @@ -460,13 +492,27 @@ public class QpidTestCase extends TestCase } } + + // Add default test logging levels that are used by the log4j-test + // Use the convenience methods to push the current logging setting + // in to the external broker's QPID_OPTS string. + if (System.getProperty("amqj.protocol.logging.level") != null) + { + setSystemProperty("amqj.protocol.logging.level"); + } + if (System.getProperty("root.logging.level") != null) + { + setSystemProperty("root.logging.level"); + } + + String QPID_OPTS = " "; // Add all the specified system properties to QPID_OPTS - if (!_setProperties.isEmpty()) + if (!_propertiesSetForBroker.isEmpty()) { - for (String key : _setProperties.keySet()) + for (String key : _propertiesSetForBroker.keySet()) { - QPID_OPTS += "-D" + key + "=" + System.getProperty(key) + " "; + QPID_OPTS += "-D" + key + "=" + _propertiesSetForBroker.get(key) + " "; } if (env.containsKey("QPID_OPTS")) @@ -489,7 +535,7 @@ public class QpidTestCase extends TestCase if (!p.await(30, TimeUnit.SECONDS)) { - _logger.info("broker failed to become ready:" + p.getStopLine()); + _logger.info("broker failed to become ready (" + p.ready + "):" + p.getStopLine()); //Ensure broker has stopped process.destroy(); cleanBroker(); @@ -666,29 +712,88 @@ public class QpidTestCase extends TestCase _testConfiguration.setProperty(property, value); } + /** + * Set a System property that is to be applied only to the external test + * broker. + * + * This is a convenience method to enable the setting of a -Dproperty=value + * entry in QPID_OPTS + * + * This is only useful for the External Java Broker tests. + * + * @param property the property name + * @param value the value to set the property to + */ + protected void setBrokerOnlySystemProperty(String property, String value) + { + if (!_propertiesSetForBroker.containsKey(property)) + { + _propertiesSetForBroker.put(property, value); + } + + } + + /** + * Set a System (-D) property for this test run. + * + * This convenience method copies the current VMs System Property + * for the external VM Broker. + * + * @param property the System property to set + */ + protected void setSystemProperty(String property) + { + setSystemProperty(property, System.getProperty(property)); + } + /** * Set a System property for the duration of this test. * * When the test run is complete the value will be reverted. * + * The values set using this method will also be propogated to the external + * Java Broker via a -D value defined in QPID_OPTS. + * + * If the value should not be set on the broker then use + * setTestClientSystemProperty(). + * * @param property the property to set * @param value the new value to use */ protected void setSystemProperty(String property, String value) { - if (!_setProperties.containsKey(property)) + // Record the value for the external broker + _propertiesSetForBroker.put(property, value); + + //Set the value for the test client vm aswell. + setTestClientSystemProperty(property, value); + } + + /** + * Set a System (-D) property for the external Broker of this test. + * + * @param property The property to set + * @param value the value to set it to. + */ + protected void setTestClientSystemProperty(String property, String value) + { + if (!_propertiesSetForTestOnly.containsKey(property)) { - _setProperties.put(property, System.getProperty(property)); - } + // Record the current value so we can revert it later. + _propertiesSetForTestOnly.put(property, System.getProperty(property)); + } System.setProperty(property, value); } + /** + * Restore the System property values that were set before this test run. + */ protected void revertSystemProperties() { - for (String key : _setProperties.keySet()) + for (String key : _propertiesSetForTestOnly.keySet()) { - String value = _setProperties.get(key); + String value = _propertiesSetForTestOnly.get(key); if (value != null) { System.setProperty(key, value); @@ -698,6 +803,12 @@ public class QpidTestCase extends TestCase System.clearProperty(key); } } + + _propertiesSetForTestOnly.clear(); + + // We don't change the current VMs settings for Broker only properties + // so we can just clear this map + _propertiesSetForBroker.clear(); } /** @@ -711,6 +822,40 @@ public class QpidTestCase extends TestCase _env.put(property, value); } + /** + * Adjust the VMs Log4j Settings just for this test run + * + * @param logger the logger to change + * @param level the level to set + */ + protected void setLoggerLevel(org.apache.log4j.Logger logger, Level level) + { + assertNotNull("Cannot set level of null logger", logger); + assertNotNull("Cannot set Logger("+logger.getName()+") to null level.",level); + + if (!_loggerLevelSetForTest.containsKey(logger)) + { + // Record the current value so we can revert it later. + _loggerLevelSetForTest.put(logger, logger.getLevel()); + } + + logger.setLevel(level); + } + + /** + * Restore the logging levels defined by this test. + */ + protected void revertLoggingLevels() + { + for (org.apache.log4j.Logger logger : _loggerLevelSetForTest.keySet()) + { + logger.setLevel(_loggerLevelSetForTest.get(logger)); + } + + _loggerLevelSetForTest.clear(); + + } + /** * Check whether the broker is an 0.8 * @@ -786,7 +931,7 @@ public class QpidTestCase extends TestCase { if (Boolean.getBoolean("profile.use_ssl")) { - _connectionFactory = getConnectionFactory("ssl"); + _connectionFactory = getConnectionFactory("default.ssl"); } else { @@ -876,15 +1021,32 @@ public class QpidTestCase extends TestCase return getClass().getSimpleName() + "-" + getName(); } + /** + * Return a Queue specific for this test. + * Uses getTestQueueName() as the name of the queue + * @return + */ + public Queue getTestQueue() + { + return new AMQQueue(ExchangeDefaults.DIRECT_EXCHANGE_NAME, getTestQueueName()); + } + + protected void tearDown() throws java.lang.Exception { - // close all the connections used by this test. - for (Connection c : _connections) + try { - c.close(); + // close all the connections used by this test. + for (Connection c : _connections) + { + c.close(); + } + } + finally{ + // Ensure any problems with close does not interfer with property resets + revertSystemProperties(); + revertLoggingLevels(); } - - revertSystemProperties(); } /** @@ -921,17 +1083,23 @@ public class QpidTestCase extends TestCase public List sendMessage(Session session, Destination destination, int count) throws Exception { - return sendMessage(session, destination, count, 0); + return sendMessage(session, destination, count, 0, 0); } public List sendMessage(Session session, Destination destination, int count, int batchSize) throws Exception + { + return sendMessage(session, destination, count, 0, batchSize); + } + + public List sendMessage(Session session, Destination destination, + int count, int offset, int batchSize) throws Exception { List messages = new ArrayList(count); MessageProducer producer = session.createProducer(destination); - for (int i = 0; i < count; i++) + for (int i = offset; i < (count + offset); i++) { Message next = createNextMessage(session, i); @@ -950,8 +1118,11 @@ public class QpidTestCase extends TestCase } // Ensure we commit the last messages - if (session.getTransacted() && (batchSize > 0) && - (count / batchSize != 0)) + // Commit the session if we are transacted and + // we have no batchSize or + // our count is not divible by batchSize. + if (session.getTransacted() && + ( batchSize == 0 || count % batchSize != 0)) { session.commit(); } @@ -961,7 +1132,11 @@ public class QpidTestCase extends TestCase public Message createNextMessage(Session session, int msgCount) throws JMSException { - return session.createMessage(); + Message message = session.createMessage(); + message.setIntProperty(INDEX, msgCount); + + return message; + } public ConnectionURL getConnectionURL() throws NamingException diff --git a/qpid/java/test-profiles/010Excludes b/qpid/java/test-profiles/010Excludes old mode 100644 new mode 100755 index f03d62667d..757a1e425c --- a/qpid/java/test-profiles/010Excludes +++ b/qpid/java/test-profiles/010Excludes @@ -92,3 +92,12 @@ org.apache.qpid.test.unit.close.JavaServerCloseRaceConditionTest#* // QPID-2084 : this test needs more work for 0-10 org.apache.qpid.test.unit.client.DynamicQueueExchangeCreateTest#* + +// QPID-2118 : 0-10 Java client has differrent error handling to 0-8 code path +org.apache.qpid.test.client.message.SelectorTest#testRuntimeSelectorError + +//QPID-942 : Implemented Channel.Flow based Producer Side flow control to the Java Broker (not in CPP Broker) +org.apache.qpid.server.queue.ProducerFlowControlTest#* + +//QPID-1950 : Commit to test this failure. This is a MINA only failure so it cannot be tested when using 010. +org.apache.qpid.server.failover.MessageDisappearWithIOExceptionTest#* diff --git a/qpid/java/test-profiles/08Excludes b/qpid/java/test-profiles/08Excludes index b277c6d929..6f3898384d 100644 --- a/qpid/java/test-profiles/08Excludes +++ b/qpid/java/test-profiles/08Excludes @@ -14,8 +14,6 @@ org.apache.qpid.server.persistent.NoLocalAfterRecoveryTest#* // QPID-1823: this takes ages to run org.apache.qpid.client.SessionCreateTest#* -org.apache.qpid.test.client.RollbackOrderTest#* - // QPID-2097 exclude it from the InVM test runs until InVM JMX Interface is reliable org.apache.qpid.management.jmx.ManagementActorLoggingTest#* org.apache.qpid.server.queue.ModelTest#* diff --git a/qpid/java/test-profiles/08StandaloneExcludes b/qpid/java/test-profiles/08StandaloneExcludes index de876e06bb..ee781fb80f 100644 --- a/qpid/java/test-profiles/08StandaloneExcludes +++ b/qpid/java/test-profiles/08StandaloneExcludes @@ -39,8 +39,6 @@ org.apache.qpid.server.persistent.NoLocalAfterRecoveryTest#* // QPID-1823: this takes ages to run org.apache.qpid.client.SessionCreateTest#* -org.apache.qpid.test.client.RollbackOrderTest#* - // This test requires the standard configuration file for validation. // Excluding here does not reduce test coverage. org.apache.qpid.server.configuration.ServerConfigurationFileTest#* diff --git a/qpid/java/test-profiles/Excludes b/qpid/java/test-profiles/Excludes index a72d3bc86c..aa60554c04 100644 --- a/qpid/java/test-profiles/Excludes +++ b/qpid/java/test-profiles/Excludes @@ -19,3 +19,15 @@ org.apache.qpid.server.logging.DerbyMessageStoreLoggingTest#* // QPID-2081 :The configuration changes are now highlighting the close race condition org.apache.qpid.server.security.acl.SimpleACLTest#* + +// QPID-1816 : Client Ack has not been addressed +org.apache.qpid.test.unit.ack.AcknowledgeAfterFailoverOnMessageTest#testDirtyClientAck +org.apache.qpid.test.unit.ack.AcknowledgeAfterFailoverOnMessageTest#testClientAck +org.apache.qpid.test.unit.ack.AcknowledgeAfterFailoverTest#testDirtyClientAck +org.apache.qpid.test.unit.ack.AcknowledgeAfterFailoverTest#testClientAck + + +// QPID-143 : Failover can occur between receive and ack but we don't stop the ack. +org.apache.qpid.test.unit.ack.AcknowledgeAfterFailoverOnMessageTest#testAutoAck +org.apache.qpid.test.unit.ack.AcknowledgeAfterFailoverOnMessageTest#testDupsOk + diff --git a/qpid/java/test-profiles/default.testprofile b/qpid/java/test-profiles/default.testprofile index 86a5b2efb3..28127e5c4c 100644 --- a/qpid/java/test-profiles/default.testprofile +++ b/qpid/java/test-profiles/default.testprofile @@ -11,11 +11,14 @@ max_prefetch=1000 log=debug amqj.logging.level=${log} +amqj.server.logging.level=${log} amqj.protocol.logging.level=${log} root.logging.level=warn log4j.configuration=file:///${test.profiles}/log4j-test.xml log4j.debug=false +# Note test-provider.properties also has variables of same name. +# Keep in sync test.port=15672 test.mport=18999 #Note : Management will start open second port on: mport + 100 : 19099 diff --git a/qpid/java/test-profiles/log4j-test.xml b/qpid/java/test-profiles/log4j-test.xml index 0aaa7d8686..2d77942a81 100644 --- a/qpid/java/test-profiles/log4j-test.xml +++ b/qpid/java/test-profiles/log4j-test.xml @@ -29,10 +29,10 @@ + - @@ -46,6 +46,10 @@ + + + + diff --git a/qpid/java/test-profiles/test-provider.properties b/qpid/java/test-profiles/test-provider.properties index e5cb18da0b..8cea012c1d 100644 --- a/qpid/java/test-profiles/test-provider.properties +++ b/qpid/java/test-profiles/test-provider.properties @@ -19,20 +19,23 @@ # # -test.port=5672 -test.port.ssl=5671 -test.port.alt=5772 -test.port.alt.ssl=5771 +# Copied from default.testprofile +test.port=15672 +test.mport=18999 +#Note : Java Management will start open second port on: mport + 100 : 19099 +test.port.ssl=15671 +test.port.alt=25672 +test.port.alt.ssl=25671 + connectionfactory.default = amqp://username:password@clientid/test?brokerlist='tcp://localhost:${test.port}' +connectionfactory.default.ssl = amqp://username:password@clientid/test?brokerlist='tcp://localhost:${test.port.ssl}?ssl='true'' connectionfactory.default.vm = amqp://username:password@clientid/test?brokerlist='vm://:1' -connectionfactory.ssl = amqp://username:password@clientid/test?brokerlist='tcp://localhost:${test.port.ssl}?ssl='true'' connectionfactory.failover = amqp://username:password@clientid/test?brokerlist='tcp://localhost:${test.port.alt};tcp://localhost:${test.port}'&sync_ack='true'&sync_publish='all'&failover='roundrobin?cyclecount='20'' - connectionfactory.failover.ssl = amqp://username:password@clientid/test?brokerlist='tcp://localhost:${test.port.alt.ssl}?ssl='true';tcp://localhost:${test.port.ssl}?ssl='true''&sync_ack='true'&sync_publish='all'&failover='roundrobin?cyclecount='20'' +connectionfactory.failover.vm = amqp://username:password@clientid/test?brokerlist='vm://:2;vm://:1'&failover='roundrobin?cyclecount='20'' -connectionfactory.failover.vm = amqp://username:password@clientid/test?brokerlist='vm://:2;vm://:1' connectionfactory.connection1 = amqp://username:password@clientid/test?brokerlist='tcp://localhost:${test.port}' connectionfactory.connection2 = amqp://username:password@clientid/test?brokerlist='tcp://localhost:${test.port.alt}' connectionfactory.connection1.vm = amqp://username:password@clientid/test?brokerlist='vm://:1' -- cgit v1.2.1 From dffa942a2be4c0721e6ebce2c7a9203f4c83a41b Mon Sep 17 00:00:00 2001 From: Aidan Skinner Date: Wed, 14 Oct 2009 21:26:25 +0000 Subject: Merge from trunk git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/java-network-refactor@825292 13f79535-47bb-0310-9956-ffa450edef68 --- qpid/java/common.xml | 3 + qpid/java/module.xml | 6 +- .../MessageDisappearWithIOExceptionTest.java | 23 ++- .../qpid/server/security/acl/SimpleACLTest.java | 171 +++++++++++++++++++++ .../ack/AcknowledgeAfterFailoverOnMessageTest.java | 6 +- .../unit/ack/AcknowledgeAfterFailoverTest.java | 2 +- .../test/unit/ack/AcknowledgeOnMessageTest.java | 33 ++-- qpid/java/test-profiles/010Excludes | 3 - qpid/java/test-profiles/08StandaloneExcludes | 1 - qpid/java/test-profiles/Excludes | 3 - 10 files changed, 221 insertions(+), 30 deletions(-) (limited to 'qpid/java') diff --git a/qpid/java/common.xml b/qpid/java/common.xml index 3393be7070..6b9c961b35 100644 --- a/qpid/java/common.xml +++ b/qpid/java/common.xml @@ -51,6 +51,9 @@ + + + diff --git a/qpid/java/module.xml b/qpid/java/module.xml index 5796af928a..9fcc8ded4d 100644 --- a/qpid/java/module.xml +++ b/qpid/java/module.xml @@ -287,9 +287,9 @@ - - - + + + diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/failover/MessageDisappearWithIOExceptionTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/failover/MessageDisappearWithIOExceptionTest.java index f1a1c1a9a8..e507ebc534 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/server/failover/MessageDisappearWithIOExceptionTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/failover/MessageDisappearWithIOExceptionTest.java @@ -179,9 +179,16 @@ public class MessageDisappearWithIOExceptionTest extends FailoverBaseCase implem messages.remove(0).getIntProperty("count"), received.getIntProperty("count")); - // Allow ack to be sent to broker, by performing a synchronous command - // along the session. -// _session.createConsumer(_session.createTemporaryQueue()).close(); + // When the Exception is received by the underlying IO layer it will + // initiate failover. The first step of which is to ensure that the + // existing conection is closed. So in this situation the connection + // will be flushed casuing the above ACK to be sent to the broker. + // + // That said: + // when the socket close is detected on the server it will rise up the + // Mina filter chain and interrupt processing. + // this has been raised as QPID-2138 + _session.createConsumer(_session.createTemporaryQueue()).close(); //Retain IO Layer AMQProtocolSession protocolSession = _connection.getProtocolHandler().getProtocolSession(); @@ -260,8 +267,14 @@ public class MessageDisappearWithIOExceptionTest extends FailoverBaseCase implem private void initialiseConnection() throws Exception { - //Create Connection - _connection = (AMQConnection) getConnection(); + //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()); + // 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, + // this would add additional complexity in the logging as a second + // broker is defined in that url. We do not need it for this test. + _connection.getFailoverPolicy().getCurrentMethod().setRetries(1); _connection.setConnectionListener(this); _session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/SimpleACLTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/SimpleACLTest.java index 3e5470d5cb..7a7d7f646e 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/SimpleACLTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/SimpleACLTest.java @@ -147,10 +147,23 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E 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("guest", "guest"); + conn.setExceptionListener(new ExceptionListener() + { + public void onException(JMSException e) + { + exceptionReceived.countDown(); + } + }); + + Session sesh = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); conn.start(); @@ -166,6 +179,11 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E 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)); } } @@ -195,6 +213,10 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E { 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"); @@ -202,6 +224,14 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E //Prevent Failover ((AMQConnection) conn).setConnectionListener(this); + conn.setExceptionListener(new ExceptionListener() + { + public void onException(JMSException e) + { + exceptionReceived.countDown(); + } + }); + Session sesh = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); conn.start(); @@ -217,6 +247,11 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E 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)); } } @@ -248,6 +283,10 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E { 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"); @@ -256,6 +295,14 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E 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); @@ -266,6 +313,11 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, 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)); } } @@ -334,11 +386,23 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E { 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(); + } + }); Session session = conn.createSession(true, Session.AUTO_ACKNOWLEDGE); @@ -370,6 +434,11 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E foundCorrectException = true; } } + + //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)); } assertTrue("Did not get AMQAuthenticationException thrown", foundCorrectException); } @@ -400,10 +469,22 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E { 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(); + } + }); + Session sesh = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); conn.start(); @@ -420,6 +501,11 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E 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)); } } @@ -427,10 +513,22 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E { 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(); + } + }); + Session sesh = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); conn.start(); @@ -446,6 +544,11 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E 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)); } } @@ -487,10 +590,22 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E { 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(); + } + }); + Session sesh = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); conn.start(); @@ -504,6 +619,11 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E catch (AMQAuthenticationException amqe) { 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)); } } @@ -511,10 +631,22 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E { 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(); + } + }); + Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); conn.start(); @@ -531,6 +663,11 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E 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)); } } @@ -538,11 +675,23 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E { 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(); + } + }); + Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); connection.start(); @@ -556,6 +705,11 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E catch (AMQAuthenticationException amqe) { 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)); } } @@ -653,9 +807,21 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E { 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(); + } + }); ((AMQConnection) conn).setConnectionListener(this); @@ -699,6 +865,11 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener, E 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)); } } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeAfterFailoverOnMessageTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeAfterFailoverOnMessageTest.java index f22a405fc3..7c5db290c4 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeAfterFailoverOnMessageTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeAfterFailoverOnMessageTest.java @@ -155,7 +155,7 @@ public class AcknowledgeAfterFailoverOnMessageTest extends AcknowledgeOnMessageT public void onMessage(Message message) { // Stop processing if we have an error and had to stop running. - if (_receviedAll.getCount() == 0) + if (_receivedAll.getCount() == 0) { _logger.debug("Dumping msgs due to error(" + _causeOfFailure.get().getMessage() + "):" + message); return; @@ -191,7 +191,7 @@ public class AcknowledgeAfterFailoverOnMessageTest extends AcknowledgeOnMessageT // Acknowledge the first message if we are now on the cleaned pass if (cleaned) { - _receviedAll.countDown(); + _receivedAll.countDown(); } return; @@ -234,7 +234,7 @@ public class AcknowledgeAfterFailoverOnMessageTest extends AcknowledgeOnMessageT // this will then trigger test teardown. if (cleaned) { - _receviedAll.countDown(); + _receivedAll.countDown(); } //Reset message count so we can try again. diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeAfterFailoverTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeAfterFailoverTest.java index eb36522fac..ae7e30c231 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeAfterFailoverTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeAfterFailoverTest.java @@ -299,7 +299,7 @@ public class AcknowledgeAfterFailoverTest extends AcknowledgeTest implements Con } catch (InterruptedException e) { - fail("Failover was interuppted"); + fail("Failover was interrupted"); } } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeOnMessageTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeOnMessageTest.java index 4254727d36..a2703be298 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeOnMessageTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeOnMessageTest.java @@ -34,7 +34,7 @@ import java.util.concurrent.atomic.AtomicReference; public class AcknowledgeOnMessageTest extends AcknowledgeTest implements MessageListener { - protected CountDownLatch _receviedAll; + protected CountDownLatch _receivedAll; protected AtomicReference _causeOfFailure = new AtomicReference(null); @Override @@ -46,7 +46,7 @@ public class AcknowledgeOnMessageTest extends AcknowledgeTest implements Message @Override public void init(boolean transacted, int mode) throws Exception { - _receviedAll = new CountDownLatch(NUM_MESSAGES); + _receivedAll = new CountDownLatch(NUM_MESSAGES); super.init(transacted, mode); _consumer.setMessageListener(this); @@ -64,26 +64,36 @@ public class AcknowledgeOnMessageTest extends AcknowledgeTest implements Message _connection.start(); - int lastCount = (int) _receviedAll.getCount(); + // Set the lastCount to NUM_MESSAGES, this ensures that the compare + // against the receviedAll count is accurate. + int lastCount = NUM_MESSAGES; - boolean complete = _receviedAll.await(5000L, TimeUnit.MILLISECONDS); + // Wait for messages to arrive + boolean complete = _receivedAll.await(5000L, TimeUnit.MILLISECONDS); + // If the messasges haven't arrived while (!complete) { - int currentCount = (int) _receviedAll.getCount(); + // Check how many we have received + int currentCount = (int) _receivedAll.getCount(); // make sure we have received a message in the last cycle. if (lastCount == currentCount) { + // If we didn't receive any messages then stop. + // Something must have gone wrong. + System.err.println("Giving up waiting as we didn't receive anything."); break; } // Remember the currentCount as the lastCount for the next cycle. // so we can exit if things get locked up. lastCount = currentCount; - complete = _receviedAll.await(5000L, TimeUnit.MILLISECONDS); + // Wait again for messages to arrive. + complete = _receivedAll.await(5000L, TimeUnit.MILLISECONDS); } + // If we failed to receive all the messages then fail the test. if (!complete) { // Check to see if we ended due to an exception in the onMessage handler @@ -95,10 +105,11 @@ public class AcknowledgeOnMessageTest extends AcknowledgeTest implements Message } else { - fail("All messages not received missing:" + _receviedAll.getCount() + "/" + NUM_MESSAGES); + fail("All messages not received missing:" + _receivedAll.getCount() + "/" + NUM_MESSAGES); } } + // Even if we received all the messages. // Check to see if we ended due to an exception in the onMessage handler Exception cause = _causeOfFailure.get(); if (cause != null) @@ -131,7 +142,7 @@ public class AcknowledgeOnMessageTest extends AcknowledgeTest implements Message { try { - int count = NUM_MESSAGES - (int) _receviedAll.getCount(); + int count = NUM_MESSAGES - (int) _receivedAll.getCount(); assertEquals("Incorrect message received", count, message.getIntProperty(INDEX)); @@ -144,7 +155,7 @@ public class AcknowledgeOnMessageTest extends AcknowledgeTest implements Message doAcknowlegement(message); - _receviedAll.countDown(); + _receivedAll.countDown(); } catch (Exception e) { @@ -162,9 +173,9 @@ public class AcknowledgeOnMessageTest extends AcknowledgeTest implements Message { _causeOfFailure.set(e); // End the test. - while (_receviedAll.getCount() != 0) + while (_receivedAll.getCount() != 0) { - _receviedAll.countDown(); + _receivedAll.countDown(); } } } diff --git a/qpid/java/test-profiles/010Excludes b/qpid/java/test-profiles/010Excludes index 757a1e425c..454aede07e 100755 --- a/qpid/java/test-profiles/010Excludes +++ b/qpid/java/test-profiles/010Excludes @@ -75,9 +75,6 @@ org.apache.qpid.server.AlertingTest#* // The C++ server has a totally different persistence mechanism org.apache.qpid.server.store.PersistentStoreTest#* -// QPID-1225 : Temporary remove this test until the problem has been addressed -org.apache.qpid.server.security.acl.SimpleACLTest#testClientPublishInvalidQueueSuccess - // CPP Broker does not follow the same Logging convention as the Java broker org.apache.qpid.server.logging.* diff --git a/qpid/java/test-profiles/08StandaloneExcludes b/qpid/java/test-profiles/08StandaloneExcludes index ee781fb80f..ed12973498 100644 --- a/qpid/java/test-profiles/08StandaloneExcludes +++ b/qpid/java/test-profiles/08StandaloneExcludes @@ -23,7 +23,6 @@ org.apache.qpid.test.client.failover.FailoverTest#* // InVM Broker tests awaiting resolution of QPID-1103 org.apache.qpid.test.client.timeouts.SyncWaitDelayTest#* org.apache.qpid.test.client.timeouts.SyncWaitTimeoutDelayTest#* -org.apache.qpid.server.security.acl.SimpleACLTest#* // Those tests are written against the 0.10 path org.apache.qpid.test.unit.message.UTF8Test#* diff --git a/qpid/java/test-profiles/Excludes b/qpid/java/test-profiles/Excludes index aa60554c04..c9c9e91836 100644 --- a/qpid/java/test-profiles/Excludes +++ b/qpid/java/test-profiles/Excludes @@ -17,9 +17,6 @@ org.apache.qpid.server.logging.MemoryMessageStoreLoggingTest#testMessageStoreClo // QPID-XXX : Test fails to start external broker due to Derby Exception. org.apache.qpid.server.logging.DerbyMessageStoreLoggingTest#* -// QPID-2081 :The configuration changes are now highlighting the close race condition -org.apache.qpid.server.security.acl.SimpleACLTest#* - // QPID-1816 : Client Ack has not been addressed org.apache.qpid.test.unit.ack.AcknowledgeAfterFailoverOnMessageTest#testDirtyClientAck org.apache.qpid.test.unit.ack.AcknowledgeAfterFailoverOnMessageTest#testClientAck -- cgit v1.2.1 From 7900c45fcecdb5e2c3154621cc01a734c5f660b5 Mon Sep 17 00:00:00 2001 From: Keith Wall Date: Fri, 5 Dec 2014 13:06:31 +0000 Subject: NO-JIRA: Remove exclusion related to QPID-3605. Looks like this was fixed long ago. git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1643264 13f79535-47bb-0310-9956-ffa450edef68 --- qpid/java/test-profiles/JavaExcludes | 3 --- 1 file changed, 3 deletions(-) (limited to 'qpid/java') diff --git a/qpid/java/test-profiles/JavaExcludes b/qpid/java/test-profiles/JavaExcludes index 618dfd8586..cafb1d573a 100644 --- a/qpid/java/test-profiles/JavaExcludes +++ b/qpid/java/test-profiles/JavaExcludes @@ -24,8 +24,5 @@ org.apache.qpid.client.SessionCreateTest#* org.apache.qpid.test.client.queue.QueuePolicyTest#testRingPolicy org.apache.qpid.test.client.queue.QueuePolicyTest#testRejectPolicy -//QPID-3605 Durable subscriber with no-local true receives messages on re-connection -org.apache.qpid.test.unit.topic.DurableSubscriptionTest#testNoLocalMessagesNotDeliveredAfterReconnection - //QPID-4153 Messages causing a runtime selector error should be dead-lettered (or something similar) org.apache.qpid.test.client.message.SelectorTest#testRuntimeSelectorError -- cgit v1.2.1 From 29ae1eaabfa2d46c3f0728d6b3f9477661f9abd4 Mon Sep 17 00:00:00 2001 From: Robert Godfrey Date: Sat, 6 Dec 2014 22:13:57 +0000 Subject: QPID-6263 : [Java Broker] remove ApplicationRegistry git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1643619 13f79535-47bb-0310-9956-ffa450edef68 --- .../main/java/org/apache/qpid/server/Broker.java | 101 ++++++++++++--- .../qpid/server/registry/ApplicationRegistry.java | 135 --------------------- .../qpid/server/registry/IApplicationRegistry.java | 38 ------ 3 files changed, 81 insertions(+), 193 deletions(-) delete mode 100644 qpid/java/broker-core/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java delete mode 100644 qpid/java/broker-core/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java (limited to 'qpid/java') diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java index 245edc0970..a5a84b019d 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java @@ -33,33 +33,45 @@ import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import org.apache.log4j.PropertyConfigurator; +import org.apache.qpid.common.QpidProperties; +import org.apache.qpid.server.configuration.BrokerProperties; import org.apache.qpid.server.configuration.updater.TaskExecutor; import org.apache.qpid.server.configuration.updater.TaskExecutorImpl; +import org.apache.qpid.server.logging.CompositeStartupMessageLogger; import org.apache.qpid.server.logging.EventLogger; +import org.apache.qpid.server.logging.Log4jMessageLogger; import org.apache.qpid.server.logging.LogRecorder; +import org.apache.qpid.server.logging.MessageLogger; import org.apache.qpid.server.logging.SystemOutMessageLogger; import org.apache.qpid.server.logging.log4j.LoggingManagementFacade; import org.apache.qpid.server.logging.messages.BrokerMessages; import org.apache.qpid.server.model.BrokerShutdownProvider; +import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.SystemConfig; import org.apache.qpid.server.plugin.PluggableFactoryLoader; import org.apache.qpid.server.plugin.SystemConfigFactory; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.registry.IApplicationRegistry; import org.apache.qpid.server.security.SecurityManager; +import org.apache.qpid.server.store.BrokerStoreUpgraderAndRecoverer; import org.apache.qpid.server.store.DurableConfigurationStore; +import org.apache.qpid.util.SystemUtils; public class Broker implements BrokerShutdownProvider { private static final Logger LOGGER = Logger.getLogger(Broker.class); private volatile Thread _shutdownHookThread; - private volatile IApplicationRegistry _applicationRegistry; private EventLogger _eventLogger; private boolean _configuringOwnLogging = false; private final TaskExecutor _taskExecutor = new TaskExecutorImpl(); private final boolean _exitJVMOnShutdownWithNonZeroExitCode; + private SystemConfig _systemConfig; + + private org.apache.qpid.server.model.Broker _broker; + + private DurableConfigurationStore _store; + + public Broker() { this(false); @@ -96,10 +108,22 @@ public class Broker implements BrokerShutdownProvider { try { - if (_applicationRegistry != null) + try + { + if (_broker != null) + { + _broker.close(); + } + } + finally { - _applicationRegistry.close(); + if(_systemConfig != null) + { + _systemConfig.close(); + } } + _store = null; + _broker = null; _taskExecutor.stop(); } @@ -169,21 +193,67 @@ public class Broker implements BrokerShutdownProvider LogRecorder logRecorder = new LogRecorder(); _taskExecutor.start(); - SystemConfig systemConfig = configFactory.newInstance(_taskExecutor, _eventLogger, logRecorder, options, this); - systemConfig.open(); - DurableConfigurationStore store = systemConfig.getConfigurationStore(); + _systemConfig = configFactory.newInstance(_taskExecutor, _eventLogger, logRecorder, options, this); + _systemConfig.open(); + _store = _systemConfig.getConfigurationStore(); - _applicationRegistry = new ApplicationRegistry(store, systemConfig); try { - _applicationRegistry.initialise(options); + // Create the RootLogger to be used during broker operation + boolean statusUpdatesEnabled = Boolean.parseBoolean(System.getProperty(BrokerProperties.PROPERTY_STATUS_UPDATES, "true")); + MessageLogger messageLogger = new Log4jMessageLogger(statusUpdatesEnabled); + final EventLogger eventLogger = _systemConfig.getEventLogger(); + eventLogger.setMessageLogger(messageLogger); + + //Create the composite (log4j+SystemOut MessageLogger to be used during startup + MessageLogger[] messageLoggers = {new SystemOutMessageLogger(), messageLogger}; + + CompositeStartupMessageLogger startupMessageLogger = new CompositeStartupMessageLogger(messageLoggers); + EventLogger startupLogger = new EventLogger(startupMessageLogger); + + startupLogger.message(BrokerMessages.STARTUP(QpidProperties.getReleaseVersion(), + QpidProperties.getBuildVersion())); + + startupLogger.message(BrokerMessages.PLATFORM(System.getProperty("java.vendor"), + System.getProperty("java.runtime.version", + System.getProperty("java.version")), + SystemUtils.getOSName(), + SystemUtils.getOSVersion(), + SystemUtils.getOSArch())); + + startupLogger.message(BrokerMessages.MAX_MEMORY(Runtime.getRuntime().maxMemory())); + + BrokerStoreUpgraderAndRecoverer upgrader = new BrokerStoreUpgraderAndRecoverer(_systemConfig); + org.apache.qpid.server.model.Broker broker = upgrader.perform(_store); + _broker = broker; + + broker.setEventLogger(startupLogger); + broker.open(); + + if (broker.getState() == State.ACTIVE) + { + startupLogger.message(BrokerMessages.READY()); + broker.setEventLogger(eventLogger); + } } catch(Exception e) { LOGGER.fatal("Exception during startup", e); try { - _applicationRegistry.close(); + try + { + if (_broker != null) + { + _broker.close(); + } + } + finally + { + _systemConfig.close(); + } + _store = null; + _broker = null; } catch(Exception ce) { @@ -297,15 +367,6 @@ public class Broker implements BrokerShutdownProvider } } - public org.apache.qpid.server.model.Broker getBroker() - { - if (_applicationRegistry == null) - { - return null; - } - return _applicationRegistry.getBroker(); - } - private class ShutdownService implements Runnable { public void run() diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java deleted file mode 100644 index d32f0299d5..0000000000 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.registry; - -import org.apache.log4j.Logger; - -import org.apache.qpid.common.QpidProperties; -import org.apache.qpid.server.BrokerOptions; -import org.apache.qpid.server.configuration.BrokerProperties; -import org.apache.qpid.server.logging.CompositeStartupMessageLogger; -import org.apache.qpid.server.logging.EventLogger; -import org.apache.qpid.server.logging.Log4jMessageLogger; -import org.apache.qpid.server.logging.MessageLogger; -import org.apache.qpid.server.logging.SystemOutMessageLogger; -import org.apache.qpid.server.logging.messages.BrokerMessages; -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.model.State; -import org.apache.qpid.server.model.SystemConfig; -import org.apache.qpid.server.store.BrokerStoreUpgraderAndRecoverer; -import org.apache.qpid.server.store.DurableConfigurationStore; -import org.apache.qpid.util.SystemUtils; - - -/** - * An abstract application registry that provides access to configuration information and handles the - * construction and caching of configurable objects. - *

- * Subclasses should handle the construction of the "registered objects" such as the exchange registry. - */ -public class ApplicationRegistry implements IApplicationRegistry -{ - private static final Logger _logger = Logger.getLogger(ApplicationRegistry.class); - - private final SystemConfig _systemConfig; - - private Broker _broker; - - private DurableConfigurationStore _store; - - public ApplicationRegistry(DurableConfigurationStore store, SystemConfig systemConfig) - { - _store = store; - _systemConfig = systemConfig; - } - - public void initialise(BrokerOptions brokerOptions) throws Exception - { - // Create the RootLogger to be used during broker operation - boolean statusUpdatesEnabled = Boolean.parseBoolean(System.getProperty(BrokerProperties.PROPERTY_STATUS_UPDATES, "true")); - MessageLogger messageLogger = new Log4jMessageLogger(statusUpdatesEnabled); - final EventLogger eventLogger = _systemConfig.getEventLogger(); - eventLogger.setMessageLogger(messageLogger); - - //Create the composite (log4j+SystemOut MessageLogger to be used during startup - MessageLogger[] messageLoggers = {new SystemOutMessageLogger(), messageLogger}; - - CompositeStartupMessageLogger startupMessageLogger = new CompositeStartupMessageLogger(messageLoggers); - EventLogger startupLogger = new EventLogger(startupMessageLogger); - - logStartupMessages(startupLogger); - - BrokerStoreUpgraderAndRecoverer upgrader = new BrokerStoreUpgraderAndRecoverer(_systemConfig); - Broker broker = upgrader.perform(_store); - _broker = broker; - - broker.setEventLogger(startupLogger); - broker.open(); - - if (broker.getState() == State.ACTIVE) - { - startupLogger.message(BrokerMessages.READY()); - broker.setEventLogger(eventLogger); - } - } - - public void close() - { - if (_logger.isInfoEnabled()) - { - _logger.info("Shutting down ApplicationRegistry:" + this); - } - try - { - if (_broker != null) - { - _broker.close(); - } - } - finally - { - _systemConfig.close(); - } - _store = null; - _broker = null; - } - - - private void logStartupMessages(EventLogger eventLogger) - { - eventLogger.message(BrokerMessages.STARTUP(QpidProperties.getReleaseVersion(), QpidProperties.getBuildVersion())); - - eventLogger.message(BrokerMessages.PLATFORM(System.getProperty("java.vendor"), - System.getProperty("java.runtime.version", System.getProperty("java.version")), - SystemUtils.getOSName(), - SystemUtils.getOSVersion(), - SystemUtils.getOSArch())); - - eventLogger.message(BrokerMessages.MAX_MEMORY(Runtime.getRuntime().maxMemory())); - } - - @Override - public Broker getBroker() - { - return _broker; - } - -} diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java deleted file mode 100644 index fb588875a6..0000000000 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.registry; - -import org.apache.qpid.server.BrokerOptions; -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.stats.StatisticsGatherer; - -public interface IApplicationRegistry -{ - - void initialise(BrokerOptions brokerOptions) throws Exception; - - /** - * Shutdown this Registry - */ - void close(); - - Broker getBroker(); -} -- cgit v1.2.1 From db07194fdec1c2c27d9de2fdc881e5d8e7b3ead9 Mon Sep 17 00:00:00 2001 From: Robert Godfrey Date: Sun, 7 Dec 2014 10:54:59 +0000 Subject: QPID-6263 : [Java Broker] Remove knowledge of BrokerOptions from SystemConfig and simply use attributes instead git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1643660 13f79535-47bb-0310-9956-ffa450edef68 --- .../store/berkeleydb/BDBSystemConfigImpl.java | 7 +- .../server/model/SystemConfigFactoryGenerator.java | 7 +- .../main/java/org/apache/qpid/server/Broker.java | 2 +- .../java/org/apache/qpid/server/BrokerOptions.java | 12 +++- .../store/ManagementModeStoreHandler.java | 24 +++---- .../qpid/server/model/AbstractSystemConfig.java | 83 ++++++++++++++++++---- .../qpid/server/model/JsonSystemConfigImpl.java | 7 +- .../org/apache/qpid/server/model/SystemConfig.java | 35 ++++++++- .../qpid/server/model/adapter/BrokerAdapter.java | 19 +++-- .../qpid/server/plugin/SystemConfigFactory.java | 5 +- .../store/ManagementModeStoreHandlerTest.java | 50 ++++++++----- .../qpid/server/store/BrokerRecovererTest.java | 2 +- .../store/BrokerStoreUpgraderAndRecovererTest.java | 2 +- .../server/store/derby/DerbySystemConfigImpl.java | 7 +- .../server/store/jdbc/JDBCSystemConfigImpl.java | 7 +- .../qpid/server/store/MemorySystemConfigImpl.java | 7 +- .../qpid/test/utils/TestBrokerConfiguration.java | 4 +- 17 files changed, 197 insertions(+), 83 deletions(-) (limited to 'qpid/java') diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBSystemConfigImpl.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBSystemConfigImpl.java index 5d65d6e16d..90bb4b74ee 100644 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBSystemConfigImpl.java +++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBSystemConfigImpl.java @@ -20,7 +20,8 @@ */ package org.apache.qpid.server.store.berkeleydb; -import org.apache.qpid.server.BrokerOptions; +import java.util.Map; + import org.apache.qpid.server.configuration.updater.TaskExecutor; import org.apache.qpid.server.logging.EventLogger; import org.apache.qpid.server.logging.LogRecorder; @@ -49,10 +50,10 @@ public class BDBSystemConfigImpl extends AbstractSystemConfig attributes, final BrokerShutdownProvider brokerShutdownProvider) { - super(taskExecutor, eventLogger, logRecorder, brokerOptions, brokerShutdownProvider); + super(taskExecutor, eventLogger, logRecorder, attributes, brokerShutdownProvider); } @Override diff --git a/qpid/java/broker-codegen/src/main/java/org/apache/qpid/server/model/SystemConfigFactoryGenerator.java b/qpid/java/broker-codegen/src/main/java/org/apache/qpid/server/model/SystemConfigFactoryGenerator.java index 317e0f7c74..52c1276d49 100644 --- a/qpid/java/broker-codegen/src/main/java/org/apache/qpid/server/model/SystemConfigFactoryGenerator.java +++ b/qpid/java/broker-codegen/src/main/java/org/apache/qpid/server/model/SystemConfigFactoryGenerator.java @@ -113,7 +113,8 @@ public class SystemConfigFactoryGenerator extends AbstractProcessor pw.println(";"); pw.println(); - pw.println("import org.apache.qpid.server.BrokerOptions;"); + pw.println("import java.util.Map;"); + pw.println(); pw.println("import org.apache.qpid.server.configuration.updater.TaskExecutor;"); pw.println("import org.apache.qpid.server.logging.EventLogger;"); pw.println("import org.apache.qpid.server.logging.LogRecorder;"); @@ -140,10 +141,10 @@ public class SystemConfigFactoryGenerator extends AbstractProcessor pw.println(" public "+objectSimpleName+" newInstance(final TaskExecutor taskExecutor,"); pw.println(" final EventLogger eventLogger,"); pw.println(" final LogRecorder logRecorder,"); - pw.println(" final BrokerOptions brokerOptions,"); + pw.println(" final Map attributes,"); pw.println(" final BrokerShutdownProvider brokerShutdownProvider)"); pw.println(" {"); - pw.println(" return new "+objectSimpleName+"(taskExecutor, eventLogger, logRecorder, brokerOptions, brokerShutdownProvider);"); + pw.println(" return new "+objectSimpleName+"(taskExecutor, eventLogger, logRecorder, attributes, brokerShutdownProvider);"); pw.println(" }"); pw.println("}"); diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java index a5a84b019d..3b899e3dd3 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java @@ -193,7 +193,7 @@ public class Broker implements BrokerShutdownProvider LogRecorder logRecorder = new LogRecorder(); _taskExecutor.start(); - _systemConfig = configFactory.newInstance(_taskExecutor, _eventLogger, logRecorder, options, this); + _systemConfig = configFactory.newInstance(_taskExecutor, _eventLogger, logRecorder, options.convertToSystemConfigAttributes(), this); _systemConfig.open(); _store = _systemConfig.getConfigurationStore(); diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/BrokerOptions.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/BrokerOptions.java index 9b3f290723..ebb113d43b 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/BrokerOptions.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/BrokerOptions.java @@ -29,6 +29,7 @@ import java.util.concurrent.ConcurrentMap; import org.apache.qpid.server.configuration.BrokerProperties; import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.SystemConfig; import org.apache.qpid.server.util.StringUtil; public class BrokerOptions @@ -80,12 +81,21 @@ public class BrokerOptions private Map _configProperties = new HashMap(); private String _initialSystemProperties; - public Map convertToSystemAttributes() + public Map convertToSystemConfigAttributes() { Map attributes = new HashMap(); attributes.put("storePath", getConfigurationStoreLocation()); attributes.put(ConfiguredObject.CONTEXT, getConfigProperties()); + + attributes.put(SystemConfig.MANAGEMENT_MODE, _managementMode); + attributes.put(SystemConfig.MANAGEMENT_MODE_QUIESCE_VIRTUAL_HOSTS, _managementModeQuiesceVhosts); + attributes.put(SystemConfig.MANAGEMENT_MODE_RMI_PORT_OVERRIDE, _managementModeRmiPortOverride); + attributes.put(SystemConfig.MANAGEMENT_MODE_JMX_PORT_OVERRIDE, _managementModeJmxPortOverride); + attributes.put(SystemConfig.MANAGEMENT_MODE_HTTP_PORT_OVERRIDE, _managementModeHttpPortOverride); + attributes.put(SystemConfig.MANAGEMENT_MODE_PASSWORD, _managementModePassword); + attributes.put(SystemConfig.INITIAL_CONFIGURATION_LOCATION, getInitialConfigurationLocation()); + return attributes; } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandler.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandler.java index 4032ae2f39..bf45268a5e 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandler.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandler.java @@ -30,7 +30,6 @@ import java.util.UUID; import org.apache.log4j.Logger; -import org.apache.qpid.server.BrokerOptions; import org.apache.qpid.server.configuration.IllegalConfigurationException; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.ConfiguredObject; @@ -40,6 +39,7 @@ import org.apache.qpid.server.model.Model; import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.Protocol; import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.SystemConfig; import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.model.adapter.BrokerAdapter; import org.apache.qpid.server.store.ConfiguredObjectRecord; @@ -62,14 +62,14 @@ public class ManagementModeStoreHandler implements DurableConfigurationStore private final DurableConfigurationStore _store; private Map _cliEntries; private Map _quiescedEntriesOriginalState; - private final BrokerOptions _options; + private final SystemConfig _systemConfig; private ConfiguredObject _parent; private HashMap _records; public ManagementModeStoreHandler(DurableConfigurationStore store, - BrokerOptions options) + SystemConfig systemConfig) { - _options = options; + _systemConfig = systemConfig; _store = store; } @@ -82,16 +82,16 @@ public class ManagementModeStoreHandler implements DurableConfigurationStore _parent = parent; _store.openConfigurationStore(parent, overwrite, initialRecords); - _quiescedEntriesOriginalState = quiesceEntries(_options); + _quiescedEntriesOriginalState = quiesceEntries(_systemConfig); _records = new HashMap(); final ConfiguredObjectRecordHandler localRecoveryHandler = new ConfiguredObjectRecordHandler() { private int _version; - private boolean _quiesceRmiPort = _options.getManagementModeRmiPortOverride() > 0; - private boolean _quiesceJmxPort = _options.getManagementModeJmxPortOverride() > 0; - private boolean _quiesceHttpPort = _options.getManagementModeHttpPortOverride() > 0; + private boolean _quiesceRmiPort = _systemConfig.getManagementModeRmiPortOverride() > 0; + private boolean _quiesceJmxPort = _systemConfig.getManagementModeJmxPortOverride() > 0; + private boolean _quiesceHttpPort = _systemConfig.getManagementModeHttpPortOverride() > 0; @Override public void begin() @@ -104,7 +104,7 @@ public class ManagementModeStoreHandler implements DurableConfigurationStore String entryType = object.getType(); Map attributes = object.getAttributes(); boolean quiesce = false; - if (VIRTUAL_HOST_TYPE.equals(entryType) && _options.isManagementModeQuiesceVirtualHosts()) + if (VIRTUAL_HOST_TYPE.equals(entryType) && _systemConfig.isManagementModeQuiesceVirtualHosts()) { quiesce = true; } @@ -174,7 +174,7 @@ public class ManagementModeStoreHandler implements DurableConfigurationStore _store.visitConfiguredObjectRecords(localRecoveryHandler); - _cliEntries = createPortsFromCommandLineOptions(_options); + _cliEntries = createPortsFromCommandLineOptions(_systemConfig); for(ConfiguredObjectRecord entry : _cliEntries.values()) { @@ -293,7 +293,7 @@ public class ManagementModeStoreHandler implements DurableConfigurationStore } } - private Map createPortsFromCommandLineOptions(BrokerOptions options) + private Map createPortsFromCommandLineOptions(SystemConfig options) { int managementModeRmiPortOverride = options.getManagementModeRmiPortOverride(); if (managementModeRmiPortOverride < 0) @@ -369,7 +369,7 @@ public class ManagementModeStoreHandler implements DurableConfigurationStore } - private Map quiesceEntries(final BrokerOptions options) + private Map quiesceEntries(final SystemConfig options) { final Map quiescedEntries = new HashMap(); final int managementModeRmiPortOverride = options.getManagementModeRmiPortOverride(); diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractSystemConfig.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractSystemConfig.java index f8dac7cbe9..5dfb178f15 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractSystemConfig.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractSystemConfig.java @@ -31,7 +31,6 @@ import java.util.HashMap; import java.util.Map; import java.util.UUID; -import org.apache.qpid.server.BrokerOptions; import org.apache.qpid.server.configuration.IllegalConfigurationException; import org.apache.qpid.server.configuration.store.ManagementModeStoreHandler; import org.apache.qpid.server.configuration.updater.TaskExecutor; @@ -48,24 +47,44 @@ public abstract class AbstractSystemConfig> private static final UUID SYSTEM_ID = new UUID(0l, 0l); private final EventLogger _eventLogger; private final LogRecorder _logRecorder; - private final BrokerOptions _brokerOptions; private final BrokerShutdownProvider _brokerShutdownProvider; private DurableConfigurationStore _configurationStore; + @ManagedAttributeField + private boolean _managementMode; + + @ManagedAttributeField + private int _managementModeRmiPortOverride; + + @ManagedAttributeField + private int _managementModeJmxPortOverride; + + @ManagedAttributeField + private int _managementModeHttpPortOverride; + + @ManagedAttributeField + private boolean _managementModeQuiesceVirtualHosts; + + @ManagedAttributeField + private String _managementModePassword; + + @ManagedAttributeField + private String _initialConfigurationLocation; + + public AbstractSystemConfig(final TaskExecutor taskExecutor, final EventLogger eventLogger, final LogRecorder logRecorder, - final BrokerOptions brokerOptions, + final Map attributes, final BrokerShutdownProvider brokerShutdownProvider) { super(parentsMap(), - updateAttributes(brokerOptions.convertToSystemAttributes()), + updateAttributes(attributes), taskExecutor, BrokerModel.getInstance()); _eventLogger = eventLogger; getTaskExecutor().start(); _logRecorder = logRecorder; - _brokerOptions = brokerOptions; _brokerShutdownProvider = brokerShutdownProvider; } @@ -100,12 +119,6 @@ public abstract class AbstractSystemConfig> return _logRecorder; } - @Override - public BrokerOptions getBrokerOptions() - { - return _brokerOptions; - } - @Override protected void onClose() { @@ -155,16 +168,16 @@ public abstract class AbstractSystemConfig> super.onOpen(); _configurationStore = createStoreObject(); - if (_brokerOptions.isManagementMode()) + if (isManagementMode()) { - _configurationStore = new ManagementModeStoreHandler(_configurationStore, _brokerOptions); + _configurationStore = new ManagementModeStoreHandler(_configurationStore, this); } try { _configurationStore.openConfigurationStore(this, false, - convertToConfigurationRecords(_brokerOptions.getInitialConfigurationLocation(), + convertToConfigurationRecords(getInitialConfigurationLocation(), this)); _configurationStore.upgradeStoreStructure(); } @@ -215,6 +228,48 @@ public abstract class AbstractSystemConfig> } + @Override + public boolean isManagementMode() + { + return _managementMode; + } + + @Override + public int getManagementModeRmiPortOverride() + { + return _managementModeRmiPortOverride; + } + + @Override + public int getManagementModeJmxPortOverride() + { + return _managementModeJmxPortOverride; + } + + @Override + public int getManagementModeHttpPortOverride() + { + return _managementModeHttpPortOverride; + } + + @Override + public boolean isManagementModeQuiesceVirtualHosts() + { + return _managementModeQuiesceVirtualHosts; + } + + @Override + public String getManagementModePassword() + { + return _managementModePassword; + } + + @Override + public String getInitialConfigurationLocation() + { + return _initialConfigurationLocation; + } + @Override public BrokerShutdownProvider getBrokerShutdownProvider() { diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/JsonSystemConfigImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/JsonSystemConfigImpl.java index c9a828e7e4..440c7e341c 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/JsonSystemConfigImpl.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/JsonSystemConfigImpl.java @@ -20,7 +20,8 @@ */ package org.apache.qpid.server.model; -import org.apache.qpid.server.BrokerOptions; +import java.util.Map; + import org.apache.qpid.server.configuration.updater.TaskExecutor; import org.apache.qpid.server.logging.EventLogger; import org.apache.qpid.server.logging.LogRecorder; @@ -38,10 +39,10 @@ public class JsonSystemConfigImpl extends AbstractSystemConfig attributes, final BrokerShutdownProvider brokerShutdownProvider) { - super(taskExecutor, eventLogger, logRecorder, brokerOptions, brokerShutdownProvider); + super(taskExecutor, eventLogger, logRecorder, attributes, brokerShutdownProvider); } public String getStorePath() diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/SystemConfig.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/SystemConfig.java index ec063142b4..c985541a53 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/SystemConfig.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/SystemConfig.java @@ -20,7 +20,6 @@ */ package org.apache.qpid.server.model; -import org.apache.qpid.server.BrokerOptions; import org.apache.qpid.server.logging.EventLogger; import org.apache.qpid.server.logging.LogRecorder; import org.apache.qpid.server.store.DurableConfigurationStore; @@ -28,9 +27,38 @@ import org.apache.qpid.server.store.DurableConfigurationStore; @ManagedObject (creatable = false) public interface SystemConfig> extends ConfiguredObject { - EventLogger getEventLogger(); + String MANAGEMENT_MODE = "managementMode"; + + String MANAGEMENT_MODE_QUIESCE_VIRTUAL_HOSTS = "managementModeQuiesceVirtualHosts"; + String MANAGEMENT_MODE_RMI_PORT_OVERRIDE = "managementModeRmiPortOverride"; + String MANAGEMENT_MODE_JMX_PORT_OVERRIDE = "managementModeJmxPortOverride"; + String MANAGEMENT_MODE_HTTP_PORT_OVERRIDE = "managementModeHttpPortOverride"; + String MANAGEMENT_MODE_PASSWORD = "managementModePassword"; + String INITIAL_CONFIGURATION_LOCATION = "initialConfigurationLocation"; + + @ManagedAttribute(defaultValue = "false") + boolean isManagementMode(); + + @ManagedAttribute(defaultValue = "0") + int getManagementModeRmiPortOverride(); + + @ManagedAttribute(defaultValue = "0") + int getManagementModeJmxPortOverride(); + + @ManagedAttribute(defaultValue = "0") + int getManagementModeHttpPortOverride(); + + @ManagedAttribute(defaultValue = "false") + boolean isManagementModeQuiesceVirtualHosts(); - BrokerOptions getBrokerOptions(); + @ManagedAttribute(secure = true) + String getManagementModePassword(); + + @ManagedAttribute + String getInitialConfigurationLocation(); + + + EventLogger getEventLogger(); Broker getBroker(); @@ -39,4 +67,5 @@ public interface SystemConfig> extends ConfiguredObjec DurableConfigurationStore getConfigurationStore(); BrokerShutdownProvider getBrokerShutdownProvider(); + } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java index 313fd509e2..13182cb93e 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java @@ -71,13 +71,13 @@ public class BrokerAdapter extends AbstractConfiguredObject imple CONNECTION_HEART_BEAT_DELAY, STATISTICS_REPORTING_PERIOD }; + private SystemConfig _parent; private EventLogger _eventLogger; private final LogRecorder _logRecorder; private final SecurityManager _securityManager; private AuthenticationProvider _managementModeAuthenticationProvider; - private BrokerOptions _brokerOptions; private Timer _reportingTimer; private final StatisticsCounter _messagesDelivered, _dataDelivered, _messagesReceived, _dataReceived; @@ -108,18 +108,17 @@ public class BrokerAdapter extends AbstractConfiguredObject imple SystemConfig parent) { super(parentsMap(parent), attributes); - + _parent = parent; _logRecorder = parent.getLogRecorder(); _eventLogger = parent.getEventLogger(); - _brokerOptions = parent.getBrokerOptions(); - _securityManager = new SecurityManager(this, _brokerOptions.isManagementMode()); - if (_brokerOptions.isManagementMode()) + _securityManager = new SecurityManager(this, parent.isManagementMode()); + if (parent.isManagementMode()) { Map authManagerAttrs = new HashMap(); authManagerAttrs.put(NAME,"MANAGEMENT_MODE_AUTHENTICATION"); authManagerAttrs.put(ID, UUID.randomUUID()); SimpleAuthenticationManager authManager = new SimpleAuthenticationManager(authManagerAttrs, this); - authManager.addUser(BrokerOptions.MANAGEMENT_MODE_USER_NAME, _brokerOptions.getManagementModePassword()); + authManager.addUser(BrokerOptions.MANAGEMENT_MODE_USER_NAME, _parent.getManagementModePassword()); _managementModeAuthenticationProvider = authManager; } _messagesDelivered = new StatisticsCounter("messages-delivered"); @@ -230,7 +229,7 @@ public class BrokerAdapter extends AbstractConfiguredObject imple @StateTransition( currentState = State.UNINITIALIZED, desiredState = State.ACTIVE ) private void activate() { - if(_brokerOptions.isManagementMode()) + if(_parent.isManagementMode()) { _managementModeAuthenticationProvider.open(); } @@ -263,7 +262,7 @@ public class BrokerAdapter extends AbstractConfiguredObject imple } final boolean brokerShutdownOnErroredChild = getContextValue(Boolean.class, BROKER_FAIL_STARTUP_WITH_ERRORED_CHILD); - if (!_brokerOptions.isManagementMode() && brokerShutdownOnErroredChild && hasBrokerAnyErroredChildren) + if (!_parent.isManagementMode() && brokerShutdownOnErroredChild && hasBrokerAnyErroredChildren) { throw new IllegalStateException(String.format("Broker context variable %s is set and the broker has %s children", BROKER_FAIL_STARTUP_WITH_ERRORED_CHILD, State.ERRORED)); @@ -274,7 +273,7 @@ public class BrokerAdapter extends AbstractConfiguredObject imple if (isManagementMode()) { _eventLogger.message(BrokerMessages.MANAGEMENT_MODE(BrokerOptions.MANAGEMENT_MODE_USER_NAME, - _brokerOptions.getManagementModePassword())); + _parent.getManagementModePassword())); } setState(State.ACTIVE); } @@ -939,7 +938,7 @@ public class BrokerAdapter extends AbstractConfiguredObject imple @Override public boolean isManagementMode() { - return _brokerOptions.isManagementMode(); + return _parent.isManagementMode(); } @Override diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/SystemConfigFactory.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/SystemConfigFactory.java index 885194d939..6d4098afea 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/SystemConfigFactory.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/SystemConfigFactory.java @@ -20,7 +20,8 @@ */ package org.apache.qpid.server.plugin; -import org.apache.qpid.server.BrokerOptions; +import java.util.Map; + import org.apache.qpid.server.configuration.updater.TaskExecutor; import org.apache.qpid.server.logging.EventLogger; import org.apache.qpid.server.logging.LogRecorder; @@ -32,6 +33,6 @@ public interface SystemConfigFactory> extends Pluggabl public X newInstance(final TaskExecutor taskExecutor, final EventLogger eventLogger, final LogRecorder logRecorder, - final BrokerOptions brokerOptions, + final Map options, final BrokerShutdownProvider brokerShutdownProvider); } diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandlerTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandlerTest.java index fbb08cdd2a..57672dc4f7 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandlerTest.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandlerTest.java @@ -34,7 +34,6 @@ import java.util.HashSet; import java.util.Map; import java.util.UUID; -import org.apache.qpid.server.model.BrokerShutdownProvider; import org.mockito.ArgumentCaptor; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; @@ -46,6 +45,7 @@ import org.apache.qpid.server.configuration.updater.TaskExecutor; import org.apache.qpid.server.logging.EventLogger; import org.apache.qpid.server.logging.LogRecorder; import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.BrokerShutdownProvider; import org.apache.qpid.server.model.JsonSystemConfigImpl; import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.Protocol; @@ -79,7 +79,7 @@ public class ManagementModeStoreHandlerTest extends QpidTestCase _taskExecutor.start(); _systemConfig = new JsonSystemConfigImpl(_taskExecutor, mock(EventLogger.class), - mock(LogRecorder.class), new BrokerOptions(), + mock(LogRecorder.class), new BrokerOptions().convertToSystemConfigAttributes(), mock(BrokerShutdownProvider.class)); @@ -111,15 +111,29 @@ public class ManagementModeStoreHandlerTest extends QpidTestCase } ).when(_store).visitConfiguredObjectRecords(recovererArgumentCaptor.capture()); _options = new BrokerOptions(); - _handler = new ManagementModeStoreHandler(_store, _options); + + _handler = new ManagementModeStoreHandler(_store, _systemConfig);; _handler.openConfigurationStore(_systemConfig, false); } + private ManagementModeStoreHandler createManagementModeStoreHandler() + { + _systemConfig.close(); + _systemConfig = new JsonSystemConfigImpl(_taskExecutor, + mock(EventLogger.class), + mock(LogRecorder.class), + _options.convertToSystemConfigAttributes(), + mock(BrokerShutdownProvider.class)); + _systemConfig.open(); + return new ManagementModeStoreHandler(_store, _systemConfig); + } + @Override public void tearDown() throws Exception { _taskExecutor.stop(); + _systemConfig.close(); super.tearDown(); } @@ -154,7 +168,7 @@ public class ManagementModeStoreHandlerTest extends QpidTestCase public void testGetRootEntryWithHttpPortOverriden() { _options.setManagementModeHttpPortOverride(9090); - _handler = new ManagementModeStoreHandler(_store, _options); + _handler = createManagementModeStoreHandler(); _handler.openConfigurationStore(_systemConfig, false); ConfiguredObjectRecord root = getRootEntry(); assertEquals("Unexpected root id", _rootId, root.getId()); @@ -166,7 +180,7 @@ public class ManagementModeStoreHandlerTest extends QpidTestCase public void testGetRootEntryWithRmiPortOverriden() { _options.setManagementModeRmiPortOverride(9090); - _handler = new ManagementModeStoreHandler(_store, _options); + _handler = createManagementModeStoreHandler(); _handler.openConfigurationStore(_systemConfig, false); ConfiguredObjectRecord root = getRootEntry(); @@ -179,7 +193,7 @@ public class ManagementModeStoreHandlerTest extends QpidTestCase public void testGetRootEntryWithConnectorPortOverriden() { _options.setManagementModeJmxPortOverride(9090); - _handler = new ManagementModeStoreHandler(_store, _options); + _handler = createManagementModeStoreHandler(); _handler.openConfigurationStore(_systemConfig, false); ConfiguredObjectRecord root = getRootEntry(); @@ -194,7 +208,7 @@ public class ManagementModeStoreHandlerTest extends QpidTestCase _options.setManagementModeHttpPortOverride(1000); _options.setManagementModeRmiPortOverride(2000); _options.setManagementModeJmxPortOverride(3000); - _handler = new ManagementModeStoreHandler(_store, _options); + _handler = createManagementModeStoreHandler(); _handler.openConfigurationStore(_systemConfig, false); ConfiguredObjectRecord root = getRootEntry(); @@ -222,7 +236,7 @@ public class ManagementModeStoreHandlerTest extends QpidTestCase public void testGetEntryByCLIConnectorPortId() { _options.setManagementModeJmxPortOverride(9090); - _handler = new ManagementModeStoreHandler(_store, _options); + _handler = createManagementModeStoreHandler(); _handler.openConfigurationStore(_systemConfig, false); @@ -234,7 +248,7 @@ public class ManagementModeStoreHandlerTest extends QpidTestCase public void testGetEntryByCLIHttpPortId() { _options.setManagementModeHttpPortOverride(9090); - _handler = new ManagementModeStoreHandler(_store, _options); + _handler = createManagementModeStoreHandler(); _handler.openConfigurationStore(_systemConfig, false); @@ -249,7 +263,7 @@ public class ManagementModeStoreHandlerTest extends QpidTestCase attributes.put(Port.PROTOCOLS, Collections.singleton(Protocol.HTTP)); when(_portEntry.getAttributes()).thenReturn(attributes); _options.setManagementModeHttpPortOverride(9090); - _handler = new ManagementModeStoreHandler(_store, _options); + _handler = createManagementModeStoreHandler(); _handler.openConfigurationStore(_systemConfig, false); @@ -263,7 +277,7 @@ public class ManagementModeStoreHandlerTest extends QpidTestCase attributes.put(Port.PROTOCOLS, Collections.singleton(Protocol.RMI)); when(_portEntry.getAttributes()).thenReturn(attributes); _options.setManagementModeRmiPortOverride(9090); - _handler = new ManagementModeStoreHandler(_store, _options); + _handler = createManagementModeStoreHandler(); _handler.openConfigurationStore(_systemConfig, false); @@ -277,7 +291,7 @@ public class ManagementModeStoreHandlerTest extends QpidTestCase attributes.put(Port.PROTOCOLS, Collections.singleton(Protocol.JMX_RMI)); when(_portEntry.getAttributes()).thenReturn(attributes); _options.setManagementModeRmiPortOverride(9090); - _handler = new ManagementModeStoreHandler(_store, _options); + _handler = createManagementModeStoreHandler(); _handler.openConfigurationStore(_systemConfig, false); @@ -328,7 +342,7 @@ public class ManagementModeStoreHandlerTest extends QpidTestCase _options.setManagementModeQuiesceVirtualHosts(mmQuiesceVhosts); } - _handler = new ManagementModeStoreHandler(_store, _options); + _handler = createManagementModeStoreHandler(); _handler.openConfigurationStore(_systemConfig, false); ConfiguredObjectRecord hostEntry = getEntry(virtualHostId); @@ -354,7 +368,7 @@ public class ManagementModeStoreHandlerTest extends QpidTestCase _options.setManagementModeHttpPortOverride(1000); _options.setManagementModeRmiPortOverride(2000); _options.setManagementModeJmxPortOverride(3000); - _handler = new ManagementModeStoreHandler(_store, _options); + _handler = createManagementModeStoreHandler(); _handler.openConfigurationStore(_systemConfig, false); Map attributes = new HashMap(); @@ -371,7 +385,7 @@ public class ManagementModeStoreHandlerTest extends QpidTestCase _options.setManagementModeHttpPortOverride(1000); _options.setManagementModeRmiPortOverride(2000); _options.setManagementModeJmxPortOverride(3000); - _handler = new ManagementModeStoreHandler(_store, _options); + _handler = createManagementModeStoreHandler(); _handler.openConfigurationStore(_systemConfig, false); ConfiguredObjectRecord root = getRootEntry(); @@ -386,7 +400,7 @@ public class ManagementModeStoreHandlerTest extends QpidTestCase public void testSaveCLIHttpPort() { _options.setManagementModeHttpPortOverride(1000); - _handler = new ManagementModeStoreHandler(_store, _options); + _handler = createManagementModeStoreHandler(); _handler.openConfigurationStore(_systemConfig, false); UUID portId = getOptionsPortId(); @@ -410,7 +424,7 @@ public class ManagementModeStoreHandlerTest extends QpidTestCase public void testRemove() { _options.setManagementModeHttpPortOverride(1000); - _handler = new ManagementModeStoreHandler(_store, _options); + _handler = createManagementModeStoreHandler(); _handler.openConfigurationStore(_systemConfig, false); ConfiguredObjectRecord record = new ConfiguredObjectRecord() @@ -446,7 +460,7 @@ public class ManagementModeStoreHandlerTest extends QpidTestCase public void testRemoveCLIPort() { _options.setManagementModeHttpPortOverride(1000); - _handler = new ManagementModeStoreHandler(_store, _options); + _handler = createManagementModeStoreHandler(); _handler.openConfigurationStore(_systemConfig, false); UUID portId = getOptionsPortId(); diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/BrokerRecovererTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/BrokerRecovererTest.java index f4802481cb..07139881c1 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/BrokerRecovererTest.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/BrokerRecovererTest.java @@ -69,7 +69,7 @@ public class BrokerRecovererTest extends TestCase _brokerShutdownProvider = mock(BrokerShutdownProvider.class); _systemConfig = new JsonSystemConfigImpl(_taskExecutor, mock(EventLogger.class), mock(LogRecorder.class), - new BrokerOptions(), + new BrokerOptions().convertToSystemConfigAttributes(), _brokerShutdownProvider); when(_brokerEntry.getId()).thenReturn(_brokerId); diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/BrokerStoreUpgraderAndRecovererTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/BrokerStoreUpgraderAndRecovererTest.java index 830fa46c2c..274ff1b1a7 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/BrokerStoreUpgraderAndRecovererTest.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/BrokerStoreUpgraderAndRecovererTest.java @@ -81,7 +81,7 @@ public class BrokerStoreUpgraderAndRecovererTest extends QpidTestCase _systemConfig = new JsonSystemConfigImpl(_taskExecutor, mock(EventLogger.class), mock(LogRecorder.class), - new BrokerOptions(), + new BrokerOptions().convertToSystemConfigAttributes(), mock(BrokerShutdownProvider.class)); } diff --git a/qpid/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/store/derby/DerbySystemConfigImpl.java b/qpid/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/store/derby/DerbySystemConfigImpl.java index a8b9edaa12..0cc4f2b18c 100644 --- a/qpid/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/store/derby/DerbySystemConfigImpl.java +++ b/qpid/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/store/derby/DerbySystemConfigImpl.java @@ -20,7 +20,8 @@ */ package org.apache.qpid.server.store.derby; -import org.apache.qpid.server.BrokerOptions; +import java.util.Map; + import org.apache.qpid.server.configuration.updater.TaskExecutor; import org.apache.qpid.server.logging.EventLogger; import org.apache.qpid.server.logging.LogRecorder; @@ -48,10 +49,10 @@ public class DerbySystemConfigImpl extends AbstractSystemConfig attributes, final BrokerShutdownProvider brokerShutdownProvider) { - super(taskExecutor, eventLogger, logRecorder, brokerOptions, brokerShutdownProvider); + super(taskExecutor, eventLogger, logRecorder, attributes, brokerShutdownProvider); } @Override diff --git a/qpid/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/JDBCSystemConfigImpl.java b/qpid/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/JDBCSystemConfigImpl.java index a552b170a0..9c3d33fc04 100644 --- a/qpid/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/JDBCSystemConfigImpl.java +++ b/qpid/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/JDBCSystemConfigImpl.java @@ -20,7 +20,8 @@ */ package org.apache.qpid.server.store.jdbc; -import org.apache.qpid.server.BrokerOptions; +import java.util.Map; + import org.apache.qpid.server.configuration.updater.TaskExecutor; import org.apache.qpid.server.logging.EventLogger; import org.apache.qpid.server.logging.LogRecorder; @@ -50,10 +51,10 @@ public class JDBCSystemConfigImpl extends AbstractSystemConfig attributes, final BrokerShutdownProvider brokerShutdownProvider) { - super(taskExecutor, eventLogger, logRecorder, brokerOptions, brokerShutdownProvider); + super(taskExecutor, eventLogger, logRecorder, attributes, brokerShutdownProvider); } @Override diff --git a/qpid/java/broker-plugins/memory-store/src/main/java/org/apache/qpid/server/store/MemorySystemConfigImpl.java b/qpid/java/broker-plugins/memory-store/src/main/java/org/apache/qpid/server/store/MemorySystemConfigImpl.java index 3f5215219b..a15de21ce7 100644 --- a/qpid/java/broker-plugins/memory-store/src/main/java/org/apache/qpid/server/store/MemorySystemConfigImpl.java +++ b/qpid/java/broker-plugins/memory-store/src/main/java/org/apache/qpid/server/store/MemorySystemConfigImpl.java @@ -20,7 +20,8 @@ */ package org.apache.qpid.server.store; -import org.apache.qpid.server.BrokerOptions; +import java.util.Map; + import org.apache.qpid.server.configuration.updater.TaskExecutor; import org.apache.qpid.server.logging.EventLogger; import org.apache.qpid.server.logging.LogRecorder; @@ -40,10 +41,10 @@ public class MemorySystemConfigImpl extends AbstractSystemConfig attributes, final BrokerShutdownProvider brokerShutdownProvider) { - super(taskExecutor, eventLogger, logRecorder, brokerOptions, brokerShutdownProvider); + super(taskExecutor, eventLogger, logRecorder, attributes, brokerShutdownProvider); } @Override diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java index fb254f59ae..3d0fb90036 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java @@ -108,7 +108,7 @@ public class TestBrokerConfiguration final AbstractSystemConfig parentObject = new JsonSystemConfigImpl(taskExecutor, mock(EventLogger.class), mock(LogRecorder.class), - brokerOptions, + brokerOptions.convertToSystemConfigAttributes(), mock(BrokerShutdownProvider.class)); ConfiguredObjectRecordConverter converter = new ConfiguredObjectRecordConverter(BrokerModel.getInstance()); @@ -219,7 +219,7 @@ public class TestBrokerConfiguration final SystemConfig parentObject = configFactory.newInstance(_taskExecutor, mock(EventLogger.class), mock(LogRecorder.class), - brokerOptions, + brokerOptions.convertToSystemConfigAttributes(), mock(BrokerShutdownProvider.class)); parentObject.open(); -- cgit v1.2.1 From b1e8d83ef545719e5a39d50726d977b5f747a245 Mon Sep 17 00:00:00 2001 From: Robert Godfrey Date: Sun, 7 Dec 2014 21:19:21 +0000 Subject: QPID-6263 : [Java Broker] Move startup/recovery logic from server.Broker to SystemConfig git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1643719 13f79535-47bb-0310-9956-ffa450edef68 --- .../main/java/org/apache/qpid/server/Broker.java | 98 ++++------------------ .../apache/qpid/server/logging/EventLogger.java | 5 ++ .../server/model/AbstractConfiguredObject.java | 7 +- .../qpid/server/model/AbstractSystemConfig.java | 82 ++++++++++++++++-- .../org/apache/qpid/server/model/SystemConfig.java | 5 +- .../store/BrokerStoreUpgraderAndRecoverer.java | 3 +- .../store/ManagementModeStoreHandlerTest.java | 34 ++++++-- .../src/main/java/org/apache/qpid/server/Main.java | 13 ++- .../qpid/test/utils/TestBrokerConfiguration.java | 22 ++--- 9 files changed, 152 insertions(+), 117 deletions(-) (limited to 'qpid/java') diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java index 3b899e3dd3..e187b32694 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java @@ -33,11 +33,9 @@ import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import org.apache.log4j.PropertyConfigurator; -import org.apache.qpid.common.QpidProperties; import org.apache.qpid.server.configuration.BrokerProperties; import org.apache.qpid.server.configuration.updater.TaskExecutor; import org.apache.qpid.server.configuration.updater.TaskExecutorImpl; -import org.apache.qpid.server.logging.CompositeStartupMessageLogger; import org.apache.qpid.server.logging.EventLogger; import org.apache.qpid.server.logging.Log4jMessageLogger; import org.apache.qpid.server.logging.LogRecorder; @@ -46,14 +44,11 @@ import org.apache.qpid.server.logging.SystemOutMessageLogger; import org.apache.qpid.server.logging.log4j.LoggingManagementFacade; import org.apache.qpid.server.logging.messages.BrokerMessages; import org.apache.qpid.server.model.BrokerShutdownProvider; -import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.SystemConfig; import org.apache.qpid.server.plugin.PluggableFactoryLoader; import org.apache.qpid.server.plugin.SystemConfigFactory; import org.apache.qpid.server.security.SecurityManager; -import org.apache.qpid.server.store.BrokerStoreUpgraderAndRecoverer; -import org.apache.qpid.server.store.DurableConfigurationStore; -import org.apache.qpid.util.SystemUtils; +import org.apache.qpid.server.util.Action; public class Broker implements BrokerShutdownProvider { @@ -63,23 +58,20 @@ public class Broker implements BrokerShutdownProvider private EventLogger _eventLogger; private boolean _configuringOwnLogging = false; private final TaskExecutor _taskExecutor = new TaskExecutorImpl(); - private final boolean _exitJVMOnShutdownWithNonZeroExitCode; private SystemConfig _systemConfig; - private org.apache.qpid.server.model.Broker _broker; - - private DurableConfigurationStore _store; + private final Action _shutdownAction; public Broker() { - this(false); + this(null); } - public Broker(boolean exitJVMOnShutdownWithNonZeroExitCode) + public Broker(Action shutdownAction) { - this._exitJVMOnShutdownWithNonZeroExitCode = exitJVMOnShutdownWithNonZeroExitCode; + _shutdownAction = shutdownAction; } protected static class InitException extends RuntimeException @@ -108,22 +100,10 @@ public class Broker implements BrokerShutdownProvider { try { - try - { - if (_broker != null) - { - _broker.close(); - } - } - finally + if(_systemConfig != null) { - if(_systemConfig != null) - { - _systemConfig.close(); - } + _systemConfig.close(); } - _store = null; - _broker = null; _taskExecutor.stop(); } @@ -134,9 +114,9 @@ public class Broker implements BrokerShutdownProvider LogManager.shutdown(); } - if (_exitJVMOnShutdownWithNonZeroExitCode && exitStatusCode != 0) + if (_shutdownAction != null) { - System.exit(exitStatusCode); + _shutdownAction.performAction(exitStatusCode); } } } @@ -178,6 +158,10 @@ public class Broker implements BrokerShutdownProvider { configureLogging(new File(options.getLogConfigFileLocation()), options.getLogWatchFrequency()); } + // Create the RootLogger to be used during broker operation + boolean statusUpdatesEnabled = Boolean.parseBoolean(System.getProperty(BrokerProperties.PROPERTY_STATUS_UPDATES, "true")); + MessageLogger messageLogger = new Log4jMessageLogger(statusUpdatesEnabled); + _eventLogger.setMessageLogger(messageLogger); PluggableFactoryLoader configFactoryLoader = new PluggableFactoryLoader<>(SystemConfigFactory.class); @@ -194,66 +178,16 @@ public class Broker implements BrokerShutdownProvider _taskExecutor.start(); _systemConfig = configFactory.newInstance(_taskExecutor, _eventLogger, logRecorder, options.convertToSystemConfigAttributes(), this); - _systemConfig.open(); - _store = _systemConfig.getConfigurationStore(); - try { - // Create the RootLogger to be used during broker operation - boolean statusUpdatesEnabled = Boolean.parseBoolean(System.getProperty(BrokerProperties.PROPERTY_STATUS_UPDATES, "true")); - MessageLogger messageLogger = new Log4jMessageLogger(statusUpdatesEnabled); - final EventLogger eventLogger = _systemConfig.getEventLogger(); - eventLogger.setMessageLogger(messageLogger); - - //Create the composite (log4j+SystemOut MessageLogger to be used during startup - MessageLogger[] messageLoggers = {new SystemOutMessageLogger(), messageLogger}; - - CompositeStartupMessageLogger startupMessageLogger = new CompositeStartupMessageLogger(messageLoggers); - EventLogger startupLogger = new EventLogger(startupMessageLogger); - - startupLogger.message(BrokerMessages.STARTUP(QpidProperties.getReleaseVersion(), - QpidProperties.getBuildVersion())); - - startupLogger.message(BrokerMessages.PLATFORM(System.getProperty("java.vendor"), - System.getProperty("java.runtime.version", - System.getProperty("java.version")), - SystemUtils.getOSName(), - SystemUtils.getOSVersion(), - SystemUtils.getOSArch())); - - startupLogger.message(BrokerMessages.MAX_MEMORY(Runtime.getRuntime().maxMemory())); - - BrokerStoreUpgraderAndRecoverer upgrader = new BrokerStoreUpgraderAndRecoverer(_systemConfig); - org.apache.qpid.server.model.Broker broker = upgrader.perform(_store); - _broker = broker; - - broker.setEventLogger(startupLogger); - broker.open(); - - if (broker.getState() == State.ACTIVE) - { - startupLogger.message(BrokerMessages.READY()); - broker.setEventLogger(eventLogger); - } + _systemConfig.open(); } - catch(Exception e) + catch(RuntimeException e) { LOGGER.fatal("Exception during startup", e); try { - try - { - if (_broker != null) - { - _broker.close(); - } - } - finally - { - _systemConfig.close(); - } - _store = null; - _broker = null; + _systemConfig.close(); } catch(Exception ce) { diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/logging/EventLogger.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/logging/EventLogger.java index 70d1db794e..ed97e14ab4 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/logging/EventLogger.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/logging/EventLogger.java @@ -59,4 +59,9 @@ public class EventLogger { _messageLogger = messageLogger; } + + public MessageLogger getMessageLogger() + { + return _messageLogger; + } } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java index a2f4f4ee0a..b9a4b32acb 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java @@ -556,9 +556,14 @@ public abstract class AbstractConfiguredObject> im { } + protected boolean rethrowRuntimeExceptionsOnOpen() + { + return false; + } + protected final void handleExceptionOnOpen(RuntimeException e) { - if (e instanceof ServerScopedRuntimeException) + if (rethrowRuntimeExceptionsOnOpen() || e instanceof ServerScopedRuntimeException) { throw e; } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractSystemConfig.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractSystemConfig.java index 5dfb178f15..19918abb14 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractSystemConfig.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractSystemConfig.java @@ -31,15 +31,21 @@ import java.util.HashMap; import java.util.Map; import java.util.UUID; +import org.apache.qpid.common.QpidProperties; import org.apache.qpid.server.configuration.IllegalConfigurationException; import org.apache.qpid.server.configuration.store.ManagementModeStoreHandler; import org.apache.qpid.server.configuration.updater.TaskExecutor; +import org.apache.qpid.server.logging.CompositeStartupMessageLogger; import org.apache.qpid.server.logging.EventLogger; import org.apache.qpid.server.logging.LogRecorder; +import org.apache.qpid.server.logging.MessageLogger; +import org.apache.qpid.server.logging.SystemOutMessageLogger; import org.apache.qpid.server.logging.messages.BrokerMessages; +import org.apache.qpid.server.store.BrokerStoreUpgraderAndRecoverer; import org.apache.qpid.server.store.ConfiguredObjectRecord; import org.apache.qpid.server.store.ConfiguredObjectRecordConverter; import org.apache.qpid.server.store.DurableConfigurationStore; +import org.apache.qpid.util.SystemUtils; public abstract class AbstractSystemConfig> extends AbstractConfiguredObject implements SystemConfig @@ -72,6 +78,9 @@ public abstract class AbstractSystemConfig> @ManagedAttributeField private String _initialConfigurationLocation; + @ManagedAttributeField + private boolean _startupLoggedToSystemOut; + public AbstractSystemConfig(final TaskExecutor taskExecutor, final EventLogger eventLogger, @@ -102,12 +111,6 @@ public abstract class AbstractSystemConfig> throw new IllegalArgumentException("Cannot change the state of the SystemContext object"); } - @Override - public State getState() - { - return State.ACTIVE; - } - @Override public EventLogger getEventLogger() { @@ -176,9 +179,9 @@ public abstract class AbstractSystemConfig> try { _configurationStore.openConfigurationStore(this, - false, - convertToConfigurationRecords(getInitialConfigurationLocation(), - this)); + false, + convertToConfigurationRecords(getInitialConfigurationLocation(), + this)); _configurationStore.upgradeStoreStructure(); } catch (IOException e) @@ -186,6 +189,61 @@ public abstract class AbstractSystemConfig> throw new IllegalArgumentException(e); } + + + } + + @StateTransition(currentState = State.UNINITIALIZED, desiredState = State.ACTIVE) + protected void activate() + { + final EventLogger eventLogger = _eventLogger; + + EventLogger startupLogger; + if (isStartupLoggedToSystemOut()) + { + //Create the composite (logging+SystemOut MessageLogger to be used during startup + MessageLogger[] messageLoggers = {new SystemOutMessageLogger(), eventLogger.getMessageLogger()}; + + CompositeStartupMessageLogger startupMessageLogger = new CompositeStartupMessageLogger(messageLoggers); + startupLogger = new EventLogger(startupMessageLogger); + } + else + { + startupLogger = eventLogger; + } + + startupLogger.message(BrokerMessages.STARTUP(QpidProperties.getReleaseVersion(), + QpidProperties.getBuildVersion())); + + startupLogger.message(BrokerMessages.PLATFORM(System.getProperty("java.vendor"), + System.getProperty("java.runtime.version", + System.getProperty("java.version")), + SystemUtils.getOSName(), + SystemUtils.getOSVersion(), + SystemUtils.getOSArch())); + + startupLogger.message(BrokerMessages.MAX_MEMORY(Runtime.getRuntime().maxMemory())); + + BrokerStoreUpgraderAndRecoverer upgrader = new BrokerStoreUpgraderAndRecoverer(this); + upgrader.perform(); + + Broker broker = getBroker(); + + broker.setEventLogger(startupLogger); + broker.open(); + + if (broker.getState() == State.ACTIVE) + { + startupLogger.message(BrokerMessages.READY()); + broker.setEventLogger(eventLogger); + } + + } + + @Override + protected final boolean rethrowRuntimeExceptionsOnOpen() + { + return true; } abstract protected DurableConfigurationStore createStoreObject(); @@ -275,4 +333,10 @@ public abstract class AbstractSystemConfig> { return _brokerShutdownProvider; } + + @Override + public boolean isStartupLoggedToSystemOut() + { + return _startupLoggedToSystemOut; + } } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/SystemConfig.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/SystemConfig.java index c985541a53..a69808180d 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/SystemConfig.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/SystemConfig.java @@ -35,7 +35,8 @@ public interface SystemConfig> extends ConfiguredObjec String MANAGEMENT_MODE_HTTP_PORT_OVERRIDE = "managementModeHttpPortOverride"; String MANAGEMENT_MODE_PASSWORD = "managementModePassword"; String INITIAL_CONFIGURATION_LOCATION = "initialConfigurationLocation"; - + String STARTUP_LOGGED_TO_SYSTEM_OUT = "startupLoggedToSystemOut"; + @ManagedAttribute(defaultValue = "false") boolean isManagementMode(); @@ -57,6 +58,8 @@ public interface SystemConfig> extends ConfiguredObjec @ManagedAttribute String getInitialConfigurationLocation(); + @ManagedAttribute(defaultValue = "true") + boolean isStartupLoggedToSystemOut(); EventLogger getEventLogger(); diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/BrokerStoreUpgraderAndRecoverer.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/BrokerStoreUpgraderAndRecoverer.java index 2be2bbbf28..a2d8d21d58 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/BrokerStoreUpgraderAndRecoverer.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/BrokerStoreUpgraderAndRecoverer.java @@ -604,8 +604,9 @@ public class BrokerStoreUpgraderAndRecoverer return brokerRecord; } - public Broker perform(final DurableConfigurationStore store) + public Broker perform() { + final DurableConfigurationStore store = _systemConfig.getConfigurationStore(); List upgradedRecords = upgrade(store); new GenericRecoverer(_systemConfig).recover(upgradedRecords); diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandlerTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandlerTest.java index 57672dc4f7..0dee5821b2 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandlerTest.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandlerTest.java @@ -44,8 +44,10 @@ import org.apache.qpid.server.configuration.updater.CurrentThreadTaskExecutor; import org.apache.qpid.server.configuration.updater.TaskExecutor; import org.apache.qpid.server.logging.EventLogger; import org.apache.qpid.server.logging.LogRecorder; +import org.apache.qpid.server.model.AbstractSystemConfig; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.BrokerShutdownProvider; +import org.apache.qpid.server.model.ConfiguredObject; import org.apache.qpid.server.model.JsonSystemConfigImpl; import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.Protocol; @@ -87,7 +89,8 @@ public class ManagementModeStoreHandlerTest extends QpidTestCase - _root = new ConfiguredObjectRecordImpl(_rootId, Broker.class.getSimpleName(), Collections.emptyMap(), Collections.singletonMap(SystemConfig.class.getSimpleName(), systemContextRecord.getId())); + _root = new ConfiguredObjectRecordImpl(_rootId, Broker.class.getSimpleName(), Collections.singletonMap(Broker.NAME, + (Object) "broker"), Collections.singletonMap(SystemConfig.class.getSimpleName(), systemContextRecord.getId())); _portEntry = mock(ConfiguredObjectRecord.class); when(_portEntry.getId()).thenReturn(_portEntryId); @@ -120,11 +123,30 @@ public class ManagementModeStoreHandlerTest extends QpidTestCase private ManagementModeStoreHandler createManagementModeStoreHandler() { _systemConfig.close(); - _systemConfig = new JsonSystemConfigImpl(_taskExecutor, - mock(EventLogger.class), - mock(LogRecorder.class), - _options.convertToSystemConfigAttributes(), - mock(BrokerShutdownProvider.class)); + Map attributes = new HashMap<>(_options.convertToSystemConfigAttributes()); + attributes.put(ConfiguredObject.DESIRED_STATE, State.QUIESCED); + _systemConfig = new AbstractSystemConfig(_taskExecutor, + mock(EventLogger.class), + mock(LogRecorder.class), + attributes, + mock(BrokerShutdownProvider.class)) + { + @Override + protected void onOpen() + { + } + + @Override + protected DurableConfigurationStore createStoreObject() + { + return _store; + } + + @Override + protected void onClose() + { + } + }; _systemConfig.open(); return new ManagementModeStoreHandler(_store, _systemConfig); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java index 76f8485884..f4c6926a17 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java @@ -41,6 +41,7 @@ import org.apache.log4j.Logger; import org.apache.qpid.common.QpidProperties; import org.apache.qpid.framing.ProtocolVersion; import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.util.Action; import org.apache.qpid.util.FileUtils; /** @@ -454,7 +455,17 @@ public class Main protected void startBroker(final BrokerOptions options) throws Exception { - Broker broker = new Broker(true); + Broker broker = new Broker(new Action() + { + @Override + public void performAction(final Integer exitStatusCode) + { + if (exitStatusCode != 0) + { + shutdown(exitStatusCode); + } + } + }); broker.startup(options); } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java index 3d0fb90036..549edcd650 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java @@ -44,21 +44,7 @@ import org.apache.qpid.server.BrokerOptions; import org.apache.qpid.server.configuration.updater.TaskExecutor; import org.apache.qpid.server.logging.EventLogger; import org.apache.qpid.server.logging.LogRecorder; -import org.apache.qpid.server.model.AbstractSystemConfig; -import org.apache.qpid.server.model.AccessControlProvider; -import org.apache.qpid.server.model.AuthenticationProvider; -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.model.BrokerModel; -import org.apache.qpid.server.model.BrokerShutdownProvider; -import org.apache.qpid.server.model.ConfiguredObject; -import org.apache.qpid.server.model.GroupProvider; -import org.apache.qpid.server.model.JsonSystemConfigImpl; -import org.apache.qpid.server.model.Plugin; -import org.apache.qpid.server.model.PreferencesProvider; -import org.apache.qpid.server.model.SystemConfig; -import org.apache.qpid.server.model.UUIDGenerator; -import org.apache.qpid.server.model.VirtualHostAlias; -import org.apache.qpid.server.model.VirtualHostNode; +import org.apache.qpid.server.model.*; import org.apache.qpid.server.model.adapter.FileBasedGroupProvider; import org.apache.qpid.server.model.adapter.FileBasedGroupProviderImpl; import org.apache.qpid.server.plugin.PluggableFactoryLoader; @@ -216,10 +202,13 @@ public class TestBrokerConfiguration SystemConfigFactory configFactory = (new PluggableFactoryLoader<>(SystemConfigFactory.class)).get(_storeType); + Map attributes = new HashMap<>(brokerOptions.convertToSystemConfigAttributes()); + attributes.put(SystemConfig.STARTUP_LOGGED_TO_SYSTEM_OUT, false); + attributes.put(ConfiguredObject.DESIRED_STATE, State.QUIESCED); final SystemConfig parentObject = configFactory.newInstance(_taskExecutor, mock(EventLogger.class), mock(LogRecorder.class), - brokerOptions.convertToSystemConfigAttributes(), + attributes, mock(BrokerShutdownProvider.class)); parentObject.open(); @@ -252,6 +241,7 @@ public class TestBrokerConfiguration configurationStore.openConfigurationStore(parentObject,true,initialRecords.toArray(new ConfiguredObjectRecord[initialRecords.size()])); configurationStore.closeConfigurationStore(); + parentObject.close(); return true; } -- cgit v1.2.1 From 71ddec5d6e828d3078a3782ab81955a538d22762 Mon Sep 17 00:00:00 2001 From: Alex Rudyy Date: Wed, 10 Dec 2014 17:34:03 +0000 Subject: QPID-6265: Allow suppression of system out operational logging in broker starter class git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1644491 13f79535-47bb-0310-9956-ffa450edef68 --- .../main/java/org/apache/qpid/server/Broker.java | 21 +++++++++++++++++---- .../java/org/apache/qpid/server/BrokerOptions.java | 18 +++++++++++++++++- 2 files changed, 34 insertions(+), 5 deletions(-) (limited to 'qpid/java') diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java index e187b32694..c18923ffe0 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java @@ -150,19 +150,29 @@ public class Broker implements BrokerShutdownProvider String storeLocation = options.getConfigurationStoreLocation(); String storeType = options.getConfigurationStoreType(); - _eventLogger.message(BrokerMessages.CONFIG(storeLocation)); + if (options.isStartupLoggedToSystemOut()) + { + _eventLogger.message(BrokerMessages.CONFIG(storeLocation)); + } //Allow skipping the logging configuration for people who are //embedding the broker and want to configure it themselves. if(!options.isSkipLoggingConfiguration()) { - configureLogging(new File(options.getLogConfigFileLocation()), options.getLogWatchFrequency()); + configureLogging(new File(options.getLogConfigFileLocation()), options.getLogWatchFrequency(), options.isStartupLoggedToSystemOut()); } // Create the RootLogger to be used during broker operation boolean statusUpdatesEnabled = Boolean.parseBoolean(System.getProperty(BrokerProperties.PROPERTY_STATUS_UPDATES, "true")); MessageLogger messageLogger = new Log4jMessageLogger(statusUpdatesEnabled); _eventLogger.setMessageLogger(messageLogger); + // Additionally, report BRK-1006 and BRK-1007 into log4j appenders + if(!options.isSkipLoggingConfiguration()) + { + _eventLogger.message(BrokerMessages.LOG_CONFIG(new File(options.getLogConfigFileLocation()).getAbsolutePath())); + } + + _eventLogger.message(BrokerMessages.CONFIG(storeLocation)); PluggableFactoryLoader configFactoryLoader = new PluggableFactoryLoader<>(SystemConfigFactory.class); SystemConfigFactory configFactory = configFactoryLoader.get(storeType); @@ -198,12 +208,15 @@ public class Broker implements BrokerShutdownProvider } - private void configureLogging(File logConfigFile, int logWatchTime) throws InitException, IOException + private void configureLogging(File logConfigFile, int logWatchTime, boolean startupLoggedToSystemOutput) throws InitException, IOException { _configuringOwnLogging = true; if (logConfigFile.exists() && logConfigFile.canRead()) { - _eventLogger.message(BrokerMessages.LOG_CONFIG(logConfigFile.getAbsolutePath())); + if (startupLoggedToSystemOutput) + { + _eventLogger.message(BrokerMessages.LOG_CONFIG(logConfigFile.getAbsolutePath())); + } if (logWatchTime > 0) { diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/BrokerOptions.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/BrokerOptions.java index ebb113d43b..c7cceb3913 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/BrokerOptions.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/BrokerOptions.java @@ -80,6 +80,7 @@ public class BrokerOptions private boolean _overwriteConfigurationStore; private Map _configProperties = new HashMap(); private String _initialSystemProperties; + private boolean _startupLoggedToSystemOut = true; public Map convertToSystemConfigAttributes() { @@ -95,7 +96,7 @@ public class BrokerOptions attributes.put(SystemConfig.MANAGEMENT_MODE_HTTP_PORT_OVERRIDE, _managementModeHttpPortOverride); attributes.put(SystemConfig.MANAGEMENT_MODE_PASSWORD, _managementModePassword); attributes.put(SystemConfig.INITIAL_CONFIGURATION_LOCATION, getInitialConfigurationLocation()); - + attributes.put(SystemConfig.STARTUP_LOGGED_TO_SYSTEM_OUT, isStartupLoggedToSystemOut()); return attributes; } @@ -382,4 +383,19 @@ public class BrokerOptions return _configProperties.get(QPID_HOME_DIR); } + /* + * Temporary method for test purposes + */ + public boolean isStartupLoggedToSystemOut() + { + return _startupLoggedToSystemOut; + } + + /* + * Temporary method for test purposes + */ + public void setStartupLoggedToSystemOut(boolean startupLoggedToSystemOut) + { + this._startupLoggedToSystemOut = startupLoggedToSystemOut; + } } -- cgit v1.2.1 From fd6bd8b5dee6807e7890f4eda578a73b4b1bb4dc Mon Sep 17 00:00:00 2001 From: Alex Rudyy Date: Wed, 10 Dec 2014 17:34:24 +0000 Subject: QPID-6265: Change system tests to have one log per file configured using Log4j, simplify QBTC git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1644492 13f79535-47bb-0310-9956-ffa450edef68 --- qpid/java/bdbstore/systests/pom.xml | 10 + .../server/store/berkeleydb/BDBBackupTest.java | 7 +- .../store/berkeleydb/replication/GroupCreator.java | 2 +- .../berkeleydb/replication/JMXManagementTest.java | 3 +- .../berkeleydb/replication/MultiNodeTest.java | 3 +- .../store/berkeleydb/replication/TwoNodeTest.java | 3 +- qpid/java/pom.xml | 3 - qpid/java/qpid-perftests-systests/pom.xml | 8 + qpid/java/qpid-systests-parent/pom.xml | 12 +- .../org/apache/qpid/test/utils/QpidTestCase.java | 2 +- qpid/java/systests/pom.xml | 11 + .../org/apache/qpid/test/utils/BrokerHolder.java | 11 +- .../qpid/test/utils/InternalBrokerHolder.java | 22 +- .../java/org/apache/qpid/test/utils/Piper.java | 20 +- .../apache/qpid/test/utils/QpidBrokerTestCase.java | 406 +++++++-------------- .../qpid/test/utils/SpawnedBrokerHolder.java | 207 ++++++++++- .../org/apache/qpid/server/BrokerStartupTest.java | 4 +- .../qpid/server/logging/BrokerLoggingTest.java | 119 +----- .../server/security/acl/AbstractACLTestCase.java | 2 +- .../management/jmx/LoggingManagementTest.java | 20 +- .../management/jmx/ManagementLoggingTest.java | 8 +- .../apache/qpid/systest/rest/KeyStoreRestTest.java | 4 +- .../apache/qpid/systest/rest/LogViewerTest.java | 49 ++- .../qpid/systest/rest/TrustStoreRestTest.java | 4 +- qpid/java/test-profiles/log4j-test.xml | 67 ---- qpid/java/test-profiles/test_resources/log4j.xml | 53 +++ .../test_resources/spawned-broker-log4j.xml | 59 +++ 27 files changed, 589 insertions(+), 530 deletions(-) delete mode 100644 qpid/java/test-profiles/log4j-test.xml create mode 100644 qpid/java/test-profiles/test_resources/log4j.xml create mode 100644 qpid/java/test-profiles/test_resources/spawned-broker-log4j.xml (limited to 'qpid/java') diff --git a/qpid/java/bdbstore/systests/pom.xml b/qpid/java/bdbstore/systests/pom.xml index b56488bc03..a5e9e2c609 100644 --- a/qpid/java/bdbstore/systests/pom.xml +++ b/qpid/java/bdbstore/systests/pom.xml @@ -80,6 +80,16 @@ + + + + src/main/resources + + + ${test.resource.directory}/test-profiles/test_resources + + + org.apache.maven.plugins diff --git a/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBBackupTest.java b/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBBackupTest.java index fab889a49f..874b5eb324 100644 --- a/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBBackupTest.java +++ b/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBBackupTest.java @@ -31,6 +31,7 @@ import javax.jms.MessageConsumer; import javax.jms.Session; import org.apache.log4j.Logger; +import org.apache.qpid.server.configuration.BrokerProperties; import org.apache.qpid.server.model.VirtualHostNode; import org.apache.qpid.server.virtualhostnode.berkeleydb.BDBVirtualHostNode; import org.apache.qpid.test.utils.Piper; @@ -151,15 +152,15 @@ public class BDBBackupTest extends QpidBrokerTestCase Process backupProcess = null; try { - String qpidHome = System.getProperty(QPID_HOME); + String qpidHome = QPID_HOME; ProcessBuilder pb = new ProcessBuilder(qpidHome + BACKUP_SCRIPT, "-todir", backupToDir.getAbsolutePath(), "-fromdir", backupFromDir.getAbsolutePath()); pb.redirectErrorStream(true); Map env = pb.environment(); - env.put(QPID_HOME, qpidHome); + env.put(BrokerProperties.PROPERTY_QPID_HOME, qpidHome); LOGGER.debug("Backup command is " + pb.command()); backupProcess = pb.start(); - Piper piper = new Piper(backupProcess.getInputStream(), _testcaseOutputStream, null, BACKUP_COMPLETE_MESSAGE); + Piper piper = new Piper(backupProcess.getInputStream(), null, BACKUP_COMPLETE_MESSAGE, "BACKUP", ""); piper.start(); piper.await(2, TimeUnit.SECONDS); backupProcess.waitFor(); diff --git a/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/GroupCreator.java b/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/GroupCreator.java index a209b476cf..9455d788e4 100644 --- a/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/GroupCreator.java +++ b/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/GroupCreator.java @@ -209,7 +209,7 @@ public class GroupCreator { try { - _testcase.startBroker(brokerPortNumber, brokerConfig); + _testcase.startBroker(brokerPortNumber, brokerConfig, null); return "OK"; } catch (Exception e) diff --git a/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/JMXManagementTest.java b/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/JMXManagementTest.java index 4fd3540964..8933297b4a 100644 --- a/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/JMXManagementTest.java +++ b/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/JMXManagementTest.java @@ -45,6 +45,7 @@ import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.store.berkeleydb.jmx.ManagedBDBHAMessageStore; import org.apache.qpid.server.virtualhostnode.berkeleydb.BDBHAVirtualHostNode; import org.apache.qpid.systest.rest.RestTestHelper; +import org.apache.qpid.test.utils.BrokerHolder; import org.apache.qpid.test.utils.JMXTestUtils; import org.apache.qpid.test.utils.QpidBrokerTestCase; import org.junit.Assert; @@ -72,7 +73,7 @@ public class JMXManagementTest extends QpidBrokerTestCase @Override protected void setUp() throws Exception { - _brokerType = BrokerType.SPAWNED; + _brokerType = BrokerHolder.BrokerType.SPAWNED; setTestClientSystemProperty("log4j.configuration", getBrokerCommandLog4JFile().toURI().toString()); diff --git a/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/MultiNodeTest.java b/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/MultiNodeTest.java index 50ca39c83b..7ec28bd1f2 100644 --- a/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/MultiNodeTest.java +++ b/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/MultiNodeTest.java @@ -48,6 +48,7 @@ import org.apache.qpid.jms.ConnectionURL; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.State; import org.apache.qpid.server.virtualhostnode.berkeleydb.BDBHAVirtualHostNode; +import org.apache.qpid.test.utils.BrokerHolder; import org.apache.qpid.test.utils.QpidBrokerTestCase; import org.apache.qpid.test.utils.TestUtils; @@ -75,7 +76,7 @@ public class MultiNodeTest extends QpidBrokerTestCase @Override protected void setUp() throws Exception { - _brokerType = BrokerType.SPAWNED; + _brokerType = BrokerHolder.BrokerType.SPAWNED; assertTrue(isJavaBroker()); assertTrue(isBrokerStorePersistent()); diff --git a/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/TwoNodeTest.java b/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/TwoNodeTest.java index 49ce60d798..b06eaf9f7c 100644 --- a/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/TwoNodeTest.java +++ b/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/TwoNodeTest.java @@ -28,6 +28,7 @@ import javax.jms.JMSException; import org.apache.qpid.jms.ConnectionURL; import org.apache.qpid.server.virtualhostnode.berkeleydb.BDBHAVirtualHostNode; +import org.apache.qpid.test.utils.BrokerHolder; import org.apache.qpid.test.utils.QpidBrokerTestCase; public class TwoNodeTest extends QpidBrokerTestCase @@ -47,7 +48,7 @@ public class TwoNodeTest extends QpidBrokerTestCase @Override protected void setUp() throws Exception { - _brokerType = BrokerType.SPAWNED; + _brokerType = BrokerHolder.BrokerType.SPAWNED; setTestClientSystemProperty("log4j.configuration", getBrokerCommandLog4JFile().toURI().toString()); diff --git a/qpid/java/pom.xml b/qpid/java/pom.xml index d2d132294d..43e50980d1 100644 --- a/qpid/java/pom.xml +++ b/qpid/java/pom.xml @@ -218,9 +218,6 @@ debug debug warn - ${project.basedir}${file.separator}test-profiles${file.separator}log4j-test.xml - log4j-test.xml - false 15672 18999 19099 diff --git a/qpid/java/qpid-perftests-systests/pom.xml b/qpid/java/qpid-perftests-systests/pom.xml index 64a5708501..e3c52326e3 100644 --- a/qpid/java/qpid-perftests-systests/pom.xml +++ b/qpid/java/qpid-perftests-systests/pom.xml @@ -110,6 +110,14 @@ + + + src/main/resources + + + ${test.resource.directory}/test-profiles/test_resources + + src/test/java diff --git a/qpid/java/qpid-systests-parent/pom.xml b/qpid/java/qpid-systests-parent/pom.xml index 88c0c45354..ce25221ffc 100644 --- a/qpid/java/qpid-systests-parent/pom.xml +++ b/qpid/java/qpid-systests-parent/pom.xml @@ -35,7 +35,8 @@ ${basedir}${file.separator}${broker.home.dir} ${qpid.home}${file.separator}qbtc-output - ${project.basedir}${file.separator}..${file.separator}test-profiles${file.separator}log4j-test.xml + ${basedir}${file.separator}target${file.separator}surefire-reports + ${basedir}/.. ${basedir}/.. ${basedir} @@ -83,7 +84,14 @@ integration-test phase below instead --> true - ${test.log4j.configuration.file} + ${test.output.dir} + ${basedir}${file.separator}target${file.separator}classes/log4j.xml + + false + true + + ${basedir}${file.separator}target${file.separator}classes/spawned-broker-log4j.xml diff --git a/qpid/java/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/QpidTestCase.java b/qpid/java/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/QpidTestCase.java index 5c9dc12d77..9238224f50 100644 --- a/qpid/java/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/QpidTestCase.java +++ b/qpid/java/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/QpidTestCase.java @@ -46,7 +46,7 @@ public class QpidTestCase extends TestCase public static final String TEST_RESOURCES_DIR = QPID_HOME + "/../test-profiles/test_resources/"; public static final String TEST_PROFILES_DIR = QPID_HOME + "/../test-profiles/"; public static final String TMP_FOLDER = System.getProperty("java.io.tmpdir"); - public static final String LOG4J_CONFIG_FILE_PATH = System.getProperty("log4j.configuration.file"); + public static final String SPAWNED_BROKER_LOG4J_CONFIG_FILE_PATH = System.getProperty("spawnedbroker.log4j.configuration.file"); private static final Logger _logger = Logger.getLogger(QpidTestCase.class); diff --git a/qpid/java/systests/pom.xml b/qpid/java/systests/pom.xml index d6c095dd4c..26e1d5b974 100644 --- a/qpid/java/systests/pom.xml +++ b/qpid/java/systests/pom.xml @@ -189,4 +189,15 @@ + + + + src/main/resources + + + ${test.resource.directory}/test-profiles/test_resources + + + + diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/BrokerHolder.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/BrokerHolder.java index 3af57327d2..4537d1a678 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/BrokerHolder.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/BrokerHolder.java @@ -20,10 +20,19 @@ */ package org.apache.qpid.test.utils; +import org.apache.qpid.server.BrokerOptions; + public interface BrokerHolder { - String getWorkingDirectory(); + public void start(BrokerOptions options) throws Exception; void shutdown(); void kill(); String dumpThreads(); + + enum BrokerType + { + EXTERNAL /** Test case relies on a Broker started independently of the test-suite */, + INTERNAL /** Test case starts an embedded broker within this JVM */, + SPAWNED /** Test case spawns a new broker as a separate process */ + } } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/InternalBrokerHolder.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/InternalBrokerHolder.java index f980453d49..a76f79f8b0 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/InternalBrokerHolder.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/InternalBrokerHolder.java @@ -21,12 +21,13 @@ package org.apache.qpid.test.utils; import java.security.PrivilegedAction; +import java.util.Map; import java.util.Set; import org.apache.log4j.Logger; import org.apache.qpid.server.Broker; -import org.apache.qpid.server.security.auth.TaskPrincipal; +import org.apache.qpid.server.BrokerOptions; import org.apache.qpid.server.security.SecurityManager; import javax.security.auth.Subject; @@ -35,27 +36,22 @@ public class InternalBrokerHolder implements BrokerHolder { private static final Logger LOGGER = Logger.getLogger(InternalBrokerHolder.class); - private final Broker _broker; - private final String _workingDirectory; + private Broker _broker; private Set _portsUsedByBroker; - public InternalBrokerHolder(final Broker broker, String workingDirectory, Set portsUsedByBroker) + public InternalBrokerHolder(Set portsUsedByBroker) { - if(broker == null) - { - throw new IllegalArgumentException("Broker must not be null"); - } - - _broker = broker; - _workingDirectory = workingDirectory; _portsUsedByBroker = portsUsedByBroker; } @Override - public String getWorkingDirectory() + public void start(BrokerOptions options) throws Exception { - return _workingDirectory; + LOGGER.info("Starting internal broker (same JVM)"); + + _broker = new Broker(); + _broker.startup(options); } public void shutdown() diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/Piper.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/Piper.java index 9413e38606..12be233c35 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/Piper.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/Piper.java @@ -35,27 +35,21 @@ public final class Piper extends Thread private static final Logger LOGGER = Logger.getLogger(Piper.class); private final BufferedReader _in; - private final PrintStream _out; + private final Logger _out; private final String _ready; private final CountDownLatch _latch; private final String _stopped; - private final String _prefix; private volatile boolean _seenReady; private volatile String _stopLine; - public Piper(InputStream in, PrintStream out, String ready, String stopped) - { - this(in, out, ready, stopped, null); - } - - public Piper(InputStream in, PrintStream out, String ready, String stopped, String prefix) + public Piper(InputStream in, String ready, String stopped, String threadName, String loggerName) { + super(threadName); _in = new BufferedReader(new InputStreamReader(in)); - _out = out; + _out = Logger.getLogger(loggerName); _ready = ready; _stopped = stopped; _seenReady = false; - _prefix = prefix; if (this._ready != null && !this._ready.equals("")) { @@ -87,11 +81,7 @@ public final class Piper extends Thread String line; while ((line = _in.readLine()) != null) { - if (_prefix != null) - { - line = _prefix + line; - } - _out.println(line); + _out.info(line); if (_latch != null && line.contains(_ready)) { diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java index 369a76a6c6..9a3308603b 100755 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java @@ -18,9 +18,7 @@ package org.apache.qpid.test.utils; import java.io.File; -import java.io.FileOutputStream; import java.io.IOException; -import java.io.PrintStream; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -28,7 +26,6 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.concurrent.TimeUnit; import javax.jms.BytesMessage; import javax.jms.Connection; @@ -48,8 +45,10 @@ import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; -import org.apache.commons.lang.StringUtils; +import org.apache.log4j.FileAppender; +import org.apache.log4j.LogManager; import org.apache.log4j.Logger; +import org.apache.log4j.xml.DOMConfigurator; import org.apache.qpid.AMQException; import org.apache.qpid.client.AMQConnectionFactory; @@ -60,7 +59,6 @@ import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.jms.BrokerDetails; import org.apache.qpid.jms.ConnectionURL; -import org.apache.qpid.server.Broker; import org.apache.qpid.server.BrokerOptions; import org.apache.qpid.server.configuration.BrokerProperties; import org.apache.qpid.server.configuration.updater.TaskExecutor; @@ -83,19 +81,11 @@ public class QpidBrokerTestCase extends QpidTestCase { private TaskExecutor _taskExecutor; - public enum BrokerType - { - EXTERNAL /** Test case relies on a Broker started independently of the test-suite */, - INTERNAL /** Test case starts an embedded broker within this JVM */, - SPAWNED /** Test case spawns a new broker as a separate process */ - } - public static final String GUEST_USERNAME = "guest"; public static final String GUEST_PASSWORD = "guest"; - protected final static String QpidHome = System.getProperty("QPID_HOME"); private final File _configFile = new File(System.getProperty("broker.config")); - private File _logConfigFile; + private File _spawnedBrokerLogConfigFile; protected final String _brokerStoreType = System.getProperty("broker.config-store-type", "JSON"); protected static final Logger _logger = Logger.getLogger(QpidBrokerTestCase.class); protected static final int LOGMONITOR_TIMEOUT = 5000; @@ -128,11 +118,7 @@ public class QpidBrokerTestCase extends QpidTestCase private static final String BROKER_COMMAND_PLATFORM = "broker.command." + SystemUtils.getOSConfigSuffix(); private static final String BROKER_CLEAN_BETWEEN_TESTS = "broker.clean.between.tests"; private static final String BROKER_VERSION = "broker.version"; - protected static final String BROKER_READY = "broker.ready"; - private static final String BROKER_STOPPED = "broker.stopped"; private static final String TEST_OUTPUT = "test.output"; - private static final String BROKER_LOG_INTERLEAVE = "broker.log.interleave"; - private static final String BROKER_LOG_PREFIX = "broker.log.prefix"; private static final String BROKER_PERSITENT = "broker.persistent"; public static final String PROFILE_USE_SSL = "profile.use_ssl"; @@ -141,41 +127,30 @@ public class QpidBrokerTestCase extends QpidTestCase public static final int DEFAULT_JMXPORT_REGISTRYSERVER = 8999; public static final int JMXPORT_CONNECTORSERVER_OFFSET = 100; public static final int DEFAULT_HTTP_MANAGEMENT_PORT_VALUE = 8080; - public static final int DEFAULT_HTTPS_MANAGEMENT_PORT_VALUE = 8443; public static final String TEST_AMQP_PORT_PROTOCOLS_PROPERTY="test.amqp_port_protocols"; // values protected static final String JAVA = "java"; - protected static final String CPP = "cpp"; - - protected static final String QPID_HOME = "QPID_HOME"; public static final int DEFAULT_PORT = Integer.getInteger("test.port", DEFAULT_PORT_VALUE); public static final int FAILING_PORT = Integer.parseInt(System.getProperty("test.port.alt")); public static final int DEFAULT_MANAGEMENT_PORT = Integer.getInteger("test.mport", DEFAULT_JMXPORT_REGISTRYSERVER); public static final int DEFAULT_HTTP_MANAGEMENT_PORT = Integer.getInteger("test.hport", DEFAULT_HTTP_MANAGEMENT_PORT_VALUE); - public static final int DEFAULT_HTTPS_MANAGEMENT_PORT = Integer.getInteger("test.hsport", DEFAULT_HTTPS_MANAGEMENT_PORT_VALUE); public static final int DEFAULT_SSL_PORT = Integer.getInteger("test.port.ssl", DEFAULT_SSL_PORT_VALUE); protected String _brokerLanguage = System.getProperty(BROKER_LANGUAGE, JAVA); - protected BrokerType _brokerType = BrokerType.valueOf(System.getProperty(BROKER_TYPE, "").toUpperCase()); + protected BrokerHolder.BrokerType _brokerType = BrokerHolder.BrokerType.valueOf(System.getProperty(BROKER_TYPE, "").toUpperCase()); private static final String BROKER_COMMAND_TEMPLATE = System.getProperty(BROKER_COMMAND_PLATFORM, System.getProperty(BROKER_COMMAND)); - protected BrokerCommandHelper _brokerCommandHelper = new BrokerCommandHelper(BROKER_COMMAND_TEMPLATE); private Boolean _brokerCleanBetweenTests = Boolean.getBoolean(BROKER_CLEAN_BETWEEN_TESTS); private final Protocol _brokerProtocol = Protocol.valueOf("AMQP_" + System.getProperty(BROKER_VERSION, " ").substring(1)); protected String _output = System.getProperty(TEST_OUTPUT, System.getProperty("java.io.tmpdir")); protected Boolean _brokerPersistent = Boolean.getBoolean(BROKER_PERSITENT); - protected static String _brokerLogPrefix = System.getProperty(BROKER_LOG_PREFIX,"BROKER: "); - protected static boolean _interleaveBrokerLog = Boolean.valueOf(System.getProperty(BROKER_LOG_INTERLEAVE,"true")); - protected File _outputFile; - protected PrintStream _testcaseOutputStream; - protected Map _brokers = new HashMap(); protected InitialContext _initialContext; @@ -195,6 +170,8 @@ public class QpidBrokerTestCase extends QpidTestCase /** Size to create our message*/ private int _messageSize = DEFAULT_MESSAGE_SIZE; + private String _brokerCommandTemplate; + /** Type of message*/ protected enum MessageType { @@ -210,7 +187,8 @@ public class QpidBrokerTestCase extends QpidTestCase { super(); _brokerConfigurations = new HashMap(); - initialiseLogConfigFile(); + initialiseSpawnedBrokerLogConfigFile(); + _brokerCommandTemplate = BROKER_COMMAND_TEMPLATE; } public TestBrokerConfiguration getBrokerConfiguration(int port) @@ -259,12 +237,12 @@ public class QpidBrokerTestCase extends QpidTestCase return configuration; } - private void initialiseLogConfigFile() + private void initialiseSpawnedBrokerLogConfigFile() { - _logConfigFile = new File(LOG4J_CONFIG_FILE_PATH); - if(!_logConfigFile.exists()) + _spawnedBrokerLogConfigFile = new File(SPAWNED_BROKER_LOG4J_CONFIG_FILE_PATH); + if(!_spawnedBrokerLogConfigFile.exists()) { - throw new RuntimeException("Log config file " + _logConfigFile.getAbsolutePath() + " does not exist"); + throw new RuntimeException("Log config file " + _spawnedBrokerLogConfigFile.getAbsolutePath() + " does not exist"); } } @@ -276,36 +254,18 @@ public class QpidBrokerTestCase extends QpidTestCase @Override public void runBare() throws Throwable { - String qname = getClass().getName() + "." + getName(); - // Initialize this for each test run _env = new HashMap(); - PrintStream oldOut = System.out; - PrintStream oldErr = System.err; - PrintStream out = null; - PrintStream err = null; + // Log4j properties expects this to be set + System.setProperty("qpid.testMethod", "-" + getName()); + System.setProperty("qpid.testClass", getClass().getName()); - boolean redirected = _output != null && _output.length() > 0; - if (redirected) - { - _outputFile = new File(String.format("%s/TEST-%s.out", _output, qname)); - out = new PrintStream(new FileOutputStream(_outputFile), true); - err = new PrintStream(String.format("%s/TEST-%s.err", _output, qname)); + String log4jConfigFile = System.getProperty("log4j.configuration.file"); + DOMConfigurator.configure(log4jConfigFile); - System.setOut(out); - System.setErr(err); - - if (_interleaveBrokerLog) - { - _testcaseOutputStream = out; - } - else - { - _testcaseOutputStream = new PrintStream(new FileOutputStream(String - .format("%s/TEST-%s.broker.out", _output, qname)), true); - } - } + // get log file from file appender + _outputFile = new File(((FileAppender)LogManager.getRootLogger().getAllAppenders().nextElement()).getFile()); try { @@ -324,7 +284,7 @@ public class QpidBrokerTestCase extends QpidTestCase revertSystemProperties(); revertLoggingLevels(); - if(_brokerCleanBetweenTests) + if (_brokerCleanBetweenTests) { final String qpidWork = System.getProperty("QPID_WORK"); cleanBrokerWork(qpidWork); @@ -333,17 +293,7 @@ public class QpidBrokerTestCase extends QpidTestCase _logger.info("========== stop " + getTestName() + " =========="); - if (redirected) - { - System.setErr(oldErr); - System.setOut(oldOut); - err.close(); - out.close(); - if (!_interleaveBrokerLog) - { - _testcaseOutputStream.close(); - } - } + LogManager.resetConfiguration(); } } @@ -403,7 +353,7 @@ public class QpidBrokerTestCase extends QpidTestCase protected int getPort(int port) { - if (!_brokerType.equals(BrokerType.EXTERNAL)) + if (!_brokerType.equals(BrokerHolder.BrokerType.EXTERNAL)) { return port == 0 ? DEFAULT_PORT : port; } @@ -424,29 +374,34 @@ public class QpidBrokerTestCase extends QpidTestCase } public void startBroker(int port, boolean managementMode) throws Exception + { + startBroker(port, managementMode, null); + } + + public void startBroker(int port, boolean managementMode, String log4jFile) throws Exception { int actualPort = getPort(port); TestBrokerConfiguration configuration = getBrokerConfiguration(actualPort); - startBroker(actualPort, configuration, managementMode); + startBroker(actualPort, configuration, managementMode, log4jFile); } protected File getBrokerCommandLog4JFile() { - return _logConfigFile; + return _spawnedBrokerLogConfigFile; } protected void setBrokerCommandLog4JFile(File file) { - _logConfigFile = file; + _spawnedBrokerLogConfigFile = file; _logger.info("Modified log config file to: " + file); } - public void startBroker(int port, TestBrokerConfiguration testConfiguration) throws Exception + public void startBroker(int port, TestBrokerConfiguration testConfiguration, String log4jFile) throws Exception { - startBroker(port, testConfiguration, false); + startBroker(port, testConfiguration, false, log4jFile); } - public void startBroker(int port, TestBrokerConfiguration testConfiguration, boolean managementMode) throws Exception + protected void startBroker(int port, TestBrokerConfiguration testConfiguration, boolean managementMode, String log4jFile) throws Exception { port = getPort(port); @@ -455,181 +410,12 @@ public class QpidBrokerTestCase extends QpidTestCase throw new IllegalStateException("There is already an existing broker running on port " + port); } - Set portsUsedByBroker = guessAllPortsUsedByBroker(port); String testConfig = saveTestConfiguration(port, testConfiguration); - - if (_brokerType.equals(BrokerType.INTERNAL) && !existingInternalBroker()) - { - setSystemProperty(BrokerProperties.PROPERTY_USE_CUSTOM_RMI_SOCKET_FACTORY, "false"); - BrokerOptions options = new BrokerOptions(); - - options.setConfigurationStoreType(_brokerStoreType); - options.setConfigurationStoreLocation(testConfig); - options.setManagementMode(managementMode); - if (managementMode) - { - options.setManagementModePassword(MANAGEMENT_MODE_PASSWORD); - } - - //Set the log config file, relying on the log4j.configuration system property - //set on the JVM by the JUnit runner task in module.xml. - options.setLogConfigFileLocation(_logConfigFile.getAbsolutePath()); - - Broker broker = new Broker(); - _logger.info("Starting internal broker (same JVM)"); - broker.startup(options); - - _brokers.put(port, new InternalBrokerHolder(broker, System.getProperty("QPID_WORK"), portsUsedByBroker)); - } - else if (!_brokerType.equals(BrokerType.EXTERNAL)) - { - // Add the port to QPID_WORK to ensure unique working dirs for multi broker tests - final String qpidWork = getQpidWork(_brokerType, port); - - String[] cmd = _brokerCommandHelper.getBrokerCommand(port, testConfig, _brokerStoreType, _logConfigFile); - if (managementMode) - { - String[] newCmd = new String[cmd.length + 3]; - System.arraycopy(cmd, 0, newCmd, 0, cmd.length); - newCmd[cmd.length] = "-mm"; - newCmd[cmd.length + 1] = "-mmpass"; - newCmd[cmd.length + 2] = MANAGEMENT_MODE_PASSWORD; - cmd = newCmd; - } - _logger.info("Starting spawn broker using command: " + StringUtils.join(cmd, ' ')); - ProcessBuilder pb = new ProcessBuilder(cmd); - pb.redirectErrorStream(true); - Map processEnv = pb.environment(); - String qpidHome = System.getProperty(QPID_HOME); - processEnv.put(QPID_HOME, qpidHome); - //Augment Path with bin directory in QPID_HOME. - boolean foundPath = false; - final String pathEntry = qpidHome + File.separator + "bin"; - for(Map.Entry entry : processEnv.entrySet()) - { - if(entry.getKey().equalsIgnoreCase("path")) - { - entry.setValue(entry.getValue().concat(File.pathSeparator + pathEntry)); - foundPath = true; - } - } - if(!foundPath) - { - processEnv.put("PATH", pathEntry); - - } - //Add the test name to the broker run. - // DON'T change PNAME, qpid.stop needs this value. - processEnv.put("QPID_PNAME", "-DPNAME=QPBRKR -DTNAME=\"" + getTestName() + "\""); - processEnv.put("QPID_WORK", qpidWork); - - // Use the environment variable to set amqj.logging.level for the broker - // The value used is a 'server' value in the test configuration to - // allow a differentiation between the client and broker logging levels. - if (System.getProperty("amqj.server.logging.level") != null) - { - setBrokerEnvironment("AMQJ_LOGGING_LEVEL", System.getProperty("amqj.server.logging.level")); - } - - // Add all the environment settings the test requested - if (!_env.isEmpty()) - { - for (Map.Entry entry : _env.entrySet()) - { - processEnv.put(entry.getKey(), entry.getValue()); - } - } - - String qpidOpts = ""; - - // a synchronized hack to avoid adding into QPID_OPTS the values - // of JVM properties "test.virtualhosts" and "test.config" set by a concurrent startup process - synchronized (_propertiesSetForBroker) - { - // Add default test logging levels that are used by the log4j-test - // Use the convenience methods to push the current logging setting - // in to the external broker's QPID_OPTS string. - setSystemProperty("amqj.protocol.logging.level"); - setSystemProperty("root.logging.level"); - - setSystemProperty("test.port"); - setSystemProperty("test.mport"); - setSystemProperty("test.cport"); - setSystemProperty("test.hport"); - setSystemProperty("test.hsport"); - setSystemProperty("test.port.ssl"); - setSystemProperty("test.port.alt"); - setSystemProperty("test.port.alt.ssl"); - setSystemProperty("test.amqp_port_protocols"); - - setSystemProperty("virtualhostnode.type"); - setSystemProperty("virtualhostnode.context.blueprint"); - - // Add all the specified system properties to QPID_OPTS - if (!_propertiesSetForBroker.isEmpty()) - { - for (String key : _propertiesSetForBroker.keySet()) - { - qpidOpts += " -D" + key + "=" + _propertiesSetForBroker.get(key); - } - } - } - if (processEnv.containsKey("QPID_OPTS")) - { - qpidOpts = processEnv.get("QPID_OPTS") + qpidOpts; - } - processEnv.put("QPID_OPTS", qpidOpts); - - // cpp broker requires that the work directory is created - createBrokerWork(qpidWork); - - Process process = pb.start(); - - Piper p = new Piper(process.getInputStream(), - _testcaseOutputStream, - System.getProperty(BROKER_READY), - System.getProperty(BROKER_STOPPED), - _interleaveBrokerLog ? _brokerLogPrefix : null); - - p.start(); - StringBuilder cmdLine = new StringBuilder(cmd[0]); - for(int i = 1; i< cmd.length; i++) - { - cmdLine.append(' '); - cmdLine.append(cmd[i]); - } - - SpawnedBrokerHolder holder = new SpawnedBrokerHolder(process, qpidWork, portsUsedByBroker, cmdLine.toString()); - if (!p.await(30, TimeUnit.SECONDS)) - { - _logger.info("broker failed to become ready (" + p.getReady() + "):" + p.getStopLine()); - String threadDump = holder.dumpThreads(); - if (!threadDump.isEmpty()) - { - _logger.info("the result of a try to capture thread dump:" + threadDump); - } - //Ensure broker has stopped - process.destroy(); - cleanBrokerWork(qpidWork); - throw new RuntimeException("broker failed to become ready:" - + p.getStopLine()); - } - - try - { - //test that the broker is still running and hasn't exited unexpectedly - int exit = process.exitValue(); - _logger.info("broker aborted: " + exit); - cleanBrokerWork(qpidWork); - throw new RuntimeException("broker aborted: " + exit); - } - catch (IllegalThreadStateException e) - { - // this is expect if the broker started successfully - } - - _brokers.put(port, holder); - } + String log4jConfig = log4jFile == null ? getBrokerCommandLog4JFile().getAbsolutePath() : log4jFile; + BrokerOptions options = getBrokerOptions(managementMode, testConfig, log4jConfig, log4jFile == null); + BrokerHolder holder = new BrokerHolderFactory().create(_brokerType, port, this); + _brokers.put(port, holder); + holder.start(options); } private boolean existingInternalBroker() @@ -645,21 +431,6 @@ public class QpidBrokerTestCase extends QpidTestCase return false; } - private String getQpidWork(BrokerType broker, int port) - { - if (!broker.equals(BrokerType.EXTERNAL)) - { - return System.getProperty("QPID_WORK")+ "/" + port; - } - - return System.getProperty("QPID_WORK"); - } - - public String getTestConfigFile() - { - return getTestConfigFile(getPort()); - } - public String getTestConfigFile(int port) { return _output + File.separator + getTestQueueName() + "-" + port + "-config"; @@ -1035,7 +806,7 @@ public class QpidBrokerTestCase extends QpidTestCase protected boolean isInternalBroker() { - return _brokerType.equals(BrokerType.INTERNAL); + return _brokerType.equals(BrokerHolder.BrokerType.INTERNAL); } protected boolean isBrokerStorePersistent() @@ -1397,16 +1168,6 @@ public class QpidBrokerTestCase extends QpidTestCase return message; } - protected int getMessageSize() - { - return _messageSize; - } - - protected void setMessageSize(int byteSize) - { - _messageSize = byteSize; - } - public BrokerDetails getBroker() { try @@ -1453,4 +1214,91 @@ public class QpidBrokerTestCase extends QpidTestCase session.commit(); session.close(); } + + protected BrokerOptions getBrokerOptions( boolean managementMode, String testConfig, String log4jConfig, boolean skipLoggingConfiguration) + { + BrokerOptions options = new BrokerOptions(); + + options.setConfigurationStoreType(_brokerStoreType); + options.setConfigurationStoreLocation(testConfig); + options.setManagementMode(managementMode); + if (managementMode) + { + options.setManagementModePassword(MANAGEMENT_MODE_PASSWORD); + } + options.setSkipLoggingConfiguration(skipLoggingConfiguration); + options.setLogConfigFileLocation(log4jConfig); + options.setStartupLoggedToSystemOut(false); + return options; + } + + private Map getJvmProperties() + { + Map jvmOptions = new HashMap(); + synchronized (_propertiesSetForBroker) + { + jvmOptions.putAll(_propertiesSetForBroker); + + copySystemProperty("amqj.protocol.logging.level", jvmOptions); + copySystemProperty("root.logging.level", jvmOptions); + + copySystemProperty("test.port", jvmOptions); + copySystemProperty("test.mport", jvmOptions); + copySystemProperty("test.cport", jvmOptions); + copySystemProperty("test.hport", jvmOptions); + copySystemProperty("test.hsport", jvmOptions); + copySystemProperty("test.port.ssl", jvmOptions); + copySystemProperty("test.port.alt", jvmOptions); + copySystemProperty("test.port.alt.ssl", jvmOptions); + copySystemProperty("test.amqp_port_protocols", jvmOptions); + + copySystemProperty("virtualhostnode.type", jvmOptions); + copySystemProperty("virtualhostnode.context.blueprint", jvmOptions); + } + return jvmOptions; + } + + private void copySystemProperty(String name, Map jvmOptions) + { + String value = System.getProperty(name); + if (value != null) + { + jvmOptions.put(name, value); + } + } + + private Map getEnvironmentProperties() + { + return new HashMap<>(_env); + } + + private String getBrokerCommandTemplate() + { + return _brokerCommandTemplate; + } + + public static class BrokerHolderFactory + { + + public BrokerHolder create(BrokerHolder.BrokerType brokerType, int port, QpidBrokerTestCase testCase) + { + Set portsUsedByBroker = testCase.guessAllPortsUsedByBroker(port); + BrokerHolder holder = null; + if (brokerType.equals(BrokerHolder.BrokerType.INTERNAL) && !testCase.existingInternalBroker()) + { + testCase.setSystemProperty(BrokerProperties.PROPERTY_USE_CUSTOM_RMI_SOCKET_FACTORY, "false"); + holder = new InternalBrokerHolder(portsUsedByBroker); + } + else if (!brokerType.equals(BrokerHolder.BrokerType.EXTERNAL)) + { + + Map jvmOptions = testCase.getJvmProperties(); + Map environmentProperties = testCase.getEnvironmentProperties(); + + holder = new SpawnedBrokerHolder(testCase.getBrokerCommandTemplate(), port, testCase.getTestName(), jvmOptions, environmentProperties, brokerType, portsUsedByBroker); + } + return holder; + } + } + } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/SpawnedBrokerHolder.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/SpawnedBrokerHolder.java index 4b747e869c..2581093f97 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/SpawnedBrokerHolder.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/SpawnedBrokerHolder.java @@ -22,6 +22,7 @@ package org.apache.qpid.test.utils; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -30,39 +31,215 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.TimeUnit; import org.apache.log4j.Logger; +import org.apache.qpid.server.BrokerOptions; +import org.apache.qpid.server.configuration.BrokerProperties; +import org.apache.qpid.server.logging.messages.BrokerMessages; +import org.apache.qpid.util.FileUtils; import org.apache.qpid.util.SystemUtils; public class SpawnedBrokerHolder implements BrokerHolder { private static final Logger LOGGER = Logger.getLogger(SpawnedBrokerHolder.class); + protected static final String BROKER_READY = System.getProperty("broker.ready", BrokerMessages.READY().toString()); + private static final String BROKER_STOPPED = System.getProperty("broker.stopped", BrokerMessages.STOPPED().toString()); - private final Process _process; - private final Integer _pid; - private final String _workingDirectory; + private final BrokerType _type; + private final int _port; + private final String _name; + private final Map _jvmOptions; + private final Map _environmentSettings; + protected BrokerCommandHelper _brokerCommandHelper; + + private Process _process; + private Integer _pid; private Set _portsUsedByBroker; - private final String _brokerCommand; + private String _brokerCommand; + + public SpawnedBrokerHolder(String brokerCommandTemplate, int port, String name, Map jvmOptions, Map environmentSettings, BrokerType type, Set portsUsedByBroker) + { + _type = type; + _portsUsedByBroker = portsUsedByBroker; + _port = port; + _name = name; + _jvmOptions = jvmOptions; + _environmentSettings = environmentSettings; + _brokerCommandHelper = new BrokerCommandHelper(brokerCommandTemplate); + } - public SpawnedBrokerHolder(final Process process, final String workingDirectory, Set portsUsedByBroker, - String brokerCmd) + + @Override + public void start(BrokerOptions brokerOptions) throws Exception { - if(process == null) + // Add the port to QPID_WORK to ensure unique working dirs for multi broker tests + final String qpidWork = getQpidWork(_type, _port); + + String[] cmd = _brokerCommandHelper.getBrokerCommand(_port, brokerOptions.getConfigurationStoreLocation(), brokerOptions.getConfigurationStoreType(), + new File(brokerOptions.getLogConfigFileLocation())); + if (brokerOptions.isManagementMode()) + { + String[] newCmd = new String[cmd.length + 3]; + System.arraycopy(cmd, 0, newCmd, 0, cmd.length); + newCmd[cmd.length] = "-mm"; + newCmd[cmd.length + 1] = "-mmpass"; + newCmd[cmd.length + 2] = brokerOptions.getManagementModePassword(); + cmd = newCmd; + } + ProcessBuilder pb = new ProcessBuilder(cmd); + pb.redirectErrorStream(true); + Map processEnv = pb.environment(); + String qpidHome = System.getProperty(BrokerProperties.PROPERTY_QPID_HOME); + processEnv.put(BrokerProperties.PROPERTY_QPID_HOME, qpidHome); + + //Augment Path with bin directory in QPID_HOME. + boolean foundPath = false; + final String pathEntry = qpidHome + File.separator + "bin"; + for(Map.Entry entry : processEnv.entrySet()) + { + if(entry.getKey().equalsIgnoreCase("path")) + { + entry.setValue(entry.getValue().concat(File.pathSeparator + pathEntry)); + foundPath = true; + } + } + if(!foundPath) + { + processEnv.put("PATH", pathEntry); + } + //Add the test name to the broker run. + // DON'T change PNAME, qpid.stop needs this value. + processEnv.put("QPID_PNAME", "-DPNAME=QPBRKR -DTNAME=\"" + _name + "\""); + processEnv.put("QPID_WORK", qpidWork); + + // Use the environment variable to set amqj.logging.level for the broker + // The value used is a 'server' value in the test configuration to + // allow a differentiation between the client and broker logging levels. + if (System.getProperty("amqj.server.logging.level") != null) + { + processEnv.put("AMQJ_LOGGING_LEVEL", System.getProperty("amqj.server.logging.level")); + } + + // Add all the environment settings the test requested + if (!_environmentSettings.isEmpty()) + { + for (Map.Entry entry : _environmentSettings.entrySet()) + { + processEnv.put(entry.getKey(), entry.getValue()); + } + } + + String qpidOpts = ""; + + // Add all the specified system properties to QPID_OPTS + if (!_jvmOptions.isEmpty()) { - throw new IllegalArgumentException("Process must not be null"); + for (String key : _jvmOptions.keySet()) + { + qpidOpts += " -D" + key + "=" + _jvmOptions.get(key); + } } - _process = process; + if (processEnv.containsKey("QPID_OPTS")) + { + qpidOpts = processEnv.get("QPID_OPTS") + qpidOpts; + } + processEnv.put("QPID_OPTS", qpidOpts); + + // cpp broker requires that the work directory is created + createBrokerWork(qpidWork); + + _process = pb.start(); + + Piper standardOutputPiper = new Piper(_process.getInputStream(), + BROKER_READY, + BROKER_STOPPED, + "STD", "BROKER-" + _port); + + standardOutputPiper.start(); + + new Piper(_process.getErrorStream(), null, null, "ERROR", "BROKER-" + _port).start(); + + StringBuilder cmdLine = new StringBuilder(cmd[0]); + for(int i = 1; i< cmd.length; i++) + { + cmdLine.append(' '); + cmdLine.append(cmd[i]); + } + + _brokerCommand = cmdLine.toString(); _pid = retrieveUnixPidIfPossible(); - _workingDirectory = workingDirectory; - _portsUsedByBroker = portsUsedByBroker; - _brokerCommand = brokerCmd; + + if (!standardOutputPiper.await(30, TimeUnit.SECONDS)) + { + LOGGER.info("broker failed to become ready (" + standardOutputPiper.getReady() + "):" + standardOutputPiper.getStopLine()); + String threadDump = dumpThreads(); + if (!threadDump.isEmpty()) + { + LOGGER.info("the result of a try to capture thread dump:" + threadDump); + } + //Ensure broker has stopped + _process.destroy(); + cleanBrokerWork(qpidWork); + throw new RuntimeException("broker failed to become ready:" + + standardOutputPiper.getStopLine()); + } + + try + { + //test that the broker is still running and hasn't exited unexpectedly + int exit = _process.exitValue(); + LOGGER.info("broker aborted: " + exit); + cleanBrokerWork(qpidWork); + throw new RuntimeException("broker aborted: " + exit); + } + catch (IllegalThreadStateException e) + { + // this is expect if the broker started successfully + } + } - @Override - public String getWorkingDirectory() + protected void createBrokerWork(final String qpidWork) { - return _workingDirectory; + if (qpidWork != null) + { + final File dir = new File(qpidWork); + dir.mkdirs(); + if (!dir.isDirectory()) + { + throw new RuntimeException("Failed to created Qpid work directory : " + qpidWork); + } + } + } + + private String getQpidWork(BrokerType broker, int port) + { + if (!broker.equals(BrokerType.EXTERNAL)) + { + return System.getProperty(BrokerProperties.PROPERTY_QPID_WORK) + File.separator + port; + } + + return System.getProperty(BrokerProperties.PROPERTY_QPID_WORK); + } + + private void cleanBrokerWork(final String qpidWork) + { + if (qpidWork != null) + { + LOGGER.info("Cleaning broker work dir: " + qpidWork); + + File file = new File(qpidWork); + if (file.exists()) + { + final boolean success = FileUtils.delete(file, true); + if(!success) + { + throw new RuntimeException("Failed to recursively delete beneath : " + file); + } + } + } } public void shutdown() diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/server/BrokerStartupTest.java b/qpid/java/systests/src/test/java/org/apache/qpid/server/BrokerStartupTest.java index e267bf439b..c475432113 100644 --- a/qpid/java/systests/src/test/java/org/apache/qpid/server/BrokerStartupTest.java +++ b/qpid/java/systests/src/test/java/org/apache/qpid/server/BrokerStartupTest.java @@ -77,7 +77,7 @@ public class BrokerStartupTest extends AbstractTestLogging brokerConfigFile.delete(); } - startBroker(port, null); + startBroker(port, null, null); AMQConnectionURL url = new AMQConnectionURL(String.format("amqp://" + GUEST_USERNAME @@ -209,7 +209,7 @@ public class BrokerStartupTest extends AbstractTestLogging brokerConfigFile.delete(); } - startBroker(port, null); + startBroker(port, null, null); AMQConnectionURL url = new AMQConnectionURL(String.format("amqp://" + GUEST_USERNAME diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/server/logging/BrokerLoggingTest.java b/qpid/java/systests/src/test/java/org/apache/qpid/server/logging/BrokerLoggingTest.java index 4952c4e10e..f7953e56d1 100644 --- a/qpid/java/systests/src/test/java/org/apache/qpid/server/logging/BrokerLoggingTest.java +++ b/qpid/java/systests/src/test/java/org/apache/qpid/server/logging/BrokerLoggingTest.java @@ -22,13 +22,15 @@ package org.apache.qpid.server.logging; import junit.framework.AssertionFailedError; -import org.apache.qpid.server.BrokerOptions; +import org.apache.log4j.FileAppender; +import org.apache.log4j.LogManager; import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.Transport; import org.apache.qpid.test.utils.TestBrokerConfiguration; import org.apache.qpid.transport.ConnectionException; import org.apache.qpid.util.LogMonitor; +import java.io.File; import java.io.IOException; import java.net.Socket; import java.util.Collections; @@ -59,6 +61,7 @@ public class BrokerLoggingTest extends AbstractTestLogging private static final Pattern BROKER_MESSAGE_LOG_PATTERN = Pattern.compile(BROKER_MESSAGE_LOG_REG_EXP); private static final String BRK_LOG_PREFIX = "BRK-"; + @Override public void setUp() throws Exception { setLogMessagePrefix(); @@ -144,94 +147,6 @@ public class BrokerLoggingTest extends AbstractTestLogging return getPathRelativeToWorkingDirectory(getTestConfigFile(DEFAULT_PORT)); } - /** - * Description: - * On startup the broker must report correctly report the log4j file in use. This is important as it can help diagnose why logging messages are not being reported. - * Input: - * No custom -l value should be provided on the command line so that the default value is correctly reported. - * Output: - * - * MESSAGE BRK-1007 : Using logging configuration : <$QPID_HOME>/etc/log4j.xml - * - * Validation Steps: - * - * 1. The BRK ID is correct - * 2. This occurs before the BRK-1001 startup message. - * 3. The log4j file is the full path to the file specified on the commandline. - * - * @throws Exception caused by broker startup - */ - public void testBrokerStartupDefaultLog4j() throws Exception - { - if (isJavaBroker() && isExternalBroker() && !isInternalBroker()) - { - String TESTID = "BRK-1007"; - - _brokerCommandHelper.removeBrokerCommandLog4JFile(); - - startBroker(); - - // Now we can create the monitor as _outputFile will now be defined - _monitor = new LogMonitor(_outputFile); - - // Ensure broker has fully started up. - getConnection(); - - // Ensure we wait for TESTID to be logged - waitAndFindMatches(TESTID); - - List results = waitAndFindMatches(BRK_LOG_PREFIX); - try - { - // Validation - - assertTrue("BRKer message not logged", results.size() > 0); - - boolean validation = false; - for (String rawLog : results) - { - // We don't care about messages after we have our log config - if (validation) - { - break; - } - - String log = getLog(rawLog); - - // Ensure we do not have a BRK-1001 message before - if (!getMessageID(log).equals(TESTID)) - { - assertFalse(getMessageID(log).equals("BRK-1001")); - continue; - } - - //1 - validateMessageID(TESTID, log); - - //2 - //There will be 1 copy of this startup message (via SystemOut) - assertEquals("Unexpected log4j configuration message count.", - 1, findMatches(TESTID).size()); - - //3 - String defaultLog4j = System.getProperty(QPID_HOME) + "/" + BrokerOptions.DEFAULT_LOG_CONFIG_FILE; - assertTrue("Log4j file(" + defaultLog4j + ") details not correctly logged:" + getMessageString(log), - getMessageString(log).endsWith(defaultLog4j)); - - validation = true; - } - - assertTrue("Validation not performed: " + TESTID + " not logged", validation); - } - catch (AssertionFailedError afe) - { - dumpLogs(results, _monitor); - - throw afe; - } - } - } - /** * Description: * On startup the broker must report correctly report the log4j file in use. This is important as it can help diagnose why logging messages are not being reported. The broker must also be capable of correctly recognising the command line property to specify the custom logging configuration. @@ -254,11 +169,17 @@ public class BrokerLoggingTest extends AbstractTestLogging // This logging startup code only occurs when you run a Java broker if (isJavaBroker()) { - String customLog4j = getBrokerCommandLog4JFile().getAbsolutePath(); + // Log4j properties expects this to be set + System.setProperty("qpid.testMethod", "-" + getName() + ".customLog4j"); + System.setProperty("qpid.testClass", getClass().getName() ); + + String customLog4j = System.getProperty("log4j.configuration.file"); String TESTID = "BRK-1007"; - startBroker(); + startBroker(0, false, customLog4j); + _outputFile = new File(((FileAppender) LogManager.getRootLogger().getAllAppenders().nextElement()).getFile()); + // Now we can create the monitor as _outputFile will now be defined _monitor = new LogMonitor(_outputFile); @@ -385,7 +306,7 @@ public class BrokerLoggingTest extends AbstractTestLogging //2 //There will be 2 copies of the startup message (one via SystemOut, and one via Log4J) assertEquals("Unexpected startup message count", - 2, findMatches(TESTID).size()); + 1, findMatches(TESTID).size()); validation = true; } @@ -471,9 +392,8 @@ public class BrokerLoggingTest extends AbstractTestLogging assertEquals("Incorrect message", TESTID, id); //2 - //There will be 2 copies of the startup message (one via SystemOut, and one via Log4J) assertEquals("Unexpected listen message count", - 2, findMatches(TESTID).size()); + 1, findMatches(TESTID).size()); //3 String message = getMessageString(log); @@ -587,7 +507,7 @@ public class BrokerLoggingTest extends AbstractTestLogging //There will be 4 copies of the startup message (two via SystemOut, and two via Log4J) List listenMessages = findMatches(TESTID); assertEquals("Four listen messages should be found.", - 4, listenMessages .size()); + 2, listenMessages .size()); int tcpStarted = 0; int sslStarted = 0; @@ -604,8 +524,8 @@ public class BrokerLoggingTest extends AbstractTestLogging } } - assertEquals("Unexpected number of logs 'Listening on TCP port'", 2, tcpStarted); - assertEquals("Unexpected number of logs 'Listening on SSL port'", 2, sslStarted); + assertEquals("Unexpected number of logs 'Listening on TCP port'", 1, tcpStarted); + assertEquals("Unexpected number of logs 'Listening on SSL port'", 1, sslStarted); //4 Test ports open testSocketOpen(getPort()); @@ -690,10 +610,9 @@ public class BrokerLoggingTest extends AbstractTestLogging //2 assertEquals("Ready message not present", "Qpid Broker Ready", getMessageString(log)); - //There will be 2 copies of the startup message (one via SystemOut, and one via Log4J) assertEquals("Unexpected ready message count", - 2, findMatches(TESTID).size()); - assertEquals("The ready messages should have been the last 2 messages", results.size() - 2, i); + 1, findMatches(TESTID).size()); + assertEquals("The ready messages should have been the last 2 messages", results.size() - 1, i); validationComplete = true; break; diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java b/qpid/java/systests/src/test/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java index 789ad420d8..f7722a8384 100644 --- a/qpid/java/systests/src/test/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java +++ b/qpid/java/systests/src/test/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java @@ -59,7 +59,7 @@ public abstract class AbstractACLTestCase extends QpidBrokerTestCase implements @Override public void setUp() throws Exception { - getBrokerConfiguration().addGroupFileConfiguration(System.getProperty(QPID_HOME) + "/etc/groups-systests"); + getBrokerConfiguration().addGroupFileConfiguration(QPID_HOME + "/etc/groups-systests"); // run test specific setup String testSetup = StringUtils.replace(getName(), "test", "setUp"); diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/systest/management/jmx/LoggingManagementTest.java b/qpid/java/systests/src/test/java/org/apache/qpid/systest/management/jmx/LoggingManagementTest.java index 3717c1594d..a06ed7be52 100644 --- a/qpid/java/systests/src/test/java/org/apache/qpid/systest/management/jmx/LoggingManagementTest.java +++ b/qpid/java/systests/src/test/java/org/apache/qpid/systest/management/jmx/LoggingManagementTest.java @@ -25,6 +25,7 @@ import javax.management.openmbean.CompositeData; import javax.management.openmbean.TabularData; import org.apache.qpid.management.common.mbeans.LoggingManagement; +import org.apache.qpid.server.configuration.BrokerProperties; import org.apache.qpid.server.logging.log4j.LoggingManagementFacadeTest; import org.apache.qpid.test.utils.JMXTestUtils; import org.apache.qpid.test.utils.QpidBrokerTestCase; @@ -35,7 +36,6 @@ import org.apache.qpid.util.LogMonitor; * System test for Logging Management. These tests rely on value set within * test-profiles/log4j-test.xml. * - * @see LoggingManagementMBeanTest * @see LoggingManagementFacadeTest * */ @@ -44,7 +44,9 @@ public class LoggingManagementTest extends QpidBrokerTestCase private JMXTestUtils _jmxUtils; private LoggingManagement _loggingManagement; private LogMonitor _monitor; + private File _logConfig; + @Override public void setUp() throws Exception { getBrokerConfiguration().addJmxManagementConfiguration(); @@ -56,8 +58,9 @@ public class LoggingManagementTest extends QpidBrokerTestCase File tmpLogFile = File.createTempFile("log4j" + "." + getName(), ".xml"); tmpLogFile.deleteOnExit(); - FileUtils.copy(getBrokerCommandLog4JFile(), tmpLogFile); + FileUtils.copy(new File(System.getProperty("log4j.configuration.file")), tmpLogFile); setBrokerCommandLog4JFile(tmpLogFile); + _logConfig = tmpLogFile; super.setUp(); _jmxUtils.open(); @@ -66,6 +69,12 @@ public class LoggingManagementTest extends QpidBrokerTestCase _monitor = new LogMonitor(_outputFile); } + public void startBroker() throws Exception + { + super.startBroker(0, false, _logConfig.getAbsolutePath()); + } + + @Override public void tearDown() throws Exception { try @@ -74,6 +83,11 @@ public class LoggingManagementTest extends QpidBrokerTestCase { _jmxUtils.close(); } + + if (_logConfig != null) + { + _logConfig.delete(); + } } finally { @@ -122,7 +136,7 @@ public class LoggingManagementTest extends QpidBrokerTestCase _loggingManagement.setConfigFileLoggerLevel(operationalLoggingLogger, "OFF"); List matches = _monitor.waitAndFindMatches("Setting level to OFF for logger 'qpid.message'", 5000); - assertEquals(1, matches.size()); + assertTrue(matches.size()>=1); assertEffectiveLoggingLevel(operationalLoggingLogger, "INFO"); diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java b/qpid/java/systests/src/test/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java index cb6eae013e..4df81845d8 100644 --- a/qpid/java/systests/src/test/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java +++ b/qpid/java/systests/src/test/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java @@ -104,7 +104,7 @@ public class ManagementLoggingTest extends AbstractTestLogging //There will be 2 copies of the startup message (one via SystemOut, and one via Log4J) results = findMatches("MNG-1001"); assertEquals("Unexpected startup message count.", - 2, results.size()); + 1, results.size()); //3 assertEquals("Startup log message is not 'Startup'.", "JMX Management Startup", @@ -185,7 +185,7 @@ public class ManagementLoggingTest extends AbstractTestLogging // Validation //There will be 4 startup messages (two via SystemOut, and two via Log4J) - assertEquals("Unexpected MNG-1002 message count", 4, results.size()); + assertEquals("Unexpected MNG-1002 message count", 2, results.size()); String log = getLogMessage(results, 0); @@ -197,7 +197,7 @@ public class ManagementLoggingTest extends AbstractTestLogging assertTrue("RMI Registry port not as expected(" + mPort + ").:" + getMessageString(log), getMessageString(log).endsWith(String.valueOf(mPort))); - log = getLogMessage(results, 2); + log = getLogMessage(results, 1); //1 validateMessageID("MNG-1002", log); @@ -243,7 +243,7 @@ public class ManagementLoggingTest extends AbstractTestLogging // Validate we only have two MNG-1002 (one via stdout, one via log4j) results = findMatches("MNG-1006"); assertEquals("Upexpected SSL Keystore message count", - 2, results.size()); + 1, results.size()); // Validate the keystore path is as expected assertTrue("SSL Keystore entry expected.:" + getMessageString(log), diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/KeyStoreRestTest.java b/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/KeyStoreRestTest.java index 4b881d1e9f..169ece986e 100644 --- a/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/KeyStoreRestTest.java +++ b/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/KeyStoreRestTest.java @@ -56,7 +56,7 @@ public class KeyStoreRestTest extends QpidRestTestCase Map keystore = keyStores.get(0); assertKeyStoreAttributes(keystore, TestBrokerConfiguration.ENTRY_NAME_SSL_KEYSTORE, - System.getProperty(QPID_HOME) + "/../" + TestSSLConstants.BROKER_KEYSTORE, null); + QPID_HOME + "/../" + TestSSLConstants.BROKER_KEYSTORE, null); } public void testCreate() throws Exception @@ -98,7 +98,7 @@ public class KeyStoreRestTest extends QpidRestTestCase List> keyStores = assertNumberOfKeyStores(1); Map keystore = keyStores.get(0); assertKeyStoreAttributes(keystore, TestBrokerConfiguration.ENTRY_NAME_SSL_KEYSTORE, - System.getProperty(QPID_HOME) + "/../" + TestSSLConstants.BROKER_KEYSTORE, null); + QPID_HOME + "/../" + TestSSLConstants.BROKER_KEYSTORE, null); } public void testDeleteFailsWhenKeyStoreInUse() throws Exception diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/LogViewerTest.java b/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/LogViewerTest.java index f2fb2581f7..a7bf743e72 100644 --- a/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/LogViewerTest.java +++ b/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/LogViewerTest.java @@ -28,25 +28,40 @@ import java.util.Map; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; -import org.apache.qpid.server.BrokerOptions; +import org.apache.log4j.FileAppender; +import org.apache.log4j.Logger; +import org.apache.log4j.SimpleLayout; +import org.apache.qpid.server.configuration.BrokerProperties; public class LogViewerTest extends QpidRestTestCase { - public static final String DEFAULT_FILE_APPENDER_NAME = "FileAppender"; private String _expectedLogFileName; + private FileAppender _fileAppender; + private String _appenderName; + @Override public void setUp() throws Exception { - setSystemProperty("logsuffix", "-" + getTestQueueName()); - _expectedLogFileName = System.getProperty("logprefix", "") + "qpid" + System.getProperty("logsuffix", "") + ".log"; - - // use real broker log file - File brokerLogFile = new File(System.getProperty(QPID_HOME), BrokerOptions.DEFAULT_LOG_CONFIG_FILE); - setBrokerCommandLog4JFile(brokerLogFile); + _appenderName = getTestQueueName(); + _expectedLogFileName = "qpid-" + _appenderName + ".log"; + _fileAppender = new FileAppender(new SimpleLayout(), + System.getProperty(BrokerProperties.PROPERTY_QPID_WORK) + File.separator + _expectedLogFileName, false); + _fileAppender.setName(_appenderName); + Logger.getRootLogger().addAppender(_fileAppender); super.setUp(); } + @Override + public void tearDown() throws Exception + { + if (_fileAppender != null) + { + Logger.getRootLogger().removeAppender(_fileAppender); + } + super.tearDown(); + } + public void testGetLogFiles() throws Exception { List> logFiles = getRestTestHelper().getJsonAsList("/service/logfilenames"); @@ -54,24 +69,32 @@ public class LogViewerTest extends QpidRestTestCase // 1 file appender is configured in QPID default log4j xml: assertTrue("Unexpected number of log files", logFiles.size() > 0); + Map logFileDetails = null; + for (Map appenderDetails: logFiles) + { + if (_appenderName.equals(appenderDetails.get("appenderName"))) + { + logFileDetails = appenderDetails; + break; + } + } - Map logFileDetails = logFiles.get(0); assertEquals("Unexpected log file name", _expectedLogFileName, logFileDetails.get("name")); assertEquals("Unexpected log file mime type", "text/plain", logFileDetails.get("mimeType")); - assertEquals("Unexpected log file appender",DEFAULT_FILE_APPENDER_NAME, logFileDetails.get("appenderName")); + assertEquals("Unexpected log file appender",_appenderName, logFileDetails.get("appenderName")); assertTrue("Unexpected log file size", ((Number)logFileDetails.get("size")).longValue()>0); assertTrue("Unexpected log file modification time", ((Number)logFileDetails.get("lastModified")).longValue()>0); } public void testDownloadExistingLogFiles() throws Exception { - byte[] bytes = getRestTestHelper().getBytes("/service/logfile?l=" + DEFAULT_FILE_APPENDER_NAME + "%2F" + _expectedLogFileName); + byte[] bytes = getRestTestHelper().getBytes("/service/logfile?l=" + _appenderName + "%2F" + _expectedLogFileName); ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(bytes)); try { ZipEntry entry = zis.getNextEntry(); - assertEquals("Unexpected broker log file name", DEFAULT_FILE_APPENDER_NAME + "/" + _expectedLogFileName, entry.getName()); + assertEquals("Unexpected broker log file name", _appenderName + "/" + _expectedLogFileName, entry.getName()); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len; @@ -91,7 +114,7 @@ public class LogViewerTest extends QpidRestTestCase public void testDownloadNonExistingLogFiles() throws Exception { - int responseCode = getRestTestHelper().submitRequest("/service/logfile?l=" + DEFAULT_FILE_APPENDER_NAME + "%2F" + int responseCode = getRestTestHelper().submitRequest("/service/logfile?l=" + _appenderName + "%2F" + _expectedLogFileName + "_" + System.currentTimeMillis(), "GET"); assertEquals("Unexpected response code", 404, responseCode); diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/TrustStoreRestTest.java b/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/TrustStoreRestTest.java index 5d2e9de3fa..1aac22d0aa 100644 --- a/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/TrustStoreRestTest.java +++ b/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/TrustStoreRestTest.java @@ -56,7 +56,7 @@ public class TrustStoreRestTest extends QpidRestTestCase Map truststore = trustStores.get(0); assertTrustStoreAttributes(truststore, TestBrokerConfiguration.ENTRY_NAME_SSL_TRUSTSTORE, - System.getProperty(QPID_HOME) + "/../" + TestSSLConstants.BROKER_TRUSTSTORE, false); + QPID_HOME + "/../" + TestSSLConstants.BROKER_TRUSTSTORE, false); } public void testCreate() throws Exception @@ -96,7 +96,7 @@ public class TrustStoreRestTest extends QpidRestTestCase List> trustStores = assertNumberOfTrustStores(1); Map truststore = trustStores.get(0); assertTrustStoreAttributes(truststore, TestBrokerConfiguration.ENTRY_NAME_SSL_TRUSTSTORE, - System.getProperty(QPID_HOME) + "/../" + TestSSLConstants.BROKER_TRUSTSTORE, false); + QPID_HOME + "/../" + TestSSLConstants.BROKER_TRUSTSTORE, false); } public void testDeleteFailsWhenTrustStoreInUse() throws Exception diff --git a/qpid/java/test-profiles/log4j-test.xml b/qpid/java/test-profiles/log4j-test.xml deleted file mode 100644 index a393fa0952..0000000000 --- a/qpid/java/test-profiles/log4j-test.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/qpid/java/test-profiles/test_resources/log4j.xml b/qpid/java/test-profiles/test_resources/log4j.xml new file mode 100644 index 0000000000..8c59ffdd98 --- /dev/null +++ b/qpid/java/test-profiles/test_resources/log4j.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/qpid/java/test-profiles/test_resources/spawned-broker-log4j.xml b/qpid/java/test-profiles/test_resources/spawned-broker-log4j.xml new file mode 100644 index 0000000000..6bb91f88b1 --- /dev/null +++ b/qpid/java/test-profiles/test_resources/spawned-broker-log4j.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.1 From 372b2b83eee4501412199326de903d3be65fd6f8 Mon Sep 17 00:00:00 2001 From: Alex Rudyy Date: Thu, 11 Dec 2014 12:00:26 +0000 Subject: QPID-6265: Unify log4j layout for system tests and spawn broker, rename test folder qbtc-ouput to qbtc-test-config git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1644611 13f79535-47bb-0310-9956-ffa450edef68 --- qpid/java/pom.xml | 2 +- qpid/java/qpid-systests-parent/pom.xml | 2 +- qpid/java/test-profiles/test_resources/spawned-broker-log4j.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'qpid/java') diff --git a/qpid/java/pom.xml b/qpid/java/pom.xml index 43e50980d1..0c9b1cb98e 100644 --- a/qpid/java/pom.xml +++ b/qpid/java/pom.xml @@ -54,7 +54,7 @@ ${basedir} - ${qpid.home}${file.separator}target${file.separator}qbtc-output + ${qpid.home}${file.separator}target${file.separator}qbtc-test-config ${project.build.directory}${file.separator}QPID_WORK java-mms.0-10 diff --git a/qpid/java/qpid-systests-parent/pom.xml b/qpid/java/qpid-systests-parent/pom.xml index ce25221ffc..fc76cce231 100644 --- a/qpid/java/qpid-systests-parent/pom.xml +++ b/qpid/java/qpid-systests-parent/pom.xml @@ -34,7 +34,7 @@ target${file.separator}qpid-broker${file.separator}${project.version} ${basedir}${file.separator}${broker.home.dir} - ${qpid.home}${file.separator}qbtc-output + ${qpid.home}${file.separator}qbtc-test-config ${basedir}${file.separator}target${file.separator}surefire-reports ${basedir}/.. diff --git a/qpid/java/test-profiles/test_resources/spawned-broker-log4j.xml b/qpid/java/test-profiles/test_resources/spawned-broker-log4j.xml index 6bb91f88b1..eb75e740b9 100644 --- a/qpid/java/test-profiles/test_resources/spawned-broker-log4j.xml +++ b/qpid/java/test-profiles/test_resources/spawned-broker-log4j.xml @@ -32,7 +32,7 @@ - + -- cgit v1.2.1 From c1b1f97c589be6b5bde0b57da5e3e932728d91e2 Mon Sep 17 00:00:00 2001 From: Robert Godfrey Date: Fri, 12 Dec 2014 14:48:34 +0000 Subject: QPID-6268 : [Java Broker] increment/decrement the unacknowledge count on the queue precisely when the queue entry changes state git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1644906 13f79535-47bb-0310-9956-ffa450edef68 --- .../src/main/java/org/apache/qpid/server/queue/AMQQueue.java | 2 ++ .../src/main/java/org/apache/qpid/server/queue/AbstractQueue.java | 5 +++-- .../src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) (limited to 'qpid/java') diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AMQQueue.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AMQQueue.java index 9cfa7dbcf3..aa64d6947d 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AMQQueue.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AMQQueue.java @@ -71,6 +71,8 @@ public interface AMQQueue> void decrementUnackedMsgCount(QueueEntry queueEntry); + void incrementUnackedMsgCount(QueueEntry entry); + boolean resend(final QueueEntry entry, final QueueConsumer consumer); List getMessagesOnTheQueue(); diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java index 8328baca3f..f905558f13 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java @@ -1230,7 +1230,6 @@ public abstract class AbstractQueue> setLastSeenEntry(sub, entry); _deliveredMessages.incrementAndGet(); - incrementUnackedMsgCount(entry); sub.send(entry, batch); } @@ -2461,13 +2460,15 @@ public abstract class AbstractQueue> return _unackedMsgBytes.get(); } + @Override public void decrementUnackedMsgCount(QueueEntry queueEntry) { _unackedMsgCount.decrementAndGet(); _unackedMsgBytes.addAndGet(-queueEntry.getSize()); } - private void incrementUnackedMsgCount(QueueEntry entry) + @Override + public void incrementUnackedMsgCount(QueueEntry entry) { _unackedMsgCount.incrementAndGet(); _unackedMsgBytes.addAndGet(entry.getSize()); diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java index a0f2dc798d..452c5ff14f 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java @@ -214,6 +214,7 @@ public abstract class QueueEntryImpl implements QueueEntry if(acquired) { _deliveryCountUpdater.compareAndSet(this,-1,0); + getQueue().incrementUnackedMsgCount(this); } return acquired; } -- cgit v1.2.1 From 5b46665ddfa9875ab7b11c6a916b943d4fbcce75 Mon Sep 17 00:00:00 2001 From: Keith Wall Date: Mon, 15 Dec 2014 13:03:19 +0000 Subject: QPID-6125: [Java Broker] Consistently quote queue/exchange names in error messages sent back over the wire git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1645645 13f79535-47bb-0310-9956-ffa450edef68 --- .../qpid/server/protocol/v0_8/AMQChannel.java | 89 +++++++++++----------- 1 file changed, 43 insertions(+), 46 deletions(-) (limited to 'qpid/java') diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java index 7604662980..2550221949 100644 --- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java @@ -2113,32 +2113,32 @@ public class AMQChannel catch (AMQQueue.ExistingExclusiveConsumer e) { _connection.closeConnection(AMQConstant.ACCESS_REFUSED, - "Cannot subscribe to queue " + "Cannot subscribe to queue '" + queue1.getName() - + " as it already has an existing exclusive consumer", _channelId); + + "' as it already has an existing exclusive consumer", _channelId); } catch (AMQQueue.ExistingConsumerPreventsExclusive e) { _connection.closeConnection(AMQConstant.ACCESS_REFUSED, - "Cannot subscribe to queue " + "Cannot subscribe to queue '" + queue1.getName() - + " exclusively as it already has a consumer", _channelId); + + "' exclusively as it already has a consumer", _channelId); } catch (AccessControlException e) { - _connection.closeConnection(AMQConstant.ACCESS_REFUSED, "Cannot subscribe to queue " + _connection.closeConnection(AMQConstant.ACCESS_REFUSED, "Cannot subscribe to queue '" + queue1.getName() - + " permission denied", _channelId); + + "' permission denied", _channelId); } catch (MessageSource.ConsumerAccessRefused consumerAccessRefused) { _connection.closeConnection(AMQConstant.ACCESS_REFUSED, - "Cannot subscribe to queue " + "Cannot subscribe to queue '" + queue1.getName() - + " as it already has an incompatible exclusivity policy", _channelId); + + "' as it already has an incompatible exclusivity policy", _channelId); } @@ -2247,7 +2247,7 @@ public class AMQChannel // if the exchange does not exist we raise a channel exception if (destination == null) { - closeChannel(AMQConstant.NOT_FOUND, "Unknown exchange name: " + exchangeName); + closeChannel(AMQConstant.NOT_FOUND, "Unknown exchange name: '" + exchangeName + "'"); } else { @@ -2805,15 +2805,14 @@ public class AMQChannel exchange = virtualHost.getExchange(exchangeName.toString()); if (exchange == null) { - closeChannel(AMQConstant.NOT_FOUND, "Unknown exchange: " + exchangeName); + closeChannel(AMQConstant.NOT_FOUND, "Unknown exchange: '" + exchangeName + "'"); } else if (!(type == null || type.length() == 0) && !exchange.getType().equals(type.asString())) { - _connection.closeConnection(AMQConstant.NOT_ALLOWED, "Attempt to redeclare exchange: " - + - exchangeName - + " of type " + _connection.closeConnection(AMQConstant.NOT_ALLOWED, "Attempt to redeclare exchange: '" + + exchangeName + + "' of type " + exchange.getType() + " to " + type @@ -2840,7 +2839,6 @@ public class AMQChannel { attributes.putAll(FieldTable.convertToMap(arguments)); } - attributes.put(Exchange.ID, null); attributes.put(Exchange.NAME, name); attributes.put(Exchange.TYPE, typeString); attributes.put(Exchange.DURABLE, durable); @@ -2865,8 +2863,8 @@ public class AMQChannel catch (ReservedExchangeNameException e) { _connection.closeConnection(AMQConstant.NOT_ALLOWED, - "Attempt to declare exchange: " + exchangeName + - " which begins with reserved prefix.", getChannelId()); + "Attempt to declare exchange: '" + exchangeName + + "' which begins with reserved prefix.", getChannelId()); } @@ -2875,8 +2873,8 @@ public class AMQChannel exchange = e.getExistingExchange(); if (!new AMQShortString(exchange.getType()).equals(type)) { - _connection.closeConnection(AMQConstant.NOT_ALLOWED, "Attempt to redeclare exchange: " - + exchangeName + " of type " + _connection.closeConnection(AMQConstant.NOT_ALLOWED, "Attempt to redeclare exchange: '" + + exchangeName + "' of type " + exchange.getType() + " to " + type + ".", getChannelId()); @@ -2912,7 +2910,7 @@ public class AMQChannel // note - since 0-8/9/9-1 can't set the alt. exchange this exception should never occur final String message = "Unknown alternate exchange " + (e.getName() != null - ? "name: \"" + e.getName() + "\"" + ? "name: '" + e.getName() + "'" : "id: " + e.getId()); _connection.closeConnection(AMQConstant.NOT_FOUND, message, getChannelId()); @@ -2958,7 +2956,7 @@ public class AMQChannel final ExchangeImpl exchange = virtualHost.getExchange(exchangeName); if (exchange == null) { - closeChannel(AMQConstant.NOT_FOUND, "No such exchange: " + exchangeStr); + closeChannel(AMQConstant.NOT_FOUND, "No such exchange: '" + exchangeStr + "'"); } else { @@ -3035,7 +3033,7 @@ public class AMQChannel else if (isDefaultExchange(exchange)) { _connection.closeConnection(AMQConstant.NOT_ALLOWED, - "Cannot bind the queue " + queueName + " to the default exchange", getChannelId()); + "Cannot bind the queue '" + queueName + "' to the default exchange", getChannelId()); } else @@ -3047,7 +3045,7 @@ public class AMQChannel if (exch == null) { closeChannel(AMQConstant.NOT_FOUND, - "Exchange " + exchangeName + " does not exist."); + "Exchange '" + exchangeName + "' does not exist."); } else { @@ -3138,19 +3136,19 @@ public class AMQChannel if (queue == null) { closeChannel(AMQConstant.NOT_FOUND, - "Queue: " + "Queue: '" + queueName - + " not found on VirtualHost(" - + virtualHost - + ")."); + + "' not found on VirtualHost '" + + virtualHost.getName() + + "'."); } else { if (!queue.verifySessionAccess(this)) { - _connection.closeConnection(AMQConstant.NOT_ALLOWED, "Queue " + _connection.closeConnection(AMQConstant.NOT_ALLOWED, "Queue '" + queue.getName() - + " is exclusive, but not created on this Connection.", getChannelId()); + + "' is exclusive, but not created on this Connection.", getChannelId()); } else { @@ -3180,7 +3178,6 @@ public class AMQChannel QueueArgumentsConverter.convertWireArgsToModel(FieldTable.convertToMap(arguments)); final String queueNameString = AMQShortString.toString(queueName); attributes.put(Queue.NAME, queueNameString); - attributes.put(Queue.ID, UUID.randomUUID()); attributes.put(Queue.DURABLE, durable); LifetimePolicy lifetimePolicy; @@ -3227,9 +3224,9 @@ public class AMQChannel if (!queue.verifySessionAccess(this)) { - _connection.closeConnection(AMQConstant.NOT_ALLOWED, "Queue " + _connection.closeConnection(AMQConstant.NOT_ALLOWED, "Queue '" + queue.getName() - + " is exclusive, but not created on this Connection.", getChannelId()); + + "' is exclusive, but not created on this Connection.", getChannelId()); } else if (queue.isExclusive() != exclusive) @@ -3323,27 +3320,27 @@ public class AMQChannel if (queue == null) { - closeChannel(AMQConstant.NOT_FOUND, "Queue " + queueName + " does not exist."); + closeChannel(AMQConstant.NOT_FOUND, "Queue '" + queueName + "' does not exist."); } else { if (ifEmpty && !queue.isEmpty()) { - closeChannel(AMQConstant.IN_USE, "Queue: " + queueName + " is not empty."); + closeChannel(AMQConstant.IN_USE, "Queue: '" + queueName + "' is not empty."); } else if (ifUnused && !queue.isUnused()) { // TODO - Error code - closeChannel(AMQConstant.IN_USE, "Queue: " + queueName + " is still used."); + closeChannel(AMQConstant.IN_USE, "Queue: '" + queueName + "' is still used."); } else { if (!queue.verifySessionAccess(this)) { - _connection.closeConnection(AMQConstant.NOT_ALLOWED, "Queue " + _connection.closeConnection(AMQConstant.NOT_ALLOWED, "Queue '" + queue.getName() - + " is exclusive, but not created on this Connection.", getChannelId()); + + "' is exclusive, but not created on this Connection.", getChannelId()); } else @@ -3383,7 +3380,7 @@ public class AMQChannel } else if ((queueName != null) && (queue = virtualHost.getQueue(queueName.toString())) == null) { - closeChannel(AMQConstant.NOT_FOUND, "Queue " + queueName + " does not exist."); + closeChannel(AMQConstant.NOT_FOUND, "Queue '" + queueName + "' does not exist."); } else if (!queue.verifySessionAccess(this)) { @@ -3416,14 +3413,14 @@ public class AMQChannel @Override public void receiveQueueUnbind(final AMQShortString queueName, final AMQShortString exchange, - final AMQShortString routingKey, + final AMQShortString bindingKey, final FieldTable arguments) { if(_logger.isDebugEnabled()) { _logger.debug("RECV[" + _channelId + "] QueueUnbind[" +" queue: " + queueName + " exchange: " + exchange + - " bindingKey: " + routingKey + + " bindingKey: " + bindingKey + " arguments: " + arguments + " ]"); } @@ -3440,14 +3437,14 @@ public class AMQChannel { String message = useDefaultQueue ? "No default queue defined on channel and queue was null" - : "Queue " + queueName + " does not exist."; + : "Queue '" + queueName + "' does not exist."; closeChannel(AMQConstant.NOT_FOUND, message); } else if (isDefaultExchange(exchange)) { - _connection.closeConnection(AMQConstant.NOT_ALLOWED, "Cannot unbind the queue " + _connection.closeConnection(AMQConstant.NOT_ALLOWED, "Cannot unbind the queue '" + queue.getName() - + " from the default exchange", getChannelId()); + + "' from the default exchange", getChannelId()); } else @@ -3457,9 +3454,9 @@ public class AMQChannel if (exch == null) { - closeChannel(AMQConstant.NOT_FOUND, "Exchange " + exchange + " does not exist."); + closeChannel(AMQConstant.NOT_FOUND, "Exchange '" + exchange + "' does not exist."); } - else if (!exch.hasBinding(String.valueOf(routingKey), queue)) + else if (!exch.hasBinding(String.valueOf(bindingKey), queue)) { closeChannel(AMQConstant.NOT_FOUND, "No such binding"); } @@ -3467,7 +3464,7 @@ public class AMQChannel { try { - exch.deleteBinding(String.valueOf(routingKey), queue); + exch.deleteBinding(String.valueOf(bindingKey), queue); final AMQMethodBody responseBody = _connection.getMethodRegistry().createQueueUnbindOkBody(); sync(); -- cgit v1.2.1 From 96f9c3e225682940e18bd5fa6a9a270a80de034c Mon Sep 17 00:00:00 2001 From: Keith Wall Date: Mon, 15 Dec 2014 14:28:17 +0000 Subject: QPID-6125: [Java Broker] Fix test broken by my previous commit git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1645667 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/qpid/test/unit/close/JavaServerCloseRaceConditionTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'qpid/java') diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/test/unit/close/JavaServerCloseRaceConditionTest.java b/qpid/java/systests/src/test/java/org/apache/qpid/test/unit/close/JavaServerCloseRaceConditionTest.java index 3fe45143d5..dfec1a8517 100644 --- a/qpid/java/systests/src/test/java/org/apache/qpid/test/unit/close/JavaServerCloseRaceConditionTest.java +++ b/qpid/java/systests/src/test/java/org/apache/qpid/test/unit/close/JavaServerCloseRaceConditionTest.java @@ -106,7 +106,7 @@ public class JavaServerCloseRaceConditionTest extends QpidBrokerTestCase } catch (Exception e) { - assertTrue("Exception should say the exchange is not known.", e.getMessage().contains("Unknown exchange: " + EXCHANGE_NAME)); + assertTrue("Exception should say the exchange is not known.", e.getMessage().contains("Unknown exchange: '" + EXCHANGE_NAME + "'")); } try @@ -119,7 +119,7 @@ public class JavaServerCloseRaceConditionTest extends QpidBrokerTestCase } catch (Exception e) { - assertTrue("Exception should say the exchange is not known.", e.getMessage().contains("Unknown exchange: " + EXCHANGE_NAME)); + assertTrue("Exception should say the exchange is not known.", e.getMessage().contains("Unknown exchange: '" + EXCHANGE_NAME + "'")); } } -- cgit v1.2.1 From 77dbff8daed044b9c95ef0c210b5fe69ff9bbc2c Mon Sep 17 00:00:00 2001 From: Keith Wall Date: Tue, 16 Dec 2014 08:55:22 +0000 Subject: QPID-6272: [Java Broker] Null reference to AMQChannel#defaultQueue once the queue is deleted git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1645880 13f79535-47bb-0310-9956-ffa450edef68 --- .../qpid/server/protocol/v0_8/AMQChannel.java | 50 ++++++++++++++++------ 1 file changed, 36 insertions(+), 14 deletions(-) (limited to 'qpid/java') diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java index 2550221949..5461b47eb4 100644 --- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java @@ -124,6 +124,8 @@ public class AMQChannel public static final int DEFAULT_PREFETCH = 4096; private static final Logger _logger = Logger.getLogger(AMQChannel.class); + private final DefaultQueueAssociationClearingTask + _defaultQueueAssociationClearingTask = new DefaultQueueAssociationClearingTask(); //TODO use Broker property to configure message authorization requirements private boolean _messageAuthorizationRequired = Boolean.getBoolean(BrokerProperties.PROPERTY_MSG_AUTH); @@ -140,7 +142,7 @@ public class AMQChannel private long _deliveryTag = 0; /** A channel has a default queue (the last declared) that is used when no queue name is explicitly set */ - private AMQQueue _defaultQueue; + private volatile AMQQueue _defaultQueue; /** This tag is unique per subscription to a queue. The server returns this in response to a basic.consume request. */ private int _consumerTag; @@ -181,11 +183,9 @@ public class AMQChannel private LogSubject _logSubject; private volatile boolean _rollingBack; - private static final Runnable NULL_TASK = new Runnable() { public void run() {} }; private List _resendList = new ArrayList(); private static final AMQShortString IMMEDIATE_DELIVERY_REPLY_TEXT = new AMQShortString("Immediate delivery is not possible."); - private long _createTime = System.currentTimeMillis(); private final ClientDeliveryMethod _clientDeliveryMethod; @@ -1289,17 +1289,6 @@ public class AMQChannel return "("+ _suspended.get() + ", " + _closing.get() + ", " + _connection.isClosing() + ") "+"["+ _connection.toString()+":"+_channelId+"]"; } - public void setDefaultQueue(AMQQueue queue) - { - _defaultQueue = queue; - } - - public AMQQueue getDefaultQueue() - { - return _defaultQueue; - } - - public boolean isClosing() { return _closing.get(); @@ -3585,4 +3574,37 @@ public class AMQChannel return exchangeName == null || AMQShortString.EMPTY_STRING.equals(exchangeName); } + private void setDefaultQueue(AMQQueue queue) + { + AMQQueue currentDefaultQueue = _defaultQueue; + if (queue != currentDefaultQueue) + { + if (currentDefaultQueue != null) + { + currentDefaultQueue.removeDeleteTask(_defaultQueueAssociationClearingTask); + } + if (queue != null) + { + queue.addDeleteTask(_defaultQueueAssociationClearingTask); + } + } + _defaultQueue = queue; + } + + private AMQQueue getDefaultQueue() + { + return _defaultQueue; + } + + private class DefaultQueueAssociationClearingTask implements Action + { + @Override + public void performAction(final AMQQueue queue) + { + if ( queue == _defaultQueue) + { + _defaultQueue = null; + } + } + } } -- cgit v1.2.1 From f62711351f225b7ac77cebe5066fa0a69cdbdf00 Mon Sep 17 00:00:00 2001 From: Robert Godfrey Date: Tue, 16 Dec 2014 16:56:59 +0000 Subject: QPID-5099 : [Java Client] release pre-acquired messages after explicit consumer close git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1646009 13f79535-47bb-0310-9956-ffa450edef68 --- .../src/main/java/org/apache/qpid/client/BasicMessageConsumer.java | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'qpid/java') diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer.java b/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer.java index 3d0e972ca2..b1e606b8e9 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer.java @@ -645,6 +645,12 @@ public abstract class BasicMessageConsumer extends Closeable implements Messa _receivingThread.interrupt(); } + + + if(!(isBrowseOnly() || getSession().isClosing())) + { + rollback(); + } } } -- cgit v1.2.1 From 87b282857f59a43fa77ab65a06ea55cd14de0e05 Mon Sep 17 00:00:00 2001 From: Robert Godfrey Date: Wed, 17 Dec 2014 00:22:01 +0000 Subject: QPID-6272 : [Java Broker] clear queue delete task on default queue before closing session git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1646118 13f79535-47bb-0310-9956-ffa450edef68 --- .../java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'qpid/java') diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java index 5461b47eb4..d52fb735a2 100644 --- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java @@ -142,7 +142,7 @@ public class AMQChannel private long _deliveryTag = 0; /** A channel has a default queue (the last declared) that is used when no queue name is explicitly set */ - private volatile AMQQueue _defaultQueue; + private volatile AMQQueue _defaultQueue; /** This tag is unique per subscription to a queue. The server returns this in response to a basic.consume request. */ private int _consumerTag; @@ -827,7 +827,7 @@ public class AMQChannel getVirtualHost().getEventLogger().message(_logSubject, operationalLogMessage); unsubscribeAllConsumers(); - + setDefaultQueue(null); for (Action task : _taskList) { task.performAction(this); @@ -3114,7 +3114,7 @@ public class AMQChannel queueName = queueStr.intern(); } - AMQQueue queue; + AMQQueue queue; //TODO: do we need to check that the queue already exists with exactly the same "configuration"? @@ -3574,9 +3574,9 @@ public class AMQChannel return exchangeName == null || AMQShortString.EMPTY_STRING.equals(exchangeName); } - private void setDefaultQueue(AMQQueue queue) + private void setDefaultQueue(AMQQueue queue) { - AMQQueue currentDefaultQueue = _defaultQueue; + AMQQueue currentDefaultQueue = _defaultQueue; if (queue != currentDefaultQueue) { if (currentDefaultQueue != null) -- cgit v1.2.1 From aa516ab4d908927a95b20275fc7daaa7bb9420a9 Mon Sep 17 00:00:00 2001 From: Keith Wall Date: Fri, 19 Dec 2014 19:13:50 +0000 Subject: QPID-6276: [Java Broker] Enhance the virtualhost UI to support upload/download of virtualhost config expressed as JSON. git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1646829 13f79535-47bb-0310-9956-ffa450edef68 --- .../bdb_ha/add/existinggroup/add.js | 3 + .../virtualhostnode/bdb_ha/add/newgroup/add.js | 3 + .../plugin/servlet/rest/RestServlet.java | 44 +++++- .../addVirtualHostNodeAndVirtualHost.html | 28 ++++ .../src/main/java/resources/css/common.css | 16 +++ .../src/main/java/resources/index.html | 1 + .../resources/js/qpid/management/VirtualHost.js | 14 ++ .../management/addVirtualHostNodeAndVirtualHost.js | 156 +++++++++++++++------ .../src/main/java/resources/showVirtualHost.html | 1 + 9 files changed, 219 insertions(+), 47 deletions(-) (limited to 'qpid/java') diff --git a/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/add/existinggroup/add.js b/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/add/existinggroup/add.js index ee467e69e4..532c37f65b 100644 --- a/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/add/existinggroup/add.js +++ b/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/add/existinggroup/add.js @@ -39,6 +39,9 @@ define(["dojo/_base/xhr", registry.byId("addVirtualHostNode.helperNodeName").set("regExpGen", util.nameOrContextVarRegexp); registry.byId("addVirtualHostNode.helperAddress").set("regExpGen", util.nodeAddressOrContextVarRegexp); registry.byId("addVirtualHostNode.address").set("regExpGen", util.nodeAddressOrContextVarRegexp); + + dom.byId("addVirtualHostNode.uploadFields").style.display = "none"; + } }; } diff --git a/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/add/newgroup/add.js b/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/add/newgroup/add.js index 464a01b5b0..c1aa9ffe4f 100644 --- a/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/add/newgroup/add.js +++ b/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/add/newgroup/add.js @@ -70,6 +70,9 @@ define(["dojo/_base/xhr", this.addVirtualHostNodePermittedNodes = registry.byId("addVirtualHostNode.permittedNodes"); registry.byId("addVirtualHostNode.groupName").set("regExpGen", util.nameOrContextVarRegexp); + + dom.byId("addVirtualHostNode.uploadFields").style.display = "block"; + }, _updatePermittedNodesJson: function () { diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java index 0bc0a4514f..52c9b10e59 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java @@ -62,13 +62,20 @@ public class RestServlet extends AbstractServlet public static final String INHERITED_ACTUALS_PARAM = "inheritedActuals"; public static final String EXTRACT_INITIAL_CONFIG_PARAM = "extractInitialConfig"; + /** + * Signifies that the agent wishes the servlet to set the Content-Disposition on the + * response with the value attachment. This filename will be derived from the parameter value. + */ + public static final String CONTENT_DISPOSITION_ATTACHMENT_FILENAME_PARAM = "contentDispositionAttachmentFilename"; + public static final Set RESERVED_PARAMS = new HashSet<>(Arrays.asList(DEPTH_PARAM, SORT_PARAM, ACTUALS_PARAM, INCLUDE_SYS_CONTEXT_PARAM, EXTRACT_INITIAL_CONFIG_PARAM, - INHERITED_ACTUALS_PARAM)); + INHERITED_ACTUALS_PARAM, + CONTENT_DISPOSITION_ATTACHMENT_FILENAME_PARAM)); private Class[] _hierarchy; @@ -316,19 +323,23 @@ public class RestServlet extends AbstractServlet @Override protected void doGetWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + // TODO - sort special params, everything else should act as a filter + String attachmentFilename = request.getParameter(CONTENT_DISPOSITION_ATTACHMENT_FILENAME_PARAM); + boolean extractInitialConfig = getBooleanParameterFromRequest(request, EXTRACT_INITIAL_CONFIG_PARAM); + response.setContentType("application/json"); response.setStatus(HttpServletResponse.SC_OK); setCachingHeadersOnResponse(response); + setContentDispositionHeaderIfNecessary(response, attachmentFilename); Collection> allObjects = getObjects(request); - // TODO - sort special params, everything else should act as a filter - boolean extractInitialConfig = getBooleanParameterFromRequest(request, EXTRACT_INITIAL_CONFIG_PARAM); int depth; boolean actuals; boolean includeSystemContext; boolean inheritedActuals; + if(extractInitialConfig) { depth = Integer.MAX_VALUE; @@ -344,20 +355,35 @@ public class RestServlet extends AbstractServlet inheritedActuals = getBooleanParameterFromRequest(request, INHERITED_ACTUALS_PARAM); } - List> output = new ArrayList>(); + List> output = new ArrayList<>(); for(ConfiguredObject configuredObject : allObjects) { output.add(_objectConverter.convertObjectToMap(configuredObject, getConfiguredClass(), depth, actuals, inheritedActuals, includeSystemContext, extractInitialConfig)); } + Writer writer = getOutputWriter(request, response); ObjectMapper mapper = new ObjectMapper(); mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true); mapper.writeValue(writer, extractInitialConfig && output.size() == 1 ? output.get(0) : output); + } - response.setContentType("application/json"); - response.setStatus(HttpServletResponse.SC_OK); + private void setContentDispositionHeaderIfNecessary(final HttpServletResponse response, + final String attachmentFilename) + { + if (attachmentFilename != null) + { + String filenameRfc2183 = ensureFilenameIsRfc2183(attachmentFilename); + if (filenameRfc2183.length() > 0) + { + response.setHeader("Content-disposition", String.format("attachment; filename=\"%s\"", filenameRfc2183)); + } + else + { + response.setHeader("Content-disposition", String.format("attachment")); // Agent will allow user to choose a name + } + } } private Class getConfiguredClass() @@ -671,4 +697,10 @@ public class RestServlet extends AbstractServlet return Boolean.parseBoolean(request.getParameter(paramName)); } + private String ensureFilenameIsRfc2183(final String requestedFilename) + { + String fileNameRfc2183 = requestedFilename.replaceAll("[\\P{InBasic_Latin}\\\\:/]", ""); + return fileNameRfc2183; + } + } diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/addVirtualHostNodeAndVirtualHost.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/addVirtualHostNodeAndVirtualHost.html index 3e3e931829..383c782d60 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/addVirtualHostNodeAndVirtualHost.html +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/addVirtualHostNodeAndVirtualHost.html @@ -59,6 +59,34 @@

+
+
+ +
+
+ +
+
+
+ +
+
+ + + +
+
+
+ +
+
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/css/common.css b/qpid/java/broker-plugins/management-http/src/main/java/resources/css/common.css index d04117b266..e6a0ce467f 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/css/common.css +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/css/common.css @@ -215,6 +215,22 @@ div .messages { height: 16px; } +.loadingIcon +{ + background: url("../dojo/dojox/image/resources/images/loading.gif") no-repeat; + width: 25px; + height: 25px; + display: inline-block; +} + +.loadedIcon +{ + background: url("../dojo/dojox/mobile/themes/common/domButtons/compat/mblDomButtonDarkBlueCheck.png") no-repeat; + width: 25px; + height: 25px; + display: inline-block; +} + .infoMessage { padding: 5px; diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/index.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/index.html index eb742bbfa0..379a25bbcd 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/index.html +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/index.html @@ -25,6 +25,7 @@ +