diff options
Diffstat (limited to 'java/common')
132 files changed, 3222 insertions, 11112 deletions
diff --git a/java/common/bin/qpid-run b/java/common/bin/qpid-run index 15d88992df..ef4363e88b 100755 --- a/java/common/bin/qpid-run +++ b/java/common/bin/qpid-run @@ -77,7 +77,10 @@ fi #Set the default system properties that we'll use now that they have #all been initialised -SYSTEM_PROPS="-Damqj.logging.level=$AMQJ_LOGGING_LEVEL -DQPID_HOME=$QPID_HOME -DQPID_WORK=$QPID_WORK" +declare -a SYSTEM_PROPS +SYSTEM_PROPS[${#SYSTEM_PROPS[@]}]="-Damqj.logging.level=$AMQJ_LOGGING_LEVEL" +SYSTEM_PROPS[${#SYSTEM_PROPS[@]}]="-DQPID_HOME=$QPID_HOME" +SYSTEM_PROPS[${#SYSTEM_PROPS[@]}]="-DQPID_WORK=$QPID_WORK" #If logprefix or logsuffix set to use PID make that happen #Otherwise just pass the value through for these props @@ -90,7 +93,7 @@ if [ -n "$QPID_LOG_PREFIX" ]; then log $INFO Using qpid logprefix property LOG_PREFIX=" -Dlogprefix=$QPID_LOG_PREFIX" fi - SYSTEM_PROPS="${SYSTEM_PROPS} ${LOG_PREFIX}" + SYSTEM_PROPS[${#SYSTEM_PROPS[@]}]="${LOG_PREFIX}" fi if [ -n "$QPID_LOG_SUFFIX" ]; then @@ -101,10 +104,10 @@ if [ -n "$QPID_LOG_SUFFIX" ]; then log $INFO Using qpig logsuffix property LOG_SUFFIX=" -Dlogsuffix=$QPID_LOG_SUFFIX" fi - SYSTEM_PROPS="${SYSTEM_PROPS} ${LOG_SUFFIX}" + SYSTEM_PROPS[${#SYSTEM_PROPS[@]}]="${LOG_SUFFIX}" fi -log $INFO System Properties set to $SYSTEM_PROPS +log $INFO System Properties set to ${SYSTEM_PROPS[@]} log $INFO QPID_OPTS set to $QPID_OPTS program=$(basename $0) @@ -254,6 +257,6 @@ if $cygwin; then JAVA=$(cygpath -u $JAVA) fi -COMMAND=($JAVA $JAVA_VM $QPID_PNAME $JAVA_GC $JAVA_MEM $SYSTEM_PROPS $JAVA_OPTS $QPID_OPTS "${JAVA_ARGS[@]}") +COMMAND=($JAVA $JAVA_VM $QPID_PNAME $JAVA_GC $JAVA_MEM "${SYSTEM_PROPS[@]}" $JAVA_OPTS $QPID_OPTS "${JAVA_ARGS[@]}") DISPATCH diff --git a/java/common/src/main/java/common.bnd b/java/common/src/main/java/common.bnd index ef56ecec9e..f12fbf9273 100755 --- a/java/common/src/main/java/common.bnd +++ b/java/common/src/main/java/common.bnd @@ -17,7 +17,7 @@ # under the License.
#
-ver: 0.9.0
+ver: 0.13.0
Bundle-SymbolicName: qpid-common
Bundle-Version: ${ver}
diff --git a/java/common/src/main/java/org/apache/mina/common/FixedSizeByteBufferAllocator.java b/java/common/src/main/java/org/apache/mina/common/FixedSizeByteBufferAllocator.java deleted file mode 100644 index 0c311b6645..0000000000 --- a/java/common/src/main/java/org/apache/mina/common/FixedSizeByteBufferAllocator.java +++ /dev/null @@ -1,467 +0,0 @@ -package org.apache.mina.common; - -import org.apache.mina.common.ByteBuffer; - -import java.nio.*; - -/* -* -* 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. -* -*/ -public class FixedSizeByteBufferAllocator implements ByteBufferAllocator -{ - - - private static final int MINIMUM_CAPACITY = 1; - - public FixedSizeByteBufferAllocator () - { - } - - public ByteBuffer allocate( int capacity, boolean direct ) - { - java.nio.ByteBuffer nioBuffer; - if( direct ) - { - nioBuffer = java.nio.ByteBuffer.allocateDirect( capacity ); - } - else - { - nioBuffer = java.nio.ByteBuffer.allocate( capacity ); - } - return new FixedSizeByteBuffer( nioBuffer ); - } - - public ByteBuffer wrap( java.nio.ByteBuffer nioBuffer ) - { - return new FixedSizeByteBuffer( nioBuffer ); - } - - public void dispose() - { - } - - - - private static final class FixedSizeByteBuffer extends ByteBuffer - { - private java.nio.ByteBuffer buf; - private int mark = -1; - - - protected FixedSizeByteBuffer( java.nio.ByteBuffer buf ) - { - this.buf = buf; - buf.order( ByteOrder.BIG_ENDIAN ); - } - - public synchronized void acquire() - { - } - - public void release() - { - } - - public java.nio.ByteBuffer buf() - { - return buf; - } - - public boolean isPooled() - { - return false; - } - - public void setPooled( boolean pooled ) - { - } - - public ByteBuffer duplicate() { - return new FixedSizeByteBuffer( this.buf.duplicate() ); - } - - public ByteBuffer slice() { - return new FixedSizeByteBuffer( this.buf.slice() ); - } - - public ByteBuffer asReadOnlyBuffer() { - return new FixedSizeByteBuffer( this.buf.asReadOnlyBuffer() ); - } - - public byte[] array() - { - return buf.array(); - } - - public int arrayOffset() - { - return buf.arrayOffset(); - } - - public boolean isDirect() - { - return buf.isDirect(); - } - - public boolean isReadOnly() - { - return buf.isReadOnly(); - } - - public int capacity() - { - return buf.capacity(); - } - - public ByteBuffer capacity( int newCapacity ) - { - if( newCapacity > capacity() ) - { - throw new IllegalArgumentException(); - } - - return this; - } - - - - public boolean isAutoExpand() - { - return false; - } - - public ByteBuffer setAutoExpand( boolean autoExpand ) - { - if(autoExpand) throw new IllegalArgumentException(); - else return this; - } - - public ByteBuffer expand( int pos, int expectedRemaining ) - { - int end = pos + expectedRemaining; - if( end > capacity() ) - { - // The buffer needs expansion. - capacity( end ); - } - - if( end > limit() ) - { - // We call limit() directly to prevent StackOverflowError - buf.limit( end ); - } - return this; - } - - public int position() - { - return buf.position(); - } - - public ByteBuffer position( int newPosition ) - { - - buf.position( newPosition ); - if( mark > newPosition ) - { - mark = -1; - } - return this; - } - - public int limit() - { - return buf.limit(); - } - - public ByteBuffer limit( int newLimit ) - { - buf.limit( newLimit ); - if( mark > newLimit ) - { - mark = -1; - } - return this; - } - - public ByteBuffer mark() - { - buf.mark(); - mark = position(); - return this; - } - - public int markValue() - { - return mark; - } - - public ByteBuffer reset() - { - buf.reset(); - return this; - } - - public ByteBuffer clear() - { - buf.clear(); - mark = -1; - return this; - } - - public ByteBuffer flip() - { - buf.flip(); - mark = -1; - return this; - } - - public ByteBuffer rewind() - { - buf.rewind(); - mark = -1; - return this; - } - - public byte get() - { - return buf.get(); - } - - public ByteBuffer put( byte b ) - { - buf.put( b ); - return this; - } - - public byte get( int index ) - { - return buf.get( index ); - } - - public ByteBuffer put( int index, byte b ) - { - buf.put( index, b ); - return this; - } - - public ByteBuffer get( byte[] dst, int offset, int length ) - { - buf.get( dst, offset, length ); - return this; - } - - public ByteBuffer put( java.nio.ByteBuffer src ) - { - buf.put( src ); - return this; - } - - public ByteBuffer put( byte[] src, int offset, int length ) - { - buf.put( src, offset, length ); - return this; - } - - public ByteBuffer compact() - { - buf.compact(); - mark = -1; - return this; - } - - public ByteOrder order() - { - return buf.order(); - } - - public ByteBuffer order( ByteOrder bo ) - { - buf.order( bo ); - return this; - } - - public char getChar() - { - return buf.getChar(); - } - - public ByteBuffer putChar( char value ) - { - buf.putChar( value ); - return this; - } - - public char getChar( int index ) - { - return buf.getChar( index ); - } - - public ByteBuffer putChar( int index, char value ) - { - buf.putChar( index, value ); - return this; - } - - public CharBuffer asCharBuffer() - { - return buf.asCharBuffer(); - } - - public short getShort() - { - return buf.getShort(); - } - - public ByteBuffer putShort( short value ) - { - buf.putShort( value ); - return this; - } - - public short getShort( int index ) - { - return buf.getShort( index ); - } - - public ByteBuffer putShort( int index, short value ) - { - buf.putShort( index, value ); - return this; - } - - public ShortBuffer asShortBuffer() - { - return buf.asShortBuffer(); - } - - public int getInt() - { - return buf.getInt(); - } - - public ByteBuffer putInt( int value ) - { - buf.putInt( value ); - return this; - } - - public int getInt( int index ) - { - return buf.getInt( index ); - } - - public ByteBuffer putInt( int index, int value ) - { - buf.putInt( index, value ); - return this; - } - - public IntBuffer asIntBuffer() - { - return buf.asIntBuffer(); - } - - public long getLong() - { - return buf.getLong(); - } - - public ByteBuffer putLong( long value ) - { - buf.putLong( value ); - return this; - } - - public long getLong( int index ) - { - return buf.getLong( index ); - } - - public ByteBuffer putLong( int index, long value ) - { - buf.putLong( index, value ); - return this; - } - - public LongBuffer asLongBuffer() - { - return buf.asLongBuffer(); - } - - public float getFloat() - { - return buf.getFloat(); - } - - public ByteBuffer putFloat( float value ) - { - buf.putFloat( value ); - return this; - } - - public float getFloat( int index ) - { - return buf.getFloat( index ); - } - - public ByteBuffer putFloat( int index, float value ) - { - buf.putFloat( index, value ); - return this; - } - - public FloatBuffer asFloatBuffer() - { - return buf.asFloatBuffer(); - } - - public double getDouble() - { - return buf.getDouble(); - } - - public ByteBuffer putDouble( double value ) - { - buf.putDouble( value ); - return this; - } - - public double getDouble( int index ) - { - return buf.getDouble( index ); - } - - public ByteBuffer putDouble( int index, double value ) - { - buf.putDouble( index, value ); - return this; - } - - public DoubleBuffer asDoubleBuffer() - { - return buf.asDoubleBuffer(); - } - - - } - - -} diff --git a/java/common/src/main/java/org/apache/mina/common/support/DefaultIoFuture.java b/java/common/src/main/java/org/apache/mina/common/support/DefaultIoFuture.java deleted file mode 100644 index 4fd28c4eb5..0000000000 --- a/java/common/src/main/java/org/apache/mina/common/support/DefaultIoFuture.java +++ /dev/null @@ -1,227 +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.mina.common.support; - -import org.apache.mina.common.IoFuture; -import org.apache.mina.common.IoSession; -import org.apache.mina.common.IoFutureListener; - -import java.util.List; -import java.util.ArrayList; -import java.util.Iterator; - -/** - * A default implementation of {@link org.apache.mina.common.IoFuture}. - * - * @author The Apache Directory Project (mina-dev@directory.apache.org) - */ -public class DefaultIoFuture implements IoFuture -{ - private final IoSession session; - private final Object lock; - private List listeners; - private Object result; - private boolean ready; - - - /** - * Creates a new instance. - * - * @param session an {@link IoSession} which is associated with this future - */ - public DefaultIoFuture( IoSession session ) - { - this.session = session; - this.lock = this; - } - - /** - * Creates a new instance which uses the specified object as a lock. - */ - public DefaultIoFuture( IoSession session, Object lock ) - { - if( lock == null ) - { - throw new NullPointerException( "lock" ); - } - this.session = session; - this.lock = lock; - } - - public IoSession getSession() - { - return session; - } - - public Object getLock() - { - return lock; - } - - public void join() - { - synchronized( lock ) - { - while( !ready ) - { - try - { - lock.wait(); - } - catch( InterruptedException e ) - { - } - } - } - } - - public boolean join( long timeoutInMillis ) - { - long startTime = ( timeoutInMillis <= 0 ) ? 0 : System - .currentTimeMillis(); - long waitTime = timeoutInMillis; - - synchronized( lock ) - { - if( ready ) - { - return ready; - } - else if( waitTime <= 0 ) - { - return ready; - } - - for( ;; ) - { - try - { - lock.wait( waitTime ); - } - catch( InterruptedException e ) - { - } - - if( ready ) - return true; - else - { - waitTime = timeoutInMillis - ( System.currentTimeMillis() - startTime ); - if( waitTime <= 0 ) - { - return ready; - } - } - } - } - } - - public boolean isReady() - { - synchronized( lock ) - { - return ready; - } - } - - /** - * Sets the result of the asynchronous operation, and mark it as finished. - */ - protected void setValue( Object newValue ) - { - synchronized( lock ) - { - // Allow only once. - if( ready ) - { - return; - } - - result = newValue; - ready = true; - lock.notifyAll(); - - notifyListeners(); - } - } - - /** - * Returns the result of the asynchronous operation. - */ - protected Object getValue() - { - synchronized( lock ) - { - return result; - } - } - - public void addListener( IoFutureListener listener ) - { - if( listener == null ) - { - throw new NullPointerException( "listener" ); - } - - synchronized( lock ) - { - if(listeners == null) - { - listeners = new ArrayList(); - } - listeners.add( listener ); - if( ready ) - { - listener.operationComplete( this ); - } - } - } - - public void removeListener( IoFutureListener listener ) - { - if( listener == null ) - { - throw new NullPointerException( "listener" ); - } - - synchronized( lock ) - { - listeners.remove( listener ); - } - } - - private void notifyListeners() - { - synchronized( lock ) - { - - if(listeners != null) - { - - for( Iterator i = listeners.iterator(); i.hasNext(); ) { - ( ( IoFutureListener ) i.next() ).operationComplete( this ); - } - } - } - } -} - - - diff --git a/java/common/src/main/java/org/apache/mina/common/support/IoServiceListenerSupport.java b/java/common/src/main/java/org/apache/mina/common/support/IoServiceListenerSupport.java deleted file mode 100644 index 5723ffbaa9..0000000000 --- a/java/common/src/main/java/org/apache/mina/common/support/IoServiceListenerSupport.java +++ /dev/null @@ -1,351 +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.mina.common.support; - -import java.net.SocketAddress; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CountDownLatch; - -import org.apache.mina.common.IoAcceptorConfig; -import org.apache.mina.common.IoConnector; -import org.apache.mina.common.IoFuture; -import org.apache.mina.common.IoFutureListener; -import org.apache.mina.common.IoHandler; -import org.apache.mina.common.IoService; -import org.apache.mina.common.IoServiceConfig; -import org.apache.mina.common.IoServiceListener; -import org.apache.mina.common.IoSession; -import org.apache.mina.util.IdentityHashSet; - -/** - * A helper which provides addition and removal of {@link IoServiceListener}s and firing - * events. - * - * @author The Apache Directory Project (mina-dev@directory.apache.org) - * @version $Rev: 446526 $, $Date: 2006-09-15 01:44:11 -0400 (Fri, 15 Sep 2006) $ - */ -public class IoServiceListenerSupport -{ - /** - * A list of {@link IoServiceListener}s. - */ - private final List listeners = new ArrayList(); - - /** - * Tracks managed <tt>serviceAddress</tt>es. - */ - private final Set managedServiceAddresses = new HashSet(); - - /** - * Tracks managed sesssions with <tt>serviceAddress</tt> as a key. - */ - private final Map managedSessions = new HashMap(); - - /** - * Creates a new instance. - */ - public IoServiceListenerSupport() - { - } - - /** - * Adds a new listener. - */ - public void add( IoServiceListener listener ) - { - synchronized( listeners ) - { - listeners.add( listener ); - } - } - - /** - * Removes an existing listener. - */ - public void remove( IoServiceListener listener ) - { - synchronized( listeners ) - { - listeners.remove( listener ); - } - } - - public Set getManagedServiceAddresses() - { - return Collections.unmodifiableSet( managedServiceAddresses ); - } - - public boolean isManaged( SocketAddress serviceAddress ) - { - synchronized( managedServiceAddresses ) - { - return managedServiceAddresses.contains( serviceAddress ); - } - } - - public Set getManagedSessions( SocketAddress serviceAddress ) - { - Set sessions; - synchronized( managedSessions ) - { - sessions = ( Set ) managedSessions.get( serviceAddress ); - if( sessions == null ) - { - sessions = new IdentityHashSet(); - } - } - - synchronized( sessions ) - { - return new IdentityHashSet( sessions ); - } - } - - /** - * Calls {@link IoServiceListener#serviceActivated(IoService, SocketAddress, IoHandler, IoServiceConfig)} - * for all registered listeners. - */ - public void fireServiceActivated( - IoService service, SocketAddress serviceAddress, - IoHandler handler, IoServiceConfig config ) - { - synchronized( managedServiceAddresses ) - { - if( !managedServiceAddresses.add( serviceAddress ) ) - { - return; - } - } - - synchronized( listeners ) - { - for( Iterator i = listeners.iterator(); i.hasNext(); ) - { - ( ( IoServiceListener ) i.next() ).serviceActivated( - service, serviceAddress, handler, config ); - } - } - } - - /** - * Calls {@link IoServiceListener#serviceDeactivated(IoService, SocketAddress, IoHandler, IoServiceConfig)} - * for all registered listeners. - */ - public synchronized void fireServiceDeactivated( - IoService service, SocketAddress serviceAddress, - IoHandler handler, IoServiceConfig config ) - { - synchronized( managedServiceAddresses ) - { - if( !managedServiceAddresses.remove( serviceAddress ) ) - { - return; - } - } - - try - { - synchronized( listeners ) - { - for( Iterator i = listeners.iterator(); i.hasNext(); ) - { - ( ( IoServiceListener ) i.next() ).serviceDeactivated( - service, serviceAddress, handler, config ); - } - } - } - finally - { - disconnectSessions( serviceAddress, config ); - } - } - - - /** - * Calls {@link IoServiceListener#sessionCreated(IoSession)} for all registered listeners. - */ - public void fireSessionCreated( IoSession session ) - { - SocketAddress serviceAddress = session.getServiceAddress(); - - // Get the session set. - boolean firstSession = false; - Set sessions; - synchronized( managedSessions ) - { - sessions = ( Set ) managedSessions.get( serviceAddress ); - if( sessions == null ) - { - sessions = new IdentityHashSet(); - managedSessions.put( serviceAddress, sessions ); - firstSession = true; - } - } - - // If already registered, ignore. - synchronized( sessions ) - { - if ( !sessions.add( session ) ) - { - return; - } - } - - // If the first connector session, fire a virtual service activation event. - if( session.getService() instanceof IoConnector && firstSession ) - { - fireServiceActivated( - session.getService(), session.getServiceAddress(), - session.getHandler(), session.getServiceConfig() ); - } - - // Fire session events. - session.getFilterChain().fireSessionCreated( session ); - session.getFilterChain().fireSessionOpened( session); - - // Fire listener events. - synchronized( listeners ) - { - for( Iterator i = listeners.iterator(); i.hasNext(); ) - { - ( ( IoServiceListener ) i.next() ).sessionCreated( session ); - } - } - } - - /** - * Calls {@link IoServiceListener#sessionDestroyed(IoSession)} for all registered listeners. - */ - public void fireSessionDestroyed( IoSession session ) - { - SocketAddress serviceAddress = session.getServiceAddress(); - - // Get the session set. - Set sessions; - boolean lastSession = false; - synchronized( managedSessions ) - { - sessions = ( Set ) managedSessions.get( serviceAddress ); - // Ignore if unknown. - if( sessions == null ) - { - return; - } - - // Try to remove the remaining empty seession set after removal. - synchronized( sessions ) - { - sessions.remove( session ); - if( sessions.isEmpty() ) - { - managedSessions.remove( serviceAddress ); - lastSession = true; - } - } - } - - // Fire session events. - session.getFilterChain().fireSessionClosed( session ); - - // Fire listener events. - try - { - synchronized( listeners ) - { - for( Iterator i = listeners.iterator(); i.hasNext(); ) - { - ( ( IoServiceListener ) i.next() ).sessionDestroyed( session ); - } - } - } - finally - { - // Fire a virtual service deactivation event for the last session of the connector. - //TODO double-check that this is *STILL* the last session. May not be the case - if( session.getService() instanceof IoConnector && lastSession ) - { - fireServiceDeactivated( - session.getService(), session.getServiceAddress(), - session.getHandler(), session.getServiceConfig() ); - } - } - } - - private void disconnectSessions( SocketAddress serviceAddress, IoServiceConfig config ) - { - if( !( config instanceof IoAcceptorConfig ) ) - { - return; - } - - if( !( ( IoAcceptorConfig ) config ).isDisconnectOnUnbind() ) - { - return; - } - - Set sessions; - synchronized( managedSessions ) - { - sessions = ( Set ) managedSessions.get( serviceAddress ); - } - - if( sessions == null ) - { - return; - } - - Set sessionsCopy; - - // Create a copy to avoid ConcurrentModificationException - synchronized( sessions ) - { - sessionsCopy = new IdentityHashSet( sessions ); - } - - final CountDownLatch latch = new CountDownLatch(sessionsCopy.size()); - - for( Iterator i = sessionsCopy.iterator(); i.hasNext(); ) - { - ( ( IoSession ) i.next() ).close().addListener( new IoFutureListener() - { - public void operationComplete( IoFuture future ) - { - latch.countDown(); - } - } ); - } - - try - { - latch.await(); - } - catch( InterruptedException ie ) - { - // Ignored - } - } -} diff --git a/java/common/src/main/java/org/apache/mina/filter/WriteBufferLimitFilterBuilder.java b/java/common/src/main/java/org/apache/mina/filter/WriteBufferLimitFilterBuilder.java deleted file mode 100644 index 4e9db9071a..0000000000 --- a/java/common/src/main/java/org/apache/mina/filter/WriteBufferLimitFilterBuilder.java +++ /dev/null @@ -1,272 +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.mina.filter; - -import org.apache.mina.common.ByteBuffer; -import org.apache.mina.common.DefaultIoFilterChainBuilder; -import org.apache.mina.common.IoFilterAdapter; -import org.apache.mina.common.IoFilterChain; -import org.apache.mina.common.IoSession; -import org.apache.mina.filter.executor.ExecutorFilter; - -import java.util.Iterator; -import java.util.List; - -/** - * This filter will turn the asynchronous filterWrite method in to a blocking send when there are more than - * the prescribed number of messages awaiting filterWrite. It should be used in conjunction with the - * {@link ReadThrottleFilterBuilder} on a server as the blocking writes will allow the read thread to - * cause an Out of Memory exception due to a back log of unprocessed messages. - * - * This is should only be viewed as a temporary work around for DIRMINA-302. - * - * A true solution should not be implemented as a filter as this issue will always occur. On a machine - * where the network is slower than the local producer. - * - * Suggested improvement is to allow implementation of policices on what to do when buffer is full. - * - * They could be: - * Block - As this does - * Wait on a given Future - to drain more of the queue.. in essence this filter with high/low watermarks - * Throw Exception - through the client filterWrite() method to allow them to get immediate feedback on buffer state - * - * <p/> - * <p>Usage: - * <p/> - * <pre><code> - * DefaultFilterChainBuilder builder = ... - * WriteBufferLimitFilterBuilder filter = new WriteBufferLimitFilterBuilder(); - * filter.attach( builder ); - * </code></pre> - * <p/> - * or - * <p/> - * <pre><code> - * IoFilterChain chain = ... - * WriteBufferLimitFilterBuilder filter = new WriteBufferLimitFilterBuilder(); - * filter.attach( chain ); - * </code></pre> - * - * @author The Apache Directory Project (mina-dev@directory.apache.org) - * @version $Rev: 619823 $, $Date: 2008-02-08 10:09:37 +0000 (Fri, 08 Feb 2008) $ - */ -public class WriteBufferLimitFilterBuilder -{ - public static final String PENDING_SIZE = WriteBufferLimitFilterBuilder.class.getName() + ".pendingSize"; - - private static int DEFAULT_CONNECTION_BUFFER_MESSAGE_COUNT = 5000; - - private volatile boolean throwNotBlock = false; - - private volatile int maximumConnectionBufferCount; - private volatile long maximumConnectionBufferSize; - - private final Object _blockLock = new Object(); - - private int _blockWaiters = 0; - - - public WriteBufferLimitFilterBuilder() - { - this(DEFAULT_CONNECTION_BUFFER_MESSAGE_COUNT); - } - - public WriteBufferLimitFilterBuilder(int maxWriteBufferSize) - { - setMaximumConnectionBufferCount(maxWriteBufferSize); - } - - - /** - * Set the maximum amount pending items in the writeQueue for a given session. - * Changing the value will only take effect when new data is received for a - * connection, including existing connections. Default value is 5000 msgs. - * - * @param maximumConnectionBufferCount New buffer size. Must be > 0 - */ - public void setMaximumConnectionBufferCount(int maximumConnectionBufferCount) - { - this.maximumConnectionBufferCount = maximumConnectionBufferCount; - this.maximumConnectionBufferSize = 0; - } - - public void setMaximumConnectionBufferSize(long maximumConnectionBufferSize) - { - this.maximumConnectionBufferSize = maximumConnectionBufferSize; - this.maximumConnectionBufferCount = 0; - } - - /** - * Attach this filter to the specified filter chain. It will search for the ThreadPoolFilter, and attach itself - * before and after that filter. - * - * @param chain {@link IoFilterChain} to attach self to. - */ - public void attach(IoFilterChain chain) - { - String name = getThreadPoolFilterEntryName(chain.getAll()); - - chain.addBefore(name, getClass().getName() + ".sendlimit", new SendLimit()); - } - - /** - * Attach this filter to the specified builder. It will search for the - * {@link ExecutorFilter}, and attach itself before and after that filter. - * - * @param builder {@link DefaultIoFilterChainBuilder} to attach self to. - */ - public void attach(DefaultIoFilterChainBuilder builder) - { - String name = getThreadPoolFilterEntryName(builder.getAll()); - - builder.addBefore(name, getClass().getName() + ".sendlimit", new SendLimit()); - } - - private String getThreadPoolFilterEntryName(List entries) - { - Iterator i = entries.iterator(); - - while (i.hasNext()) - { - IoFilterChain.Entry entry = (IoFilterChain.Entry) i.next(); - - if (entry.getFilter().getClass().isAssignableFrom(ExecutorFilter.class)) - { - return entry.getName(); - } - } - - throw new IllegalStateException("Chain does not contain a ExecutorFilter"); - } - - - public class SendLimit extends IoFilterAdapter - { - public void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception - { - try - { - waitTillSendAllowed(session); - } - catch (WriteBufferFullExeception wbfe) - { - nextFilter.exceptionCaught(session, wbfe); - } - - if (writeRequest.getMessage() instanceof ByteBuffer) - { - increasePendingWriteSize(session, (ByteBuffer) writeRequest.getMessage()); - } - - nextFilter.filterWrite(session, writeRequest); - } - - private void increasePendingWriteSize(IoSession session, ByteBuffer message) - { - synchronized (session) - { - Long pendingSize = getScheduledWriteBytes(session) + message.remaining(); - session.setAttribute(PENDING_SIZE, pendingSize); - } - } - - private boolean sendAllowed(IoSession session) - { - if (session.isClosing()) - { - return true; - } - - int lmswm = maximumConnectionBufferCount; - long lmswb = maximumConnectionBufferSize; - - return (lmswm == 0 || session.getScheduledWriteRequests() < lmswm) - && (lmswb == 0 || getScheduledWriteBytes(session) < lmswb); - } - - private long getScheduledWriteBytes(IoSession session) - { - synchronized (session) - { - Long i = (Long) session.getAttribute(PENDING_SIZE); - return null == i ? 0 : i; - } - } - - private void waitTillSendAllowed(IoSession session) - { - synchronized (_blockLock) - { - if (throwNotBlock) - { - throw new WriteBufferFullExeception(); - } - - _blockWaiters++; - - while (!sendAllowed(session)) - { - try - { - _blockLock.wait(); - } - catch (InterruptedException e) - { - // Ignore. - } - } - _blockWaiters--; - } - } - - public void messageSent(NextFilter nextFilter, IoSession session, Object message) throws Exception - { - if (message instanceof ByteBuffer) - { - decrementPendingWriteSize(session, (ByteBuffer) message); - } - notifyWaitingWriters(); - nextFilter.messageSent(session, message); - } - - private void decrementPendingWriteSize(IoSession session, ByteBuffer message) - { - synchronized (session) - { - session.setAttribute(PENDING_SIZE, getScheduledWriteBytes(session) - message.remaining()); - } - } - - private void notifyWaitingWriters() - { - synchronized (_blockLock) - { - if (_blockWaiters != 0) - { - _blockLock.notifyAll(); - } - } - - } - - }//SentLimit - - -} diff --git a/java/common/src/main/java/org/apache/mina/filter/codec/OurCumulativeProtocolDecoder.java b/java/common/src/main/java/org/apache/mina/filter/codec/OurCumulativeProtocolDecoder.java deleted file mode 100644 index 3f7e206cb4..0000000000 --- a/java/common/src/main/java/org/apache/mina/filter/codec/OurCumulativeProtocolDecoder.java +++ /dev/null @@ -1,197 +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.mina.filter.codec; - -import org.apache.mina.common.ByteBuffer; -import org.apache.mina.common.IoSession; - -/** - * A {@link ProtocolDecoder} that cumulates the content of received - * buffers to a <em>cumulative buffer</em> to help users implement decoders. - * <p> - * If the received {@link ByteBuffer} is only a part of a message. - * decoders should cumulate received buffers to make a message complete or - * to postpone decoding until more buffers arrive. - * <p> - * Here is an example decoder that decodes CRLF terminated lines into - * <code>Command</code> objects: - * <pre> - * public class CRLFTerminatedCommandLineDecoder - * extends CumulativeProtocolDecoder { - * - * private Command parseCommand(ByteBuffer in) { - * // Convert the bytes in the specified buffer to a - * // Command object. - * ... - * } - * - * protected boolean doDecode(IoSession session, ByteBuffer in, - * ProtocolDecoderOutput out) - * throws Exception { - * - * // Remember the initial position. - * int start = in.position(); - * - * // Now find the first CRLF in the buffer. - * byte previous = 0; - * while (in.hasRemaining()) { - * byte current = in.get(); - * - * if (previous == '\r' && current == '\n') { - * // Remember the current position and limit. - * int position = in.position(); - * int limit = in.limit(); - * try { - * in.position(start); - * in.limit(position); - * // The bytes between in.position() and in.limit() - * // now contain a full CRLF terminated line. - * out.write(parseCommand(in.slice())); - * } finally { - * // Set the position to point right after the - * // detected line and set the limit to the old - * // one. - * in.position(position); - * in.limit(limit); - * } - * // Decoded one line; CumulativeProtocolDecoder will - * // call me again until I return false. So just - * // return true until there are no more lines in the - * // buffer. - * return true; - * } - * - * previous = current; - * } - * - * // Could not find CRLF in the buffer. Reset the initial - * // position to the one we recorded above. - * in.position(start); - * - * return false; - * } - * } - * </pre> - * - * @author The Apache Directory Project (mina-dev@directory.apache.org) - * @version $Rev: 619823 $, $Date: 2008-02-08 10:09:37 +0000 (Fri, 08 Feb 2008) $ - */ -public abstract class OurCumulativeProtocolDecoder extends ProtocolDecoderAdapter { - - private static final String BUFFER = OurCumulativeProtocolDecoder.class - .getName() - + ".Buffer"; - - /** - * Creates a new instance. - */ - protected OurCumulativeProtocolDecoder() { - } - - /** - * Cumulates content of <tt>in</tt> into internal buffer and forwards - * decoding request to {@link #doDecode(IoSession, ByteBuffer, ProtocolDecoderOutput)}. - * <tt>doDecode()</tt> is invoked repeatedly until it returns <tt>false</tt> - * and the cumulative buffer is NOT compacted after decoding ends. - * - * @throws IllegalStateException if your <tt>doDecode()</tt> returned - * <tt>true</tt> not consuming the cumulative buffer. - */ - public void decode(IoSession session, ByteBuffer in, - ProtocolDecoderOutput out) throws Exception { - boolean usingSessionBuffer = true; - ByteBuffer buf = (ByteBuffer) session.getAttribute(BUFFER); - // If we have a session buffer, append data to that; otherwise - // use the buffer read from the network directly. - if (buf != null) { - buf.put(in); - buf.flip(); - } else { - buf = in; - usingSessionBuffer = false; - } - - for (;;) { - int oldPos = buf.position(); - boolean decoded = doDecode(session, buf, out); - if (decoded) { - if (buf.position() == oldPos) { - throw new IllegalStateException( - "doDecode() can't return true when buffer is not consumed."); - } - - if (!buf.hasRemaining()) { - break; - } - } else { - break; - } - } - - - // if there is any data left that cannot be decoded, we store - // it in a buffer in the session and next time this decoder is - // invoked the session buffer gets appended to - if (buf.hasRemaining()) { - storeRemainingInSession(buf, session); - } else { - if (usingSessionBuffer) - removeSessionBuffer(session); - } - } - - /** - * Implement this method to consume the specified cumulative buffer and - * decode its content into message(s). - * - * @param in the cumulative buffer - * @return <tt>true</tt> if and only if there's more to decode in the buffer - * and you want to have <tt>doDecode</tt> method invoked again. - * Return <tt>false</tt> if remaining data is not enough to decode, - * then this method will be invoked again when more data is cumulated. - * @throws Exception if cannot decode <tt>in</tt>. - */ - protected abstract boolean doDecode(IoSession session, ByteBuffer in, - ProtocolDecoderOutput out) throws Exception; - - /** - * Releases the cumulative buffer used by the specified <tt>session</tt>. - * Please don't forget to call <tt>super.dispose( session )</tt> when - * you override this method. - */ - public void dispose(IoSession session) throws Exception { - removeSessionBuffer(session); - } - - private void removeSessionBuffer(IoSession session) { - ByteBuffer buf = (ByteBuffer) session.removeAttribute(BUFFER); - if (buf != null) { - buf.release(); - } - } - - private void storeRemainingInSession(ByteBuffer buf, IoSession session) { - ByteBuffer remainingBuf = ByteBuffer.allocate(buf.capacity()); - remainingBuf.setAutoExpand(true); - remainingBuf.order(buf.order()); - remainingBuf.put(buf); - session.setAttribute(BUFFER, remainingBuf); - } -} diff --git a/java/common/src/main/java/org/apache/mina/filter/codec/QpidProtocolCodecFilter.java b/java/common/src/main/java/org/apache/mina/filter/codec/QpidProtocolCodecFilter.java deleted file mode 100644 index b8c6f29720..0000000000 --- a/java/common/src/main/java/org/apache/mina/filter/codec/QpidProtocolCodecFilter.java +++ /dev/null @@ -1,440 +0,0 @@ -package org.apache.mina.filter.codec; - - -/* -* -* 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 org.apache.mina.common.*; -import org.apache.mina.common.support.DefaultWriteFuture; -import org.apache.mina.filter.codec.support.SimpleProtocolDecoderOutput; -import org.apache.mina.util.SessionLog; -import org.apache.mina.util.Queue; - - -public class QpidProtocolCodecFilter extends IoFilterAdapter -{ - public static final String ENCODER = QpidProtocolCodecFilter.class.getName() + ".encoder"; - public static final String DECODER = QpidProtocolCodecFilter.class.getName() + ".decoder"; - - private static final Class[] EMPTY_PARAMS = new Class[0]; - private static final ByteBuffer EMPTY_BUFFER = ByteBuffer.wrap( new byte[0] ); - - private final ProtocolCodecFactory factory; - - public QpidProtocolCodecFilter( ProtocolCodecFactory factory ) - { - if( factory == null ) - { - throw new NullPointerException( "factory" ); - } - this.factory = factory; - } - - public QpidProtocolCodecFilter( final ProtocolEncoder encoder, final ProtocolDecoder decoder ) - { - if( encoder == null ) - { - throw new NullPointerException( "encoder" ); - } - if( decoder == null ) - { - throw new NullPointerException( "decoder" ); - } - - this.factory = new ProtocolCodecFactory() - { - public ProtocolEncoder getEncoder() - { - return encoder; - } - - public ProtocolDecoder getDecoder() - { - return decoder; - } - }; - } - - public QpidProtocolCodecFilter( final Class encoderClass, final Class decoderClass ) - { - if( encoderClass == null ) - { - throw new NullPointerException( "encoderClass" ); - } - if( decoderClass == null ) - { - throw new NullPointerException( "decoderClass" ); - } - if( !ProtocolEncoder.class.isAssignableFrom( encoderClass ) ) - { - throw new IllegalArgumentException( "encoderClass: " + encoderClass.getName() ); - } - if( !ProtocolDecoder.class.isAssignableFrom( decoderClass ) ) - { - throw new IllegalArgumentException( "decoderClass: " + decoderClass.getName() ); - } - try - { - encoderClass.getConstructor( EMPTY_PARAMS ); - } - catch( NoSuchMethodException e ) - { - throw new IllegalArgumentException( "encoderClass doesn't have a public default constructor." ); - } - try - { - decoderClass.getConstructor( EMPTY_PARAMS ); - } - catch( NoSuchMethodException e ) - { - throw new IllegalArgumentException( "decoderClass doesn't have a public default constructor." ); - } - - this.factory = new ProtocolCodecFactory() - { - public ProtocolEncoder getEncoder() throws Exception - { - return ( ProtocolEncoder ) encoderClass.newInstance(); - } - - public ProtocolDecoder getDecoder() throws Exception - { - return ( ProtocolDecoder ) decoderClass.newInstance(); - } - }; - } - - public void onPreAdd( IoFilterChain parent, String name, IoFilter.NextFilter nextFilter ) throws Exception - { - if( parent.contains( ProtocolCodecFilter.class ) ) - { - throw new IllegalStateException( "A filter chain cannot contain more than one QpidProtocolCodecFilter." ); - } - } - - public void messageReceived( IoFilter.NextFilter nextFilter, IoSession session, Object message ) throws Exception - { - if( !( message instanceof ByteBuffer ) ) - { - nextFilter.messageReceived( session, message ); - return; - } - - ByteBuffer in = ( ByteBuffer ) message; - ProtocolDecoder decoder = getDecoder( session ); - ProtocolDecoderOutput decoderOut = getDecoderOut( session, nextFilter ); - - try - { - decoder.decode( session, in, decoderOut ); - } - catch( Throwable t ) - { - ProtocolDecoderException pde; - if( t instanceof ProtocolDecoderException ) - { - pde = ( ProtocolDecoderException ) t; - } - else - { - pde = new ProtocolDecoderException( t ); - } - pde.setHexdump( in.getHexDump() ); - throw pde; - } - finally - { - // Dispose the decoder if this session is connectionless. - if( session.getTransportType().isConnectionless() ) - { - disposeDecoder( session ); - } - - // Release the read buffer. - in.release(); - - decoderOut.flush(); - } - } - - public void messageSent( IoFilter.NextFilter nextFilter, IoSession session, Object message ) throws Exception - { - if( message instanceof HiddenByteBuffer ) - { - return; - } - - if( !( message instanceof MessageByteBuffer ) ) - { - nextFilter.messageSent( session, message ); - return; - } - - nextFilter.messageSent( session, ( ( MessageByteBuffer ) message ).message ); - } - - public void filterWrite( IoFilter.NextFilter nextFilter, IoSession session, IoFilter.WriteRequest writeRequest ) throws Exception - { - Object message = writeRequest.getMessage(); - if( message instanceof ByteBuffer ) - { - nextFilter.filterWrite( session, writeRequest ); - return; - } - - ProtocolEncoder encoder = getEncoder( session ); - ProtocolEncoderOutputImpl encoderOut = getEncoderOut( session, nextFilter, writeRequest ); - - try - { - encoder.encode( session, message, encoderOut ); - encoderOut.flush(); - nextFilter.filterWrite( - session, - new IoFilter.WriteRequest( - new MessageByteBuffer( writeRequest.getMessage() ), - writeRequest.getFuture(), writeRequest.getDestination() ) ); - } - catch( Throwable t ) - { - ProtocolEncoderException pee; - if( t instanceof ProtocolEncoderException ) - { - pee = ( ProtocolEncoderException ) t; - } - else - { - pee = new ProtocolEncoderException( t ); - } - throw pee; - } - finally - { - // Dispose the encoder if this session is connectionless. - if( session.getTransportType().isConnectionless() ) - { - disposeEncoder( session ); - } - } - } - - public void sessionClosed( IoFilter.NextFilter nextFilter, IoSession session ) throws Exception - { - // Call finishDecode() first when a connection is closed. - ProtocolDecoder decoder = getDecoder( session ); - ProtocolDecoderOutput decoderOut = getDecoderOut( session, nextFilter ); - try - { - decoder.finishDecode( session, decoderOut ); - } - catch( Throwable t ) - { - ProtocolDecoderException pde; - if( t instanceof ProtocolDecoderException ) - { - pde = ( ProtocolDecoderException ) t; - } - else - { - pde = new ProtocolDecoderException( t ); - } - throw pde; - } - finally - { - // Dispose all. - disposeEncoder( session ); - disposeDecoder( session ); - - decoderOut.flush(); - } - - nextFilter.sessionClosed( session ); - } - - private ProtocolEncoder getEncoder( IoSession session ) throws Exception - { - ProtocolEncoder encoder = ( ProtocolEncoder ) session.getAttribute( ENCODER ); - if( encoder == null ) - { - encoder = factory.getEncoder(); - session.setAttribute( ENCODER, encoder ); - } - return encoder; - } - - private ProtocolEncoderOutputImpl getEncoderOut( IoSession session, IoFilter.NextFilter nextFilter, IoFilter.WriteRequest writeRequest ) - { - return new ProtocolEncoderOutputImpl( session, nextFilter, writeRequest ); - } - - private ProtocolDecoder getDecoder( IoSession session ) throws Exception - { - ProtocolDecoder decoder = ( ProtocolDecoder ) session.getAttribute( DECODER ); - if( decoder == null ) - { - decoder = factory.getDecoder(); - session.setAttribute( DECODER, decoder ); - } - return decoder; - } - - private ProtocolDecoderOutput getDecoderOut( IoSession session, IoFilter.NextFilter nextFilter ) - { - return new SimpleProtocolDecoderOutput( session, nextFilter ); - } - - private void disposeEncoder( IoSession session ) - { - ProtocolEncoder encoder = ( ProtocolEncoder ) session.removeAttribute( ENCODER ); - if( encoder == null ) - { - return; - } - - try - { - encoder.dispose( session ); - } - catch( Throwable t ) - { - SessionLog.warn( - session, - "Failed to dispose: " + encoder.getClass().getName() + - " (" + encoder + ')' ); - } - } - - private void disposeDecoder( IoSession session ) - { - ProtocolDecoder decoder = ( ProtocolDecoder ) session.removeAttribute( DECODER ); - if( decoder == null ) - { - return; - } - - try - { - decoder.dispose( session ); - } - catch( Throwable t ) - { - SessionLog.warn( - session, - "Falied to dispose: " + decoder.getClass().getName() + - " (" + decoder + ')' ); - } - } - - private static class HiddenByteBuffer extends ByteBufferProxy - { - private HiddenByteBuffer( ByteBuffer buf ) - { - super( buf ); - } - } - - private static class MessageByteBuffer extends ByteBufferProxy - { - private final Object message; - - private MessageByteBuffer( Object message ) - { - super( EMPTY_BUFFER ); - this.message = message; - } - - public void acquire() - { - // no-op since we are wraping a zero-byte buffer, this instance is to just curry the message - } - - public void release() - { - // no-op since we are wraping a zero-byte buffer, this instance is to just curry the message - } - } - - private static class ProtocolEncoderOutputImpl implements ProtocolEncoderOutput - { - private ByteBuffer buffer; - - private final IoSession session; - private final IoFilter.NextFilter nextFilter; - private final IoFilter.WriteRequest writeRequest; - - public ProtocolEncoderOutputImpl( IoSession session, IoFilter.NextFilter nextFilter, IoFilter.WriteRequest writeRequest ) - { - this.session = session; - this.nextFilter = nextFilter; - this.writeRequest = writeRequest; - } - - - - public void write( ByteBuffer buf ) - { - if(buffer != null) - { - flush(); - } - buffer = buf; - } - - public void mergeAll() - { - } - - public WriteFuture flush() - { - WriteFuture future = null; - if( buffer == null ) - { - return null; - } - else - { - ByteBuffer buf = buffer; - // Flush only when the buffer has remaining. - if( buf.hasRemaining() ) - { - future = doFlush( buf ); - } - - } - - return future; - } - - - protected WriteFuture doFlush( ByteBuffer buf ) - { - WriteFuture future = new DefaultWriteFuture( session ); - nextFilter.filterWrite( - session, - new IoFilter.WriteRequest( - buf, - future, writeRequest.getDestination() ) ); - return future; - } - } -} - diff --git a/java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketAcceptor.java b/java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketAcceptor.java deleted file mode 100644 index e5360d32e0..0000000000 --- a/java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketAcceptor.java +++ /dev/null @@ -1,547 +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.mina.transport.socket.nio; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.nio.channels.SelectionKey; -import java.nio.channels.Selector; -import java.nio.channels.ServerSocketChannel; -import java.nio.channels.SocketChannel; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.apache.mina.common.ExceptionMonitor; -import org.apache.mina.common.IoAcceptor; -import org.apache.mina.common.IoHandler; -import org.apache.mina.common.IoServiceConfig; -import org.apache.mina.common.support.BaseIoAcceptor; -import org.apache.mina.util.Queue; -import org.apache.mina.util.NewThreadExecutor; -import org.apache.mina.util.NamePreservingRunnable; -import edu.emory.mathcs.backport.java.util.concurrent.Executor; - -/** - * {@link IoAcceptor} for socket transport (TCP/IP). - * - * @author The Apache Directory Project (mina-dev@directory.apache.org) - * @version $Rev: 619823 $, $Date: 2008-02-08 10:09:37 +0000 (Fri, 08 Feb 2008) $ - */ -public class MultiThreadSocketAcceptor extends SocketAcceptor -{ - /** - * @noinspection StaticNonFinalField - */ - private static volatile int nextId = 0; - - private final Executor executor; - private final Object lock = new Object(); - private final int id = nextId ++; - private final String threadName = "SocketAcceptor-" + id; - private final Map channels = new HashMap(); - - private final Queue registerQueue = new Queue(); - private final Queue cancelQueue = new Queue(); - - private final MultiThreadSocketIoProcessor[] ioProcessors; - private final int processorCount; - - /** - * @noinspection FieldAccessedSynchronizedAndUnsynchronized - */ - private Selector selector; - private Worker worker; - private int processorDistributor = 0; - - /** - * Create an acceptor with a single processing thread using a NewThreadExecutor - */ - public MultiThreadSocketAcceptor() - { - this( 1, new NewThreadExecutor() ); - } - - /** - * Create an acceptor with the desired number of processing threads - * - * @param processorCount Number of processing threads - * @param executor Executor to use for launching threads - */ - public MultiThreadSocketAcceptor( int processorCount, Executor executor ) - { - if( processorCount < 1 ) - { - throw new IllegalArgumentException( "Must have at least one processor" ); - } - - this.executor = executor; - this.processorCount = processorCount; - ioProcessors = new MultiThreadSocketIoProcessor[processorCount]; - - for( int i = 0; i < processorCount; i++ ) - { - ioProcessors[i] = new MultiThreadSocketIoProcessor( "SocketAcceptorIoProcessor-" + id + "." + i, executor ); - } - } - - - /** - * Binds to the specified <code>address</code> and handles incoming connections with the specified - * <code>handler</code>. Backlog value is configured to the value of <code>backlog</code> property. - * - * @throws IOException if failed to bind - */ - public void bind( SocketAddress address, IoHandler handler, IoServiceConfig config ) throws IOException - { - if( handler == null ) - { - throw new NullPointerException( "handler" ); - } - - if( address != null && !( address instanceof InetSocketAddress ) ) - { - throw new IllegalArgumentException( "Unexpected address type: " + address.getClass() ); - } - - if( config == null ) - { - config = getDefaultConfig(); - } - - RegistrationRequest request = new RegistrationRequest( address, handler, config ); - - synchronized( registerQueue ) - { - registerQueue.push( request ); - } - - startupWorker(); - - selector.wakeup(); - - synchronized( request ) - { - while( !request.done ) - { - try - { - request.wait(); - } - catch( InterruptedException e ) - { - ExceptionMonitor.getInstance().exceptionCaught( e ); - } - } - } - - if( request.exception != null ) - { - throw request.exception; - } - } - - - private synchronized void startupWorker() throws IOException - { - synchronized( lock ) - { - if( worker == null ) - { - selector = Selector.open(); - worker = new Worker(); - - executor.execute( new NamePreservingRunnable( worker ) ); - } - } - } - - public void unbind( SocketAddress address ) - { - if( address == null ) - { - throw new NullPointerException( "address" ); - } - - CancellationRequest request = new CancellationRequest( address ); - - try - { - startupWorker(); - } - catch( IOException e ) - { - // IOException is thrown only when Worker thread is not - // running and failed to open a selector. We simply throw - // IllegalArgumentException here because we can simply - // conclude that nothing is bound to the selector. - throw new IllegalArgumentException( "Address not bound: " + address ); - } - - synchronized( cancelQueue ) - { - cancelQueue.push( request ); - } - - selector.wakeup(); - - synchronized( request ) - { - while( !request.done ) - { - try - { - request.wait(); - } - catch( InterruptedException e ) - { - ExceptionMonitor.getInstance().exceptionCaught( e ); - } - } - } - - if( request.exception != null ) - { - request.exception.fillInStackTrace(); - - throw request.exception; - } - } - - - private class Worker implements Runnable - { - public void run() - { - Thread.currentThread().setName(MultiThreadSocketAcceptor.this.threadName ); - - for( ; ; ) - { - try - { - int nKeys = selector.select(); - - registerNew(); - - if( nKeys > 0 ) - { - processSessions( selector.selectedKeys() ); - } - - cancelKeys(); - - if( selector.keys().isEmpty() ) - { - synchronized( lock ) - { - if( selector.keys().isEmpty() && - registerQueue.isEmpty() && - cancelQueue.isEmpty() ) - { - worker = null; - try - { - selector.close(); - } - catch( IOException e ) - { - ExceptionMonitor.getInstance().exceptionCaught( e ); - } - finally - { - selector = null; - } - break; - } - } - } - } - catch( IOException e ) - { - ExceptionMonitor.getInstance().exceptionCaught( e ); - - try - { - Thread.sleep( 1000 ); - } - catch( InterruptedException e1 ) - { - ExceptionMonitor.getInstance().exceptionCaught( e1 ); - } - } - } - } - - private void processSessions( Set keys ) throws IOException - { - Iterator it = keys.iterator(); - while( it.hasNext() ) - { - SelectionKey key = ( SelectionKey ) it.next(); - - it.remove(); - - if( !key.isAcceptable() ) - { - continue; - } - - ServerSocketChannel ssc = ( ServerSocketChannel ) key.channel(); - - SocketChannel ch = ssc.accept(); - - if( ch == null ) - { - continue; - } - - boolean success = false; - try - { - - RegistrationRequest req = ( RegistrationRequest ) key.attachment(); - - MultiThreadSocketSessionImpl session = new MultiThreadSocketSessionImpl( - MultiThreadSocketAcceptor.this, nextProcessor(), getListeners(), - req.config, ch, req.handler, req.address ); - - // New Interface -// SocketSessionImpl session = new SocketSessionImpl( -// SocketAcceptor.this, nextProcessor(), getListeners(), -// req.config, ch, req.handler, req.address ); - - - getFilterChainBuilder().buildFilterChain( session.getFilterChain() ); - req.config.getFilterChainBuilder().buildFilterChain( session.getFilterChain() ); - req.config.getThreadModel().buildFilterChain( session.getFilterChain() ); - session.getIoProcessor().addNew( session ); - success = true; - } - catch( Throwable t ) - { - ExceptionMonitor.getInstance().exceptionCaught( t ); - } - finally - { - if( !success ) - { - ch.close(); - } - } - } - } - } - - private MultiThreadSocketIoProcessor nextProcessor() - { - return ioProcessors[processorDistributor++ % processorCount]; - } - - - private void registerNew() - { - if( registerQueue.isEmpty() ) - { - return; - } - - for( ; ; ) - { - RegistrationRequest req; - - synchronized( registerQueue ) - { - req = ( RegistrationRequest ) registerQueue.pop(); - } - - if( req == null ) - { - break; - } - - ServerSocketChannel ssc = null; - - try - { - ssc = ServerSocketChannel.open(); - ssc.configureBlocking( false ); - - // Configure the server socket, - SocketAcceptorConfig cfg; - if( req.config instanceof SocketAcceptorConfig ) - { - cfg = ( SocketAcceptorConfig ) req.config; - } - else - { - cfg = ( SocketAcceptorConfig ) getDefaultConfig(); - } - - ssc.socket().setReuseAddress( cfg.isReuseAddress() ); - ssc.socket().setReceiveBufferSize( - ( ( SocketSessionConfig ) cfg.getSessionConfig() ).getReceiveBufferSize() ); - - // and bind. - ssc.socket().bind( req.address, cfg.getBacklog() ); - if( req.address == null || req.address.getPort() == 0 ) - { - req.address = ( InetSocketAddress ) ssc.socket().getLocalSocketAddress(); - } - ssc.register( selector, SelectionKey.OP_ACCEPT, req ); - - synchronized( channels ) - { - channels.put( req.address, ssc ); - } - - getListeners().fireServiceActivated( - this, req.address, req.handler, req.config ); - } - catch( IOException e ) - { - req.exception = e; - } - finally - { - synchronized( req ) - { - req.done = true; - - req.notifyAll(); - } - - if( ssc != null && req.exception != null ) - { - try - { - ssc.close(); - } - catch( IOException e ) - { - ExceptionMonitor.getInstance().exceptionCaught( e ); - } - } - } - } - } - - - private void cancelKeys() - { - if( cancelQueue.isEmpty() ) - { - return; - } - - for( ; ; ) - { - CancellationRequest request; - - synchronized( cancelQueue ) - { - request = ( CancellationRequest ) cancelQueue.pop(); - } - - if( request == null ) - { - break; - } - - ServerSocketChannel ssc; - synchronized( channels ) - { - ssc = ( ServerSocketChannel ) channels.remove( request.address ); - } - - // close the channel - try - { - if( ssc == null ) - { - request.exception = new IllegalArgumentException( "Address not bound: " + request.address ); - } - else - { - SelectionKey key = ssc.keyFor( selector ); - request.registrationRequest = ( RegistrationRequest ) key.attachment(); - key.cancel(); - - selector.wakeup(); // wake up again to trigger thread death - - ssc.close(); - } - } - catch( IOException e ) - { - ExceptionMonitor.getInstance().exceptionCaught( e ); - } - finally - { - synchronized( request ) - { - request.done = true; - request.notifyAll(); - } - - if( request.exception == null ) - { - getListeners().fireServiceDeactivated( - this, request.address, - request.registrationRequest.handler, - request.registrationRequest.config ); - } - } - } - } - - private static class RegistrationRequest - { - private InetSocketAddress address; - private final IoHandler handler; - private final IoServiceConfig config; - private IOException exception; - private boolean done; - - private RegistrationRequest( SocketAddress address, IoHandler handler, IoServiceConfig config ) - { - this.address = ( InetSocketAddress ) address; - this.handler = handler; - this.config = config; - } - } - - - private static class CancellationRequest - { - private final SocketAddress address; - private boolean done; - private RegistrationRequest registrationRequest; - private RuntimeException exception; - - private CancellationRequest( SocketAddress address ) - { - this.address = address; - } - } -} diff --git a/java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketConnector.java b/java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketConnector.java deleted file mode 100644 index 7344f70078..0000000000 --- a/java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketConnector.java +++ /dev/null @@ -1,486 +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.mina.transport.socket.nio; - -import edu.emory.mathcs.backport.java.util.concurrent.Executor; -import org.apache.mina.common.ConnectFuture; -import org.apache.mina.common.ExceptionMonitor; -import org.apache.mina.common.IoConnector; -import org.apache.mina.common.IoConnectorConfig; -import org.apache.mina.common.IoHandler; -import org.apache.mina.common.IoServiceConfig; -import org.apache.mina.common.support.AbstractIoFilterChain; -import org.apache.mina.common.support.DefaultConnectFuture; -import org.apache.mina.util.NamePreservingRunnable; -import org.apache.mina.util.NewThreadExecutor; -import org.apache.mina.util.Queue; - -import java.io.IOException; -import java.net.ConnectException; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.nio.channels.SelectionKey; -import java.nio.channels.Selector; -import java.nio.channels.SocketChannel; -import java.util.Iterator; -import java.util.Set; - -/** - * {@link IoConnector} for socket transport (TCP/IP). - * - * @author The Apache Directory Project (mina-dev@directory.apache.org) - * @version $Rev: 619823 $, $Date: 2008-02-08 10:09:37 +0000 (Fri, 08 Feb 2008) $ - */ -public class MultiThreadSocketConnector extends SocketConnector -{ - /** @noinspection StaticNonFinalField */ - private static volatile int nextId = 0; - - private final Object lock = new Object(); - private final int id = nextId++; - private final String threadName = "SocketConnector-" + id; - - private final Queue connectQueue = new Queue(); - private final MultiThreadSocketIoProcessor[] ioProcessors; - private final int processorCount; - private final Executor executor; - - /** @noinspection FieldAccessedSynchronizedAndUnsynchronized */ - private Selector selector; - private Worker worker; - private int processorDistributor = 0; - private int workerTimeout = 60; // 1 min. - - /** Create a connector with a single processing thread using a NewThreadExecutor */ - public MultiThreadSocketConnector() - { - this(1, new NewThreadExecutor()); - } - - /** - * Create a connector with the desired number of processing threads - * - * @param processorCount Number of processing threads - * @param executor Executor to use for launching threads - */ - public MultiThreadSocketConnector(int processorCount, Executor executor) - { - if (processorCount < 1) - { - throw new IllegalArgumentException("Must have at least one processor"); - } - - this.executor = executor; - this.processorCount = processorCount; - ioProcessors = new MultiThreadSocketIoProcessor[processorCount]; - - for (int i = 0; i < processorCount; i++) - { - ioProcessors[i] = new MultiThreadSocketIoProcessor("SocketConnectorIoProcessor-" + id + "." + i, executor); - } - } - - /** - * How many seconds to keep the connection thread alive between connection requests - * - * @return Number of seconds to keep connection thread alive - */ - public int getWorkerTimeout() - { - return workerTimeout; - } - - /** - * Set how many seconds the connection worker thread should remain alive once idle before terminating itself. - * - * @param workerTimeout Number of seconds to keep thread alive. Must be >=0 - */ - public void setWorkerTimeout(int workerTimeout) - { - if (workerTimeout < 0) - { - throw new IllegalArgumentException("Must be >= 0"); - } - this.workerTimeout = workerTimeout; - } - - public ConnectFuture connect(SocketAddress address, IoHandler handler, IoServiceConfig config) - { - return connect(address, null, handler, config); - } - - public ConnectFuture connect(SocketAddress address, SocketAddress localAddress, - IoHandler handler, IoServiceConfig config) - { - if (address == null) - { - throw new NullPointerException("address"); - } - if (handler == null) - { - throw new NullPointerException("handler"); - } - - if (!(address instanceof InetSocketAddress)) - { - throw new IllegalArgumentException("Unexpected address type: " - + address.getClass()); - } - - if (localAddress != null && !(localAddress instanceof InetSocketAddress)) - { - throw new IllegalArgumentException("Unexpected local address type: " - + localAddress.getClass()); - } - - if (config == null) - { - config = getDefaultConfig(); - } - - SocketChannel ch = null; - boolean success = false; - try - { - ch = SocketChannel.open(); - ch.socket().setReuseAddress(true); - if (localAddress != null) - { - ch.socket().bind(localAddress); - } - - ch.configureBlocking(false); - - if (ch.connect(address)) - { - DefaultConnectFuture future = new DefaultConnectFuture(); - newSession(ch, handler, config, future); - success = true; - return future; - } - - success = true; - } - catch (IOException e) - { - return DefaultConnectFuture.newFailedFuture(e); - } - finally - { - if (!success && ch != null) - { - try - { - ch.close(); - } - catch (IOException e) - { - ExceptionMonitor.getInstance().exceptionCaught(e); - } - } - } - - ConnectionRequest request = new ConnectionRequest(ch, handler, config); - synchronized (lock) - { - try - { - startupWorker(); - } - catch (IOException e) - { - try - { - ch.close(); - } - catch (IOException e2) - { - ExceptionMonitor.getInstance().exceptionCaught(e2); - } - - return DefaultConnectFuture.newFailedFuture(e); - } - } - - synchronized (connectQueue) - { - connectQueue.push(request); - } - selector.wakeup(); - - return request; - } - - private synchronized void startupWorker() throws IOException - { - if (worker == null) - { - selector = Selector.open(); - worker = new Worker(); - executor.execute(new NamePreservingRunnable(worker)); - } - } - - private void registerNew() - { - if (connectQueue.isEmpty()) - { - return; - } - - for (; ;) - { - ConnectionRequest req; - synchronized (connectQueue) - { - req = (ConnectionRequest) connectQueue.pop(); - } - - if (req == null) - { - break; - } - - SocketChannel ch = req.channel; - try - { - ch.register(selector, SelectionKey.OP_CONNECT, req); - } - catch (IOException e) - { - req.setException(e); - } - } - } - - private void processSessions(Set keys) - { - Iterator it = keys.iterator(); - - while (it.hasNext()) - { - SelectionKey key = (SelectionKey) it.next(); - - if (!key.isConnectable()) - { - continue; - } - - SocketChannel ch = (SocketChannel) key.channel(); - ConnectionRequest entry = (ConnectionRequest) key.attachment(); - - boolean success = false; - try - { - ch.finishConnect(); - newSession(ch, entry.handler, entry.config, entry); - success = true; - } - catch (Throwable e) - { - entry.setException(e); - } - finally - { - key.cancel(); - if (!success) - { - try - { - ch.close(); - } - catch (IOException e) - { - ExceptionMonitor.getInstance().exceptionCaught(e); - } - } - } - } - - keys.clear(); - } - - private void processTimedOutSessions(Set keys) - { - long currentTime = System.currentTimeMillis(); - Iterator it = keys.iterator(); - - while (it.hasNext()) - { - SelectionKey key = (SelectionKey) it.next(); - - if (!key.isValid()) - { - continue; - } - - ConnectionRequest entry = (ConnectionRequest) key.attachment(); - - if (currentTime >= entry.deadline) - { - entry.setException(new ConnectException()); - try - { - key.channel().close(); - } - catch (IOException e) - { - ExceptionMonitor.getInstance().exceptionCaught(e); - } - finally - { - key.cancel(); - } - } - } - } - - private void newSession(SocketChannel ch, IoHandler handler, IoServiceConfig config, ConnectFuture connectFuture) - throws IOException - { - MultiThreadSocketSessionImpl session = - new MultiThreadSocketSessionImpl(this, nextProcessor(), getListeners(), - config, ch, handler, ch.socket().getRemoteSocketAddress()); - - //new interface -// SocketSessionImpl session = new SocketSessionImpl( -// this, nextProcessor(), getListeners(), -// config, ch, handler, ch.socket().getRemoteSocketAddress() ); - try - { - getFilterChainBuilder().buildFilterChain(session.getFilterChain()); - config.getFilterChainBuilder().buildFilterChain(session.getFilterChain()); - config.getThreadModel().buildFilterChain(session.getFilterChain()); - } - catch (Throwable e) - { - throw (IOException) new IOException("Failed to create a session.").initCause(e); - } - - // Set the ConnectFuture of the specified session, which will be - // removed and notified by AbstractIoFilterChain eventually. - session.setAttribute( AbstractIoFilterChain.CONNECT_FUTURE, connectFuture ); - - // Forward the remaining process to the SocketIoProcessor. - session.getIoProcessor().addNew(session); - } - - private MultiThreadSocketIoProcessor nextProcessor() - { - return ioProcessors[processorDistributor++ % processorCount]; - } - - private class Worker implements Runnable - { - private long lastActive = System.currentTimeMillis(); - - public void run() - { - Thread.currentThread().setName(MultiThreadSocketConnector.this.threadName); - - for (; ;) - { - try - { - int nKeys = selector.select(1000); - - registerNew(); - - if (nKeys > 0) - { - processSessions(selector.selectedKeys()); - } - - processTimedOutSessions(selector.keys()); - - if (selector.keys().isEmpty()) - { - if (System.currentTimeMillis() - lastActive > workerTimeout * 1000L) - { - synchronized (lock) - { - if (selector.keys().isEmpty() && - connectQueue.isEmpty()) - { - worker = null; - try - { - selector.close(); - } - catch (IOException e) - { - ExceptionMonitor.getInstance().exceptionCaught(e); - } - finally - { - selector = null; - } - break; - } - } - } - } - else - { - lastActive = System.currentTimeMillis(); - } - } - catch (IOException e) - { - ExceptionMonitor.getInstance().exceptionCaught(e); - - try - { - Thread.sleep(1000); - } - catch (InterruptedException e1) - { - ExceptionMonitor.getInstance().exceptionCaught(e1); - } - } - } - } - } - - private class ConnectionRequest extends DefaultConnectFuture - { - private final SocketChannel channel; - private final long deadline; - private final IoHandler handler; - private final IoServiceConfig config; - - private ConnectionRequest(SocketChannel channel, IoHandler handler, IoServiceConfig config) - { - this.channel = channel; - long timeout; - if (config instanceof IoConnectorConfig) - { - timeout = ((IoConnectorConfig) config).getConnectTimeoutMillis(); - } - else - { - timeout = ((IoConnectorConfig) getDefaultConfig()).getConnectTimeoutMillis(); - } - this.deadline = System.currentTimeMillis() + timeout; - this.handler = handler; - this.config = config; - } - } -} diff --git a/java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketFilterChain.java b/java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketFilterChain.java deleted file mode 100644 index 67b8c8d820..0000000000 --- a/java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketFilterChain.java +++ /dev/null @@ -1,67 +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.mina.transport.socket.nio; - -import java.io.IOException; - -import org.apache.mina.common.ByteBuffer; -import org.apache.mina.common.IoFilterChain; -import org.apache.mina.common.IoSession; -import org.apache.mina.common.IoFilter.WriteRequest; -import org.apache.mina.common.support.AbstractIoFilterChain; -import org.apache.mina.util.Queue; - -/** - * An {@link IoFilterChain} for socket transport (TCP/IP). - * - * @author The Apache Directory Project (mina-dev@directory.apache.org) - */ -class MultiThreadSocketFilterChain extends AbstractIoFilterChain { - - MultiThreadSocketFilterChain( IoSession parent ) - { - super( parent ); - } - - protected void doWrite( IoSession session, WriteRequest writeRequest ) - { - MultiThreadSocketSessionImpl s = (MultiThreadSocketSessionImpl) session; - Queue writeRequestQueue = s.getWriteRequestQueue(); - - // SocketIoProcessor.doFlush() will reset it after write is finished - // because the buffer will be passed with messageSent event. - ( ( ByteBuffer ) writeRequest.getMessage() ).mark(); - synchronized( writeRequestQueue ) - { - writeRequestQueue.push( writeRequest ); - if( writeRequestQueue.size() == 1 && session.getTrafficMask().isWritable() ) - { - // Notify SocketIoProcessor only when writeRequestQueue was empty. - s.getIoProcessor().flush( s ); - } - } - } - - protected void doClose( IoSession session ) throws IOException - { - MultiThreadSocketSessionImpl s = (MultiThreadSocketSessionImpl) session; - s.getIoProcessor().remove( s ); - } -} diff --git a/java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketIoProcessor.java b/java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketIoProcessor.java deleted file mode 100644 index c23ad8686f..0000000000 --- a/java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketIoProcessor.java +++ /dev/null @@ -1,1026 +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.mina.transport.socket.nio; - -import edu.emory.mathcs.backport.java.util.concurrent.Executor; -import edu.emory.mathcs.backport.java.util.concurrent.locks.ReentrantLock; -import org.apache.mina.common.ByteBuffer; -import org.apache.mina.common.ExceptionMonitor; -import org.apache.mina.common.IdleStatus; -import org.apache.mina.common.IoFilter.WriteRequest; -import org.apache.mina.common.WriteTimeoutException; -import org.apache.mina.util.IdentityHashSet; -import org.apache.mina.util.NamePreservingRunnable; -import org.apache.mina.util.Queue; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.nio.channels.SelectionKey; -import java.nio.channels.Selector; -import java.nio.channels.SocketChannel; -import java.util.Iterator; -import java.util.Set; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; - -/** - * Performs all I/O operations for sockets which is connected or bound. This class is used by MINA internally. - * - * @author The Apache Directory Project (mina-dev@directory.apache.org) - * @version $Rev: 619823 $, $Date: 2008-02-08 10:09:37 +0000 (Fri, 08 Feb 2008) $, - */ -class MultiThreadSocketIoProcessor extends SocketIoProcessor -{ - Logger _logger = LoggerFactory.getLogger(MultiThreadSocketIoProcessor.class); - Logger _loggerRead = LoggerFactory.getLogger(MultiThreadSocketIoProcessor.class + ".Reader"); - Logger _loggerWrite = LoggerFactory.getLogger(MultiThreadSocketIoProcessor.class + ".Writer"); - - private static final long SELECTOR_TIMEOUT = 1000L; - - private int MAX_READ_BYTES_PER_SESSION = 524288; //512K - private int MAX_FLUSH_BYTES_PER_SESSION = 524288; //512K - - private final Object readLock = new Object(); - private final Object writeLock = new Object(); - - private final String threadName; - private final Executor executor; - - private ReentrantLock trafficMaskUpdateLock = new ReentrantLock(); - - /** @noinspection FieldAccessedSynchronizedAndUnsynchronized */ - private volatile Selector selector, writeSelector; - - private final Queue newSessions = new Queue(); - private final Queue removingSessions = new Queue(); - private final BlockingQueue flushingSessions = new LinkedBlockingQueue(); - private final IdentityHashSet flushingSessionsSet = new IdentityHashSet(); - - private final Queue trafficControllingSessions = new Queue(); - - private ReadWorker readWorker; - private WriteWorker writeWorker; - private long lastIdleReadCheckTime = System.currentTimeMillis(); - private long lastIdleWriteCheckTime = System.currentTimeMillis(); - - MultiThreadSocketIoProcessor(String threadName, Executor executor) - { - super(threadName, executor); - this.threadName = threadName; - this.executor = executor; - } - - void addNew(SocketSessionImpl session) throws IOException - { - synchronized (newSessions) - { - newSessions.push(session); - } - - startupWorker(); - - selector.wakeup(); - writeSelector.wakeup(); - } - - void remove(SocketSessionImpl session) throws IOException - { - scheduleRemove(session); - startupWorker(); - selector.wakeup(); - } - - private void startupWorker() throws IOException - { - synchronized (readLock) - { - if (readWorker == null) - { - selector = Selector.open(); - readWorker = new ReadWorker(); - executor.execute(new NamePreservingRunnable(readWorker)); - } - } - - synchronized (writeLock) - { - if (writeWorker == null) - { - writeSelector = Selector.open(); - writeWorker = new WriteWorker(); - executor.execute(new NamePreservingRunnable(writeWorker)); - } - } - - } - - void flush(SocketSessionImpl session) - { - scheduleFlush(session); - Selector selector = this.writeSelector; - - if (selector != null) - { - selector.wakeup(); - } - } - - void updateTrafficMask(SocketSessionImpl session) - { - scheduleTrafficControl(session); - Selector selector = this.selector; - if (selector != null) - { - selector.wakeup(); - } - } - - private void scheduleRemove(SocketSessionImpl session) - { - synchronized (removingSessions) - { - removingSessions.push(session); - } - } - - private void scheduleFlush(SocketSessionImpl session) - { - synchronized (flushingSessionsSet) - { - //if flushingSessions grows to contain Integer.MAX_VALUE sessions - // then this will fail. - if (flushingSessionsSet.add(session)) - { - flushingSessions.offer(session); - } - } - } - - private void scheduleTrafficControl(SocketSessionImpl session) - { - synchronized (trafficControllingSessions) - { - trafficControllingSessions.push(session); - } - } - - private void doAddNewReader() throws InterruptedException - { - if (newSessions.isEmpty()) - { - return; - } - - for (; ;) - { - MultiThreadSocketSessionImpl session; - - synchronized (newSessions) - { - session = (MultiThreadSocketSessionImpl) newSessions.peek(); - } - - if (session == null) - { - break; - } - - SocketChannel ch = session.getChannel(); - - - try - { - - ch.configureBlocking(false); - session.setSelectionKey(ch.register(selector, - SelectionKey.OP_READ, - session)); - - //System.out.println("ReadDebug:"+"Awaiting Registration"); - session.awaitRegistration(); - sessionCreated(session); - } - catch (IOException e) - { - // Clear the AbstractIoFilterChain.CONNECT_FUTURE attribute - // and call ConnectFuture.setException(). - session.getFilterChain().fireExceptionCaught(session, e); - } - } - } - - - private void doAddNewWrite() throws InterruptedException - { - if (newSessions.isEmpty()) - { - return; - } - - for (; ;) - { - MultiThreadSocketSessionImpl session; - - synchronized (newSessions) - { - session = (MultiThreadSocketSessionImpl) newSessions.peek(); - } - - if (session == null) - { - break; - } - - SocketChannel ch = session.getChannel(); - - try - { - ch.configureBlocking(false); - synchronized (flushingSessionsSet) - { - flushingSessionsSet.add(session); - } - - session.setWriteSelectionKey(ch.register(writeSelector, - SelectionKey.OP_WRITE, - session)); - - //System.out.println("WriteDebug:"+"Awaiting Registration"); - session.awaitRegistration(); - sessionCreated(session); - } - catch (IOException e) - { - - // Clear the AbstractIoFilterChain.CONNECT_FUTURE attribute - // and call ConnectFuture.setException(). - session.getFilterChain().fireExceptionCaught(session, e); - } - } - } - - - private void sessionCreated(SocketSessionImpl sessionParam) throws InterruptedException - { - MultiThreadSocketSessionImpl session = (MultiThreadSocketSessionImpl) sessionParam; - synchronized (newSessions) - { - if (!session.created()) - { - _logger.debug("Popping new session"); - newSessions.pop(); - - // AbstractIoFilterChain.CONNECT_FUTURE is cleared inside here - // in AbstractIoFilterChain.fireSessionOpened(). - session.getServiceListeners().fireSessionCreated(session); - - session.doneCreation(); - } - } - } - - private void doRemove() - { - if (removingSessions.isEmpty()) - { - return; - } - - for (; ;) - { - MultiThreadSocketSessionImpl session; - - synchronized (removingSessions) - { - session = (MultiThreadSocketSessionImpl) removingSessions.pop(); - } - - if (session == null) - { - break; - } - - SocketChannel ch = session.getChannel(); - SelectionKey key = session.getReadSelectionKey(); - SelectionKey writeKey = session.getWriteSelectionKey(); - - // Retry later if session is not yet fully initialized. - // (In case that Session.close() is called before addSession() is processed) - if (key == null || writeKey == null) - { - scheduleRemove(session); - break; - } - // skip if channel is already closed - if (!key.isValid() || !writeKey.isValid()) - { - continue; - } - - try - { - //System.out.println("ReadDebug:"+"Removing Session: " + System.identityHashCode(session)); - synchronized (readLock) - { - key.cancel(); - } - synchronized (writeLock) - { - writeKey.cancel(); - } - ch.close(); - } - catch (IOException e) - { - session.getFilterChain().fireExceptionCaught(session, e); - } - finally - { - releaseWriteBuffers(session); - session.getServiceListeners().fireSessionDestroyed(session); - } - } - } - - private void processRead(Set selectedKeys) - { - Iterator it = selectedKeys.iterator(); - - while (it.hasNext()) - { - SelectionKey key = (SelectionKey) it.next(); - MultiThreadSocketSessionImpl session = (MultiThreadSocketSessionImpl) key.attachment(); - - synchronized (readLock) - { - if (key.isValid() && key.isReadable() && session.getTrafficMask().isReadable()) - { - read(session); - } - } - - } - - selectedKeys.clear(); - } - - private void processWrite(Set selectedKeys) - { - Iterator it = selectedKeys.iterator(); - - while (it.hasNext()) - { - SelectionKey key = (SelectionKey) it.next(); - SocketSessionImpl session = (SocketSessionImpl) key.attachment(); - - synchronized (writeLock) - { - if (key.isValid() && key.isWritable() && session.getTrafficMask().isWritable()) - { - - // Clear OP_WRITE - key.interestOps(key.interestOps() & (~SelectionKey.OP_WRITE)); - - synchronized (flushingSessionsSet) - { - flushingSessions.offer(session); - } - } - } - } - - selectedKeys.clear(); - } - - private void read(SocketSessionImpl session) - { - - //if (_loggerWrite.isDebugEnabled()) - { - //System.out.println("WriteDebug:"+"Starting read for Session:" + System.identityHashCode(session)); - } - - int totalReadBytes = 0; - - while (totalReadBytes <= MAX_READ_BYTES_PER_SESSION) - { - ByteBuffer buf = ByteBuffer.allocate(session.getReadBufferSize()); - SocketChannel ch = session.getChannel(); - - try - { - buf.clear(); - - int readBytes = 0; - int ret; - - try - { - while ((ret = ch.read(buf.buf())) > 0) - { - readBytes += ret; - totalReadBytes += ret; - } - } - finally - { - buf.flip(); - } - - - if (readBytes > 0) - { - session.increaseReadBytes(readBytes); - - session.getFilterChain().fireMessageReceived(session, buf); - buf = null; - } - - if (ret <= 0) - { - if (ret == 0) - { - if (readBytes == session.getReadBufferSize()) - { - continue; - } - } - else - { - scheduleRemove(session); - } - - break; - } - } - catch (Throwable e) - { - if (e instanceof IOException) - { - scheduleRemove(session); - } - session.getFilterChain().fireExceptionCaught(session, e); - - //Stop Reading this session. - return; - } - finally - { - if (buf != null) - { - buf.release(); - } - } - }//for - - // if (_loggerWrite.isDebugEnabled()) - { - //System.out.println("WriteDebug:"+"Read for Session:" + System.identityHashCode(session) + " got: " + totalReadBytes); - } - } - - - private void notifyReadIdleness() - { - // process idle sessions - long currentTime = System.currentTimeMillis(); - if ((currentTime - lastIdleReadCheckTime) >= 1000) - { - lastIdleReadCheckTime = currentTime; - Set keys = selector.keys(); - if (keys != null) - { - for (Iterator it = keys.iterator(); it.hasNext();) - { - SelectionKey key = (SelectionKey) it.next(); - SocketSessionImpl session = (SocketSessionImpl) key.attachment(); - notifyReadIdleness(session, currentTime); - } - } - } - } - - private void notifyWriteIdleness() - { - // process idle sessions - long currentTime = System.currentTimeMillis(); - if ((currentTime - lastIdleWriteCheckTime) >= 1000) - { - lastIdleWriteCheckTime = currentTime; - Set keys = writeSelector.keys(); - if (keys != null) - { - for (Iterator it = keys.iterator(); it.hasNext();) - { - SelectionKey key = (SelectionKey) it.next(); - SocketSessionImpl session = (SocketSessionImpl) key.attachment(); - notifyWriteIdleness(session, currentTime); - } - } - } - } - - private void notifyReadIdleness(SocketSessionImpl session, long currentTime) - { - notifyIdleness0( - session, currentTime, - session.getIdleTimeInMillis(IdleStatus.BOTH_IDLE), - IdleStatus.BOTH_IDLE, - Math.max(session.getLastIoTime(), session.getLastIdleTime(IdleStatus.BOTH_IDLE))); - notifyIdleness0( - session, currentTime, - session.getIdleTimeInMillis(IdleStatus.READER_IDLE), - IdleStatus.READER_IDLE, - Math.max(session.getLastReadTime(), session.getLastIdleTime(IdleStatus.READER_IDLE))); - - notifyWriteTimeout(session, currentTime, session - .getWriteTimeoutInMillis(), session.getLastWriteTime()); - } - - private void notifyWriteIdleness(SocketSessionImpl session, long currentTime) - { - notifyIdleness0( - session, currentTime, - session.getIdleTimeInMillis(IdleStatus.BOTH_IDLE), - IdleStatus.BOTH_IDLE, - Math.max(session.getLastIoTime(), session.getLastIdleTime(IdleStatus.BOTH_IDLE))); - notifyIdleness0( - session, currentTime, - session.getIdleTimeInMillis(IdleStatus.WRITER_IDLE), - IdleStatus.WRITER_IDLE, - Math.max(session.getLastWriteTime(), session.getLastIdleTime(IdleStatus.WRITER_IDLE))); - - notifyWriteTimeout(session, currentTime, session - .getWriteTimeoutInMillis(), session.getLastWriteTime()); - } - - private void notifyIdleness0(SocketSessionImpl session, long currentTime, - long idleTime, IdleStatus status, - long lastIoTime) - { - if (idleTime > 0 && lastIoTime != 0 - && (currentTime - lastIoTime) >= idleTime) - { - session.increaseIdleCount(status); - session.getFilterChain().fireSessionIdle(session, status); - } - } - - private void notifyWriteTimeout(SocketSessionImpl session, - long currentTime, - long writeTimeout, long lastIoTime) - { - - MultiThreadSocketSessionImpl sesh = (MultiThreadSocketSessionImpl) session; - SelectionKey key = sesh.getWriteSelectionKey(); - - synchronized (writeLock) - { - if (writeTimeout > 0 - && (currentTime - lastIoTime) >= writeTimeout - && key != null && key.isValid() - && (key.interestOps() & SelectionKey.OP_WRITE) != 0) - { - session.getFilterChain().fireExceptionCaught(session, new WriteTimeoutException()); - } - } - } - - private SocketSessionImpl getNextFlushingSession() - { - return (SocketSessionImpl) flushingSessions.poll(); - } - - private void releaseSession(SocketSessionImpl session) - { - synchronized (session.getWriteRequestQueue()) - { - synchronized (flushingSessionsSet) - { - if (session.getScheduledWriteRequests() > 0) - { - if (_loggerWrite.isDebugEnabled()) - { - //System.out.println("WriteDebug:"+"Reflush" + System.identityHashCode(session)); - } - flushingSessions.offer(session); - } - else - { - if (_loggerWrite.isDebugEnabled()) - { - //System.out.println("WriteDebug:"+"Releasing session " + System.identityHashCode(session)); - } - flushingSessionsSet.remove(session); - } - } - } - } - - private void releaseWriteBuffers(SocketSessionImpl session) - { - Queue writeRequestQueue = session.getWriteRequestQueue(); - WriteRequest req; - - //Should this be synchronized? - synchronized (writeRequestQueue) - { - while ((req = (WriteRequest) writeRequestQueue.pop()) != null) - { - try - { - ((ByteBuffer) req.getMessage()).release(); - } - catch (IllegalStateException e) - { - session.getFilterChain().fireExceptionCaught(session, e); - } - finally - { - req.getFuture().setWritten(false); - } - } - } - } - - private void doFlush() - { - MultiThreadSocketSessionImpl session; - - while ((session = (MultiThreadSocketSessionImpl) getNextFlushingSession()) != null) - { - if (!session.isConnected()) - { - releaseWriteBuffers(session); - releaseSession(session); - continue; - } - - SelectionKey key = session.getWriteSelectionKey(); - // Retry later if session is not yet fully initialized. - // (In case that Session.write() is called before addSession() is processed) - if (key == null) - { - scheduleFlush(session); - releaseSession(session); - continue; - } - // skip if channel is already closed - if (!key.isValid()) - { - releaseSession(session); - continue; - } - - try - { - if (doFlush(session)) - { - releaseSession(session); - } - } - catch (IOException e) - { - releaseSession(session); - scheduleRemove(session); - session.getFilterChain().fireExceptionCaught(session, e); - } - - } - - } - - private boolean doFlush(SocketSessionImpl sessionParam) throws IOException - { - MultiThreadSocketSessionImpl session = (MultiThreadSocketSessionImpl) sessionParam; - // Clear OP_WRITE - SelectionKey key = session.getWriteSelectionKey(); - synchronized (writeLock) - { - key.interestOps(key.interestOps() & (~SelectionKey.OP_WRITE)); - } - SocketChannel ch = session.getChannel(); - Queue writeRequestQueue = session.getWriteRequestQueue(); - - long totalFlushedBytes = 0; - while (true) - { - WriteRequest req; - - synchronized (writeRequestQueue) - { - req = (WriteRequest) writeRequestQueue.first(); - } - - if (req == null) - { - break; - } - - ByteBuffer buf = (ByteBuffer) req.getMessage(); - if (buf.remaining() == 0) - { - synchronized (writeRequestQueue) - { - writeRequestQueue.pop(); - } - - session.increaseWrittenMessages(); - - buf.reset(); - session.getFilterChain().fireMessageSent(session, req); - continue; - } - - - int writtenBytes = 0; - - // Reported as DIRMINA-362 - //note: todo: fixme: Not sure it is important but if we see NoyYetConnected exceptions or 100% CPU in the kernel then this is it. - if (key.isWritable()) - { - writtenBytes = ch.write(buf.buf()); - totalFlushedBytes += writtenBytes; - } - - if (writtenBytes > 0) - { - session.increaseWrittenBytes(writtenBytes); - } - - if (buf.hasRemaining() || (totalFlushedBytes <= MAX_FLUSH_BYTES_PER_SESSION)) - { - // Kernel buffer is full - synchronized (writeLock) - { - key.interestOps(key.interestOps() | SelectionKey.OP_WRITE); - } - if (_loggerWrite.isDebugEnabled()) - { - //System.out.println("WriteDebug:"+"Written BF: " + (session.getWrittenBytes() - totalFlushedBytes) + " bytes"); - } - return false; - } - } - - if (_loggerWrite.isDebugEnabled()) - { - //System.out.println("WriteDebug:"+"Written : " + (session.getWrittenBytes() - totalFlushedBytes) + " bytes"); - } - return true; - } - - private void doUpdateTrafficMask() - { - if (trafficControllingSessions.isEmpty() || trafficMaskUpdateLock.isLocked()) - { - return; - } - - // Synchronize over entire operation as this method should be called - // from both read and write thread and we don't want the order of the - // updates to get changed. - trafficMaskUpdateLock.lock(); - try - { - for (; ;) - { - MultiThreadSocketSessionImpl session; - - session = (MultiThreadSocketSessionImpl) trafficControllingSessions.pop(); - - if (session == null) - { - break; - } - - SelectionKey key = session.getReadSelectionKey(); - // Retry later if session is not yet fully initialized. - // (In case that Session.suspend??() or session.resume??() is - // called before addSession() is processed) - if (key == null) - { - scheduleTrafficControl(session); - break; - } - // skip if channel is already closed - if (!key.isValid()) - { - continue; - } - - // The normal is OP_READ and, if there are write requests in the - // session's write queue, set OP_WRITE to trigger flushing. - - //Sset to Read and Write if there is nothing then the cost - // is one loop through the flusher. - int ops = SelectionKey.OP_READ; - - // Now mask the preferred ops with the mask of the current session - int mask = session.getTrafficMask().getInterestOps(); - synchronized (readLock) - { - key.interestOps(ops & mask); - } - //Change key to the WriteSelection Key - key = session.getWriteSelectionKey(); - if (key != null && key.isValid()) - { - Queue writeRequestQueue = session.getWriteRequestQueue(); - synchronized (writeRequestQueue) - { - if (!writeRequestQueue.isEmpty()) - { - ops = SelectionKey.OP_WRITE; - synchronized (writeLock) - { - key.interestOps(ops & mask); - } - } - } - } - } - } - finally - { - trafficMaskUpdateLock.unlock(); - } - - } - - private class WriteWorker implements Runnable - { - - public void run() - { - Thread.currentThread().setName(MultiThreadSocketIoProcessor.this.threadName + "Writer"); - - //System.out.println("WriteDebug:"+"Startup"); - for (; ;) - { - try - { - int nKeys = writeSelector.select(SELECTOR_TIMEOUT); - - doAddNewWrite(); - doUpdateTrafficMask(); - - if (nKeys > 0) - { - //System.out.println("WriteDebug:"+nKeys + " keys from writeselector"); - processWrite(writeSelector.selectedKeys()); - } - else - { - //System.out.println("WriteDebug:"+"No keys from writeselector"); - } - - doRemove(); - notifyWriteIdleness(); - - if (flushingSessionsSet.size() > 0) - { - doFlush(); - } - - if (writeSelector.keys().isEmpty()) - { - synchronized (writeLock) - { - - if (writeSelector.keys().isEmpty() && newSessions.isEmpty()) - { - writeWorker = null; - try - { - writeSelector.close(); - } - catch (IOException e) - { - ExceptionMonitor.getInstance().exceptionCaught(e); - } - finally - { - writeSelector = null; - } - - break; - } - } - } - - } - catch (Throwable t) - { - ExceptionMonitor.getInstance().exceptionCaught(t); - - try - { - Thread.sleep(1000); - } - catch (InterruptedException e1) - { - ExceptionMonitor.getInstance().exceptionCaught(e1); - } - } - } - //System.out.println("WriteDebug:"+"Shutdown"); - } - - } - - private class ReadWorker implements Runnable - { - - public void run() - { - Thread.currentThread().setName(MultiThreadSocketIoProcessor.this.threadName + "Reader"); - - //System.out.println("ReadDebug:"+"Startup"); - for (; ;) - { - try - { - int nKeys = selector.select(SELECTOR_TIMEOUT); - - doAddNewReader(); - doUpdateTrafficMask(); - - if (nKeys > 0) - { - //System.out.println("ReadDebug:"+nKeys + " keys from selector"); - - processRead(selector.selectedKeys()); - } - else - { - //System.out.println("ReadDebug:"+"No keys from selector"); - } - - - doRemove(); - notifyReadIdleness(); - - if (selector.keys().isEmpty()) - { - - synchronized (readLock) - { - if (selector.keys().isEmpty() && newSessions.isEmpty()) - { - readWorker = null; - try - { - selector.close(); - } - catch (IOException e) - { - ExceptionMonitor.getInstance().exceptionCaught(e); - } - finally - { - selector = null; - } - - break; - } - } - } - } - catch (Throwable t) - { - ExceptionMonitor.getInstance().exceptionCaught(t); - - try - { - Thread.sleep(1000); - } - catch (InterruptedException e1) - { - ExceptionMonitor.getInstance().exceptionCaught(e1); - } - } - } - //System.out.println("ReadDebug:"+"Shutdown"); - } - - } -} diff --git a/java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketSessionConfigImpl.java b/java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketSessionConfigImpl.java deleted file mode 100644 index 043d4800b6..0000000000 --- a/java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketSessionConfigImpl.java +++ /dev/null @@ -1,240 +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.mina.transport.socket.nio; - -import org.apache.mina.common.ExceptionMonitor; -import org.apache.mina.common.IoConnectorConfig; -import org.apache.mina.common.support.BaseIoSessionConfig; - -import java.io.IOException; -import java.net.Socket; -import java.net.SocketException; - -/** - * An {@link IoConnectorConfig} for {@link SocketConnector}. - * - * @author The Apache Directory Project (mina-dev@directory.apache.org) - * @version $Rev: 619823 $, $Date: 2008-02-08 10:09:37 +0000 (Fri, 08 Feb 2008) $ - */ -public class MultiThreadSocketSessionConfigImpl extends org.apache.mina.transport.socket.nio.SocketSessionConfigImpl -{ - private static boolean SET_RECEIVE_BUFFER_SIZE_AVAILABLE = false; - private static boolean SET_SEND_BUFFER_SIZE_AVAILABLE = false; - private static boolean GET_TRAFFIC_CLASS_AVAILABLE = false; - private static boolean SET_TRAFFIC_CLASS_AVAILABLE = false; - - private static boolean DEFAULT_REUSE_ADDRESS; - private static int DEFAULT_RECEIVE_BUFFER_SIZE; - private static int DEFAULT_SEND_BUFFER_SIZE; - private static int DEFAULT_TRAFFIC_CLASS; - private static boolean DEFAULT_KEEP_ALIVE; - private static boolean DEFAULT_OOB_INLINE; - private static int DEFAULT_SO_LINGER; - private static boolean DEFAULT_TCP_NO_DELAY; - - static - { - initialize(); - } - - private static void initialize() - { - Socket socket = null; - - socket = new Socket(); - - try - { - DEFAULT_REUSE_ADDRESS = socket.getReuseAddress(); - DEFAULT_RECEIVE_BUFFER_SIZE = socket.getReceiveBufferSize(); - DEFAULT_SEND_BUFFER_SIZE = socket.getSendBufferSize(); - DEFAULT_KEEP_ALIVE = socket.getKeepAlive(); - DEFAULT_OOB_INLINE = socket.getOOBInline(); - DEFAULT_SO_LINGER = socket.getSoLinger(); - DEFAULT_TCP_NO_DELAY = socket.getTcpNoDelay(); - - // Check if setReceiveBufferSize is supported. - try - { - socket.setReceiveBufferSize(DEFAULT_RECEIVE_BUFFER_SIZE); - SET_RECEIVE_BUFFER_SIZE_AVAILABLE = true; - } - catch( SocketException e ) - { - SET_RECEIVE_BUFFER_SIZE_AVAILABLE = false; - } - - // Check if setSendBufferSize is supported. - try - { - socket.setSendBufferSize(DEFAULT_SEND_BUFFER_SIZE); - SET_SEND_BUFFER_SIZE_AVAILABLE = true; - } - catch( SocketException e ) - { - SET_SEND_BUFFER_SIZE_AVAILABLE = false; - } - - // Check if getTrafficClass is supported. - try - { - DEFAULT_TRAFFIC_CLASS = socket.getTrafficClass(); - GET_TRAFFIC_CLASS_AVAILABLE = true; - } - catch( SocketException e ) - { - GET_TRAFFIC_CLASS_AVAILABLE = false; - DEFAULT_TRAFFIC_CLASS = 0; - } - } - catch( SocketException e ) - { - throw new ExceptionInInitializerError(e); - } - finally - { - if( socket != null ) - { - try - { - socket.close(); - } - catch( IOException e ) - { - ExceptionMonitor.getInstance().exceptionCaught(e); - } - } - } - } - - public static boolean isSetReceiveBufferSizeAvailable() { - return SET_RECEIVE_BUFFER_SIZE_AVAILABLE; - } - - public static boolean isSetSendBufferSizeAvailable() { - return SET_SEND_BUFFER_SIZE_AVAILABLE; - } - - public static boolean isGetTrafficClassAvailable() { - return GET_TRAFFIC_CLASS_AVAILABLE; - } - - public static boolean isSetTrafficClassAvailable() { - return SET_TRAFFIC_CLASS_AVAILABLE; - } - - private boolean reuseAddress = DEFAULT_REUSE_ADDRESS; - private int receiveBufferSize = DEFAULT_RECEIVE_BUFFER_SIZE; - private int sendBufferSize = DEFAULT_SEND_BUFFER_SIZE; - private int trafficClass = DEFAULT_TRAFFIC_CLASS; - private boolean keepAlive = DEFAULT_KEEP_ALIVE; - private boolean oobInline = DEFAULT_OOB_INLINE; - private int soLinger = DEFAULT_SO_LINGER; - private boolean tcpNoDelay = DEFAULT_TCP_NO_DELAY; - - /** - * Creates a new instance. - */ - MultiThreadSocketSessionConfigImpl() - { - } - - public boolean isReuseAddress() - { - return reuseAddress; - } - - public void setReuseAddress( boolean reuseAddress ) - { - this.reuseAddress = reuseAddress; - } - - public int getReceiveBufferSize() - { - return receiveBufferSize; - } - - public void setReceiveBufferSize( int receiveBufferSize ) - { - this.receiveBufferSize = receiveBufferSize; - } - - public int getSendBufferSize() - { - return sendBufferSize; - } - - public void setSendBufferSize( int sendBufferSize ) - { - this.sendBufferSize = sendBufferSize; - } - - public int getTrafficClass() - { - return trafficClass; - } - - public void setTrafficClass( int trafficClass ) - { - this.trafficClass = trafficClass; - } - - public boolean isKeepAlive() - { - return keepAlive; - } - - public void setKeepAlive( boolean keepAlive ) - { - this.keepAlive = keepAlive; - } - - public boolean isOobInline() - { - return oobInline; - } - - public void setOobInline( boolean oobInline ) - { - this.oobInline = oobInline; - } - - public int getSoLinger() - { - return soLinger; - } - - public void setSoLinger( int soLinger ) - { - this.soLinger = soLinger; - } - - public boolean isTcpNoDelay() - { - return tcpNoDelay; - } - - public void setTcpNoDelay( boolean tcpNoDelay ) - { - this.tcpNoDelay = tcpNoDelay; - } - - -} diff --git a/java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketSessionImpl.java b/java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketSessionImpl.java deleted file mode 100644 index be4a2d289d..0000000000 --- a/java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketSessionImpl.java +++ /dev/null @@ -1,488 +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.mina.transport.socket.nio; - -import org.apache.mina.common.IoFilter.WriteRequest; -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.RuntimeIOException; -import org.apache.mina.common.TransportType; -import org.apache.mina.common.support.BaseIoSessionConfig; -import org.apache.mina.common.support.IoServiceListenerSupport; -import org.apache.mina.util.Queue; - -import java.net.SocketAddress; -import java.net.SocketException; -import java.nio.channels.SelectionKey; -import java.nio.channels.SocketChannel; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.atomic.AtomicBoolean; - -/** - * An {@link IoSession} for socket transport (TCP/IP). - * - * @author The Apache Directory Project (mina-dev@directory.apache.org) - * @version $Rev: 619823 $, $Date: 2008-02-08 10:09:37 +0000 (Fri, 08 Feb 2008) $ - */ -class MultiThreadSocketSessionImpl extends SocketSessionImpl -{ - private final IoService manager; - private final IoServiceConfig serviceConfig; - private final SocketSessionConfig config = new SessionConfigImpl(); - private final MultiThreadSocketIoProcessor ioProcessor; - private final MultiThreadSocketFilterChain filterChain; - private final SocketChannel ch; - private final Queue writeRequestQueue; - private final IoHandler handler; - private final SocketAddress remoteAddress; - private final SocketAddress localAddress; - private final SocketAddress serviceAddress; - private final IoServiceListenerSupport serviceListeners; - private SelectionKey readKey, writeKey; - private int readBufferSize; - private CountDownLatch registeredReadyLatch = new CountDownLatch(2); - private AtomicBoolean created = new AtomicBoolean(false); - - /** - * Creates a new instance. - */ - MultiThreadSocketSessionImpl( IoService manager, - SocketIoProcessor ioProcessor, - IoServiceListenerSupport listeners, - IoServiceConfig serviceConfig, - SocketChannel ch, - IoHandler defaultHandler, - SocketAddress serviceAddress ) - { - super(manager, ioProcessor, listeners, serviceConfig, ch,defaultHandler,serviceAddress); - this.manager = manager; - this.serviceListeners = listeners; - this.ioProcessor = (MultiThreadSocketIoProcessor) ioProcessor; - this.filterChain = new MultiThreadSocketFilterChain(this); - this.ch = ch; - this.writeRequestQueue = new Queue(); - this.handler = defaultHandler; - this.remoteAddress = ch.socket().getRemoteSocketAddress(); - this.localAddress = ch.socket().getLocalSocketAddress(); - this.serviceAddress = serviceAddress; - this.serviceConfig = serviceConfig; - - // Apply the initial session settings - IoSessionConfig sessionConfig = serviceConfig.getSessionConfig(); - if( sessionConfig instanceof SocketSessionConfig ) - { - SocketSessionConfig cfg = ( SocketSessionConfig ) sessionConfig; - this.config.setKeepAlive( cfg.isKeepAlive() ); - this.config.setOobInline( cfg.isOobInline() ); - this.config.setReceiveBufferSize( cfg.getReceiveBufferSize() ); - this.readBufferSize = cfg.getReceiveBufferSize(); - this.config.setReuseAddress( cfg.isReuseAddress() ); - this.config.setSendBufferSize( cfg.getSendBufferSize() ); - this.config.setSoLinger( cfg.getSoLinger() ); - this.config.setTcpNoDelay( cfg.isTcpNoDelay() ); - - if( this.config.getTrafficClass() != cfg.getTrafficClass() ) - { - this.config.setTrafficClass( cfg.getTrafficClass() ); - } - } - } - - void awaitRegistration() throws InterruptedException - { - registeredReadyLatch.countDown(); - - registeredReadyLatch.await(); - } - - boolean created() throws InterruptedException - { - return created.get(); - } - - void doneCreation() - { - created.getAndSet(true); - } - - public IoService getService() - { - return manager; - } - - public IoServiceConfig getServiceConfig() - { - return serviceConfig; - } - - public IoSessionConfig getConfig() - { - return config; - } - - SocketIoProcessor getIoProcessor() - { - return ioProcessor; - } - - public IoFilterChain getFilterChain() - { - return filterChain; - } - - SocketChannel getChannel() - { - return ch; - } - - IoServiceListenerSupport getServiceListeners() - { - return serviceListeners; - } - - SelectionKey getSelectionKey() - { - return readKey; - } - - SelectionKey getReadSelectionKey() - { - return readKey; - } - - SelectionKey getWriteSelectionKey() - { - return writeKey; - } - - void setSelectionKey(SelectionKey key) - { - this.readKey = key; - } - - void setWriteSelectionKey(SelectionKey key) - { - this.writeKey = key; - } - - public IoHandler getHandler() - { - return handler; - } - - protected void close0() - { - filterChain.fireFilterClose( this ); - } - - Queue getWriteRequestQueue() - { - return writeRequestQueue; - } - - /** - @return int Number of write scheduled write requests - @deprecated - */ - public int getScheduledWriteMessages() - { - return getScheduledWriteRequests(); - } - - public int getScheduledWriteRequests() - { - synchronized( writeRequestQueue ) - { - return writeRequestQueue.size(); - } - } - - public int getScheduledWriteBytes() - { - synchronized( writeRequestQueue ) - { - return writeRequestQueue.byteSize(); - } - } - - protected void write0( WriteRequest writeRequest ) - { - filterChain.fireFilterWrite( this, writeRequest ); - } - - public TransportType getTransportType() - { - return TransportType.SOCKET; - } - - public SocketAddress getRemoteAddress() - { - //This is what I had previously -// return ch.socket().getRemoteSocketAddress(); - return remoteAddress; - } - - public SocketAddress getLocalAddress() - { - //This is what I had previously -// return ch.socket().getLocalSocketAddress(); - return localAddress; - } - - public SocketAddress getServiceAddress() - { - return serviceAddress; - } - - protected void updateTrafficMask() - { - this.ioProcessor.updateTrafficMask( this ); - } - - int getReadBufferSize() - { - return readBufferSize; - } - - private class SessionConfigImpl extends BaseIoSessionConfig implements SocketSessionConfig - { - public boolean isKeepAlive() - { - try - { - return ch.socket().getKeepAlive(); - } - catch( SocketException e ) - { - throw new RuntimeIOException( e ); - } - } - - public void setKeepAlive( boolean on ) - { - try - { - ch.socket().setKeepAlive( on ); - } - catch( SocketException e ) - { - throw new RuntimeIOException( e ); - } - } - - public boolean isOobInline() - { - try - { - return ch.socket().getOOBInline(); - } - catch( SocketException e ) - { - throw new RuntimeIOException( e ); - } - } - - public void setOobInline( boolean on ) - { - try - { - ch.socket().setOOBInline( on ); - } - catch( SocketException e ) - { - throw new RuntimeIOException( e ); - } - } - - public boolean isReuseAddress() - { - try - { - return ch.socket().getReuseAddress(); - } - catch( SocketException e ) - { - throw new RuntimeIOException( e ); - } - } - - public void setReuseAddress( boolean on ) - { - try - { - ch.socket().setReuseAddress( on ); - } - catch( SocketException e ) - { - throw new RuntimeIOException( e ); - } - } - - public int getSoLinger() - { - try - { - return ch.socket().getSoLinger(); - } - catch( SocketException e ) - { - throw new RuntimeIOException( e ); - } - } - - public void setSoLinger( int linger ) - { - try - { - if( linger < 0 ) - { - ch.socket().setSoLinger( false, 0 ); - } - else - { - ch.socket().setSoLinger( true, linger ); - } - } - catch( SocketException e ) - { - throw new RuntimeIOException( e ); - } - } - - public boolean isTcpNoDelay() - { - try - { - return ch.socket().getTcpNoDelay(); - } - catch( SocketException e ) - { - throw new RuntimeIOException( e ); - } - } - - public void setTcpNoDelay( boolean on ) - { - try - { - ch.socket().setTcpNoDelay( on ); - } - catch( SocketException e ) - { - throw new RuntimeIOException( e ); - } - } - - public int getTrafficClass() - { - if( SocketSessionConfigImpl.isGetTrafficClassAvailable() ) - { - try - { - return ch.socket().getTrafficClass(); - } - catch( SocketException e ) - { - // Throw an exception only when setTrafficClass is also available. - if( SocketSessionConfigImpl.isSetTrafficClassAvailable() ) - { - throw new RuntimeIOException( e ); - } - } - } - - return 0; - } - - public void setTrafficClass( int tc ) - { - if( SocketSessionConfigImpl.isSetTrafficClassAvailable() ) - { - try - { - ch.socket().setTrafficClass( tc ); - } - catch( SocketException e ) - { - throw new RuntimeIOException( e ); - } - } - } - - public int getSendBufferSize() - { - try - { - return ch.socket().getSendBufferSize(); - } - catch( SocketException e ) - { - throw new RuntimeIOException( e ); - } - } - - public void setSendBufferSize( int size ) - { - if( SocketSessionConfigImpl.isSetSendBufferSizeAvailable() ) - { - try - { - ch.socket().setSendBufferSize( size ); - } - catch( SocketException e ) - { - throw new RuntimeIOException( e ); - } - } - } - - public int getReceiveBufferSize() - { - try - { - return ch.socket().getReceiveBufferSize(); - } - catch( SocketException e ) - { - throw new RuntimeIOException( e ); - } - } - - public void setReceiveBufferSize( int size ) - { - if( SocketSessionConfigImpl.isSetReceiveBufferSizeAvailable() ) - { - try - { - ch.socket().setReceiveBufferSize( size ); - MultiThreadSocketSessionImpl.this.readBufferSize = size; - } - catch( SocketException e ) - { - throw new RuntimeIOException( e ); - } - } - } - } -} diff --git a/java/common/src/main/java/org/apache/mina/transport/vmpipe/QpidVmPipeConnector.java b/java/common/src/main/java/org/apache/mina/transport/vmpipe/QpidVmPipeConnector.java deleted file mode 100644 index a23e546af5..0000000000 --- a/java/common/src/main/java/org/apache/mina/transport/vmpipe/QpidVmPipeConnector.java +++ /dev/null @@ -1,151 +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.mina.transport.vmpipe; - -import java.io.IOException; -import java.net.SocketAddress; - -import org.apache.mina.common.ConnectFuture; -import org.apache.mina.common.ExceptionMonitor; -import org.apache.mina.common.IoFilterChain; -import org.apache.mina.common.IoHandler; -import org.apache.mina.common.IoServiceConfig; -import org.apache.mina.common.IoSessionConfig; -import org.apache.mina.common.support.AbstractIoFilterChain; -import org.apache.mina.common.support.BaseIoConnector; -import org.apache.mina.common.support.BaseIoConnectorConfig; -import org.apache.mina.common.support.BaseIoSessionConfig; -import org.apache.mina.common.support.DefaultConnectFuture; -import org.apache.mina.transport.vmpipe.support.VmPipe; -import org.apache.mina.transport.vmpipe.support.VmPipeIdleStatusChecker; -import org.apache.mina.transport.vmpipe.support.VmPipeSessionImpl; -import org.apache.mina.util.AnonymousSocketAddress; - -/** - * Connects to {@link IoHandler}s which is bound on the specified - * {@link VmPipeAddress}. - * - * @author The Apache Directory Project (mina-dev@directory.apache.org) - * @version $Rev: 619823 $, $Date: 2008-02-08 10:09:37 +0000 (Fri, 08 Feb 2008) $ - */ -public class QpidVmPipeConnector extends VmPipeConnector -{ - private static final IoSessionConfig CONFIG = new BaseIoSessionConfig() {}; - private final IoServiceConfig defaultConfig = new BaseIoConnectorConfig() - { - public IoSessionConfig getSessionConfig() - { - return CONFIG; - } - }; - - /** - * Creates a new instance. - */ - public QpidVmPipeConnector() - { - } - - public ConnectFuture connect( SocketAddress address, IoHandler handler, IoServiceConfig config ) - { - return connect( address, null, handler, config ); - } - - public ConnectFuture connect( SocketAddress address, SocketAddress localAddress, IoHandler handler, IoServiceConfig config ) - { - if( address == null ) - throw new NullPointerException( "address" ); - if( handler == null ) - throw new NullPointerException( "handler" ); - if( ! ( address instanceof VmPipeAddress ) ) - throw new IllegalArgumentException( - "address must be VmPipeAddress." ); - - if( config == null ) - { - config = getDefaultConfig(); - } - - VmPipe entry = ( VmPipe ) VmPipeAcceptor.boundHandlers.get( address ); - if( entry == null ) - { - return DefaultConnectFuture.newFailedFuture( - new IOException( "Endpoint unavailable: " + address ) ); - } - - DefaultConnectFuture future = new DefaultConnectFuture(); - VmPipeSessionImpl localSession = - new VmPipeSessionImpl( - this, - config, - getListeners(), - new Object(), // lock - new AnonymousSocketAddress(), - handler, - entry ); - - // initialize acceptor session - VmPipeSessionImpl remoteSession = localSession.getRemoteSession(); - try - { - IoFilterChain filterChain = remoteSession.getFilterChain(); - entry.getAcceptor().getFilterChainBuilder().buildFilterChain( filterChain ); - entry.getConfig().getFilterChainBuilder().buildFilterChain( filterChain ); - entry.getConfig().getThreadModel().buildFilterChain( filterChain ); - - // The following sentences don't throw any exceptions. - entry.getListeners().fireSessionCreated( remoteSession ); - VmPipeIdleStatusChecker.getInstance().addSession( remoteSession ); - } - catch( Throwable t ) - { - ExceptionMonitor.getInstance().exceptionCaught( t ); - remoteSession.close(); - } - - - // initialize connector session - try - { - IoFilterChain filterChain = localSession.getFilterChain(); - this.getFilterChainBuilder().buildFilterChain( filterChain ); - config.getFilterChainBuilder().buildFilterChain( filterChain ); - config.getThreadModel().buildFilterChain( filterChain ); - - // The following sentences don't throw any exceptions. - localSession.setAttribute( AbstractIoFilterChain.CONNECT_FUTURE, future ); - getListeners().fireSessionCreated( localSession ); - VmPipeIdleStatusChecker.getInstance().addSession( localSession); - } - catch( Throwable t ) - { - future.setException( t ); - } - - - - return future; - } - - public IoServiceConfig getDefaultConfig() - { - return defaultConfig; - } -}
\ No newline at end of file diff --git a/java/common/src/main/java/org/apache/qpid/AMQChannelException.java b/java/common/src/main/java/org/apache/qpid/AMQChannelException.java index ef9420ba87..2f6290b55a 100644 --- a/java/common/src/main/java/org/apache/qpid/AMQChannelException.java +++ b/java/common/src/main/java/org/apache/qpid/AMQChannelException.java @@ -54,6 +54,7 @@ public class AMQChannelException extends AMQException public AMQFrame getCloseFrame(int channel) { MethodRegistry reg = MethodRegistry.getMethodRegistry(new ProtocolVersion(major,minor)); - return new AMQFrame(channel, reg.createChannelCloseBody(getErrorCode() == null ? AMQConstant.INTERNAL_ERROR.getCode() : getErrorCode().getCode(), new AMQShortString(getMessage()),_classId,_methodId)); + return new AMQFrame(channel, reg.createChannelCloseBody(getErrorCode() == null ? AMQConstant.INTERNAL_ERROR.getCode() : getErrorCode().getCode(), getMessageAsShortString(),_classId,_methodId)); } + } diff --git a/java/common/src/main/java/org/apache/qpid/AMQConnectionException.java b/java/common/src/main/java/org/apache/qpid/AMQConnectionException.java index 8ef6facef1..ca9c9f9dc4 100644 --- a/java/common/src/main/java/org/apache/qpid/AMQConnectionException.java +++ b/java/common/src/main/java/org/apache/qpid/AMQConnectionException.java @@ -62,9 +62,10 @@ public class AMQConnectionException extends AMQException MethodRegistry reg = MethodRegistry.getMethodRegistry(new ProtocolVersion(major,minor)); return new AMQFrame(0, reg.createConnectionCloseBody(getErrorCode().getCode(), - new AMQShortString(getMessage()), + getMessageAsShortString(), _classId, _methodId)); } + } diff --git a/java/common/src/main/java/org/apache/qpid/AMQException.java b/java/common/src/main/java/org/apache/qpid/AMQException.java index b0c6fccc9e..86d439d269 100644 --- a/java/common/src/main/java/org/apache/qpid/AMQException.java +++ b/java/common/src/main/java/org/apache/qpid/AMQException.java @@ -20,6 +20,7 @@ */ package org.apache.qpid; +import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.protocol.AMQConstant; /** @@ -121,4 +122,19 @@ public class AMQException extends Exception return newAMQE; } + + /** + * Truncates the exception message to 255 characters if its length exceeds 255. + * + * @return exception message + */ + public AMQShortString getMessageAsShortString() + { + String message = getMessage(); + if (message != null && message.length() > AMQShortString.MAX_LENGTH) + { + message = message.substring(0, AMQShortString.MAX_LENGTH - 3) + "..."; + } + return new AMQShortString(message); + } } diff --git a/java/common/src/main/java/org/apache/qpid/AMQInvalidArgumentException.java b/java/common/src/main/java/org/apache/qpid/AMQInvalidArgumentException.java index baca2a4773..2bbaaef1fc 100644 --- a/java/common/src/main/java/org/apache/qpid/AMQInvalidArgumentException.java +++ b/java/common/src/main/java/org/apache/qpid/AMQInvalidArgumentException.java @@ -34,7 +34,7 @@ public class AMQInvalidArgumentException extends AMQException { public AMQInvalidArgumentException(String message, Throwable cause) { - super(AMQConstant.INVALID_ARGUMENT, message, cause); + super(AMQConstant.ARGUMENT_INVALID, message, cause); } public boolean isHardError() diff --git a/java/common/src/main/java/org/apache/qpid/ToyBroker.java b/java/common/src/main/java/org/apache/qpid/ToyBroker.java deleted file mode 100644 index 5423bbb68f..0000000000 --- a/java/common/src/main/java/org/apache/qpid/ToyBroker.java +++ /dev/null @@ -1,208 +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; - -import org.apache.qpid.transport.*; -import org.apache.qpid.transport.network.mina.MinaHandler; - -import static org.apache.qpid.transport.util.Functions.str; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.LinkedBlockingQueue; - - -/** - * ToyBroker - * - * @author Rafael H. Schloming - */ - -class ToyBroker extends SessionDelegate -{ - - private ToyExchange exchange; - private Map<String,Consumer> consumers = new ConcurrentHashMap<String,Consumer>(); - - public ToyBroker(ToyExchange exchange) - { - this.exchange = exchange; - } - - public void messageAcquire(Session context, MessageAcquire struct) - { - System.out.println("\n==================> messageAcquire " ); - context.executionResult((int) struct.getId(), new Acquired(struct.getTransfers())); - } - - @Override public void queueDeclare(Session ssn, QueueDeclare qd) - { - exchange.createQueue(qd.getQueue()); - System.out.println("\n==================> declared queue: " + qd.getQueue() + "\n"); - } - - @Override public void exchangeBind(Session ssn, ExchangeBind qb) - { - exchange.bindQueue(qb.getExchange(), qb.getBindingKey(),qb.getQueue()); - System.out.println("\n==================> bound queue: " + qb.getQueue() + " with binding key " + qb.getBindingKey() + "\n"); - } - - @Override public void queueQuery(Session ssn, QueueQuery qq) - { - QueueQueryResult result = new QueueQueryResult().queue(qq.getQueue()); - ssn.executionResult((int) qq.getId(), result); - } - - @Override public void messageSubscribe(Session ssn, MessageSubscribe ms) - { - Consumer c = new Consumer(); - c._queueName = ms.getQueue(); - consumers.put(ms.getDestination(),c); - System.out.println("\n==================> message subscribe : " + ms.getDestination() + " queue: " + ms.getQueue() + "\n"); - } - - @Override public void messageFlow(Session ssn,MessageFlow struct) - { - Consumer c = consumers.get(struct.getDestination()); - c._credit = struct.getValue(); - System.out.println("\n==================> message flow : " + struct.getDestination() + " credit: " + struct.getValue() + "\n"); - } - - @Override public void messageFlush(Session ssn,MessageFlush struct) - { - System.out.println("\n==================> message flush for consumer : " + struct.getDestination() + "\n"); - checkAndSendMessagesToConsumer(ssn,struct.getDestination()); - } - - @Override public void messageTransfer(Session ssn, MessageTransfer xfr) - { - String dest = xfr.getDestination(); - System.out.println("received transfer " + dest); - Header header = xfr.getHeader(); - DeliveryProperties props = header.get(DeliveryProperties.class); - if (props != null) - { - System.out.println("received headers routing_key " + props.getRoutingKey()); - } - - MessageProperties mp = header.get(MessageProperties.class); - System.out.println("MP: " + mp); - if (mp != null) - { - System.out.println(mp.getApplicationHeaders()); - } - - if (exchange.route(dest,props == null ? null : props.getRoutingKey(),xfr)) - { - System.out.println("queued " + xfr); - dispatchMessages(ssn); - } - else - { - - if (props == null || !props.getDiscardUnroutable()) - { - RangeSet ranges = new RangeSet(); - ranges.add(xfr.getId()); - ssn.messageReject(ranges, MessageRejectCode.UNROUTABLE, - "no such destination"); - } - } - ssn.processed(xfr); - } - - private void transferMessageToPeer(Session ssn,String dest, MessageTransfer m) - { - System.out.println("\n==================> Transfering message to: " +dest + "\n"); - ssn.messageTransfer(m.getDestination(), MessageAcceptMode.EXPLICIT, - MessageAcquireMode.PRE_ACQUIRED, - m.getHeader(), m.getBody()); - } - - private void dispatchMessages(Session ssn) - { - for (String dest: consumers.keySet()) - { - checkAndSendMessagesToConsumer(ssn,dest); - } - } - - private void checkAndSendMessagesToConsumer(Session ssn,String dest) - { - Consumer c = consumers.get(dest); - LinkedBlockingQueue<MessageTransfer> queue = exchange.getQueue(c._queueName); - MessageTransfer m = queue.poll(); - while (m != null && c._credit>0) - { - transferMessageToPeer(ssn,dest,m); - c._credit--; - m = queue.poll(); - } - } - - // ugly, but who cares :) - // assumes unit is always no of messages, not bytes - // assumes it's credit mode and not window - private static class Consumer - { - long _credit; - String _queueName; - } - - private static final class ToyBrokerSession extends Session - { - - public ToyBrokerSession(Connection connection, Binary name, long expiry, ToyExchange exchange) - { - super(connection, new ToyBroker(exchange), name, expiry); - } - } - - public static final void main(String[] args) throws IOException - { - final ToyExchange exchange = new ToyExchange(); - ConnectionDelegate delegate = new ServerDelegate() - { - @Override - public void init(Connection conn, ProtocolHeader hdr) - { - conn.setSessionFactory(new Connection.SessionFactory() - { - public Session newSession(Connection conn, Binary name, long expiry) - { - return new ToyBrokerSession(conn, name, expiry, exchange); - } - }); - - super.init(conn, hdr); //To change body of overridden methods use File | Settings | File Templates. - } - - }; - - MinaHandler.accept("0.0.0.0", 5672, delegate); - } - -} diff --git a/java/common/src/main/java/org/apache/qpid/ToyClient.java b/java/common/src/main/java/org/apache/qpid/ToyClient.java deleted file mode 100644 index 5b2db10613..0000000000 --- a/java/common/src/main/java/org/apache/qpid/ToyClient.java +++ /dev/null @@ -1,108 +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; - -import java.nio.*; -import java.util.*; - -import org.apache.qpid.transport.*; -import org.apache.qpid.transport.network.mina.MinaHandler; - - -/** - * ToyClient - * - * @author Rafael H. Schloming - */ - -class ToyClient implements SessionListener -{ - public void opened(Session ssn) {} - - public void resumed(Session ssn) {} - - public void exception(Session ssn, SessionException exc) - { - exc.printStackTrace(); - } - - public void message(Session ssn, MessageTransfer xfr) - { - System.out.println("msg: " + xfr); - } - - public void closed(Session ssn) {} - - public static final void main(String[] args) - { - Connection conn = new Connection(); - conn.connect("0.0.0.0", 5672, null, "guest", "guest", false); - Session ssn = conn.createSession(); - ssn.setSessionListener(new ToyClient()); - - ssn.queueDeclare("asdf", null, null); - ssn.sync(); - - Map<String,Object> nested = new LinkedHashMap<String,Object>(); - nested.put("list", Arrays.asList("one", "two", "three")); - Map<String,Object> map = new LinkedHashMap<String,Object>(); - - map.put("str", "this is a string"); - - map.put("+int", 3); - map.put("-int", -3); - map.put("maxint", Integer.MAX_VALUE); - map.put("minint", Integer.MIN_VALUE); - - map.put("+short", (short) 1); - map.put("-short", (short) -1); - map.put("maxshort", (short) Short.MAX_VALUE); - map.put("minshort", (short) Short.MIN_VALUE); - - map.put("float", (float) 3.3); - map.put("double", 4.9); - map.put("char", 'c'); - - map.put("table", nested); - map.put("list", Arrays.asList(1, 2, 3)); - map.put("binary", new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}); - - ssn.messageTransfer("asdf", MessageAcceptMode.EXPLICIT, - MessageAcquireMode.PRE_ACQUIRED, - new Header(new DeliveryProperties(), - new MessageProperties() - .setApplicationHeaders(map)), - "this is the data"); - - ssn.messageTransfer("fdsa", MessageAcceptMode.EXPLICIT, - MessageAcquireMode.PRE_ACQUIRED, - null, - "this should be rejected"); - ssn.sync(); - - Future<QueueQueryResult> future = ssn.queueQuery("asdf"); - System.out.println(future.get().getQueue()); - ssn.sync(); - ssn.close(); - conn.close(); - } - -} diff --git a/java/common/src/main/java/org/apache/qpid/ToyExchange.java b/java/common/src/main/java/org/apache/qpid/ToyExchange.java deleted file mode 100644 index da6aed9629..0000000000 --- a/java/common/src/main/java/org/apache/qpid/ToyExchange.java +++ /dev/null @@ -1,154 +0,0 @@ -package org.apache.qpid; -/* - * - * 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.ArrayList; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.apache.qpid.transport.MessageTransfer; - - -public class ToyExchange -{ - final static String DIRECT = "amq.direct"; - final static String TOPIC = "amq.topic"; - - private Map<String,List<LinkedBlockingQueue<MessageTransfer>>> directEx = new HashMap<String,List<LinkedBlockingQueue<MessageTransfer>>>(); - private Map<String,List<LinkedBlockingQueue<MessageTransfer>>> topicEx = new HashMap<String,List<LinkedBlockingQueue<MessageTransfer>>>(); - private Map<String,LinkedBlockingQueue<MessageTransfer>> queues = new HashMap<String,LinkedBlockingQueue<MessageTransfer>>(); - - public void createQueue(String name) - { - queues.put(name, new LinkedBlockingQueue<MessageTransfer>()); - } - - public LinkedBlockingQueue<MessageTransfer> getQueue(String name) - { - return queues.get(name); - } - - public void bindQueue(String type,String binding,String queueName) - { - LinkedBlockingQueue<MessageTransfer> queue = queues.get(queueName); - binding = normalizeKey(binding); - if(DIRECT.equals(type)) - { - - if (directEx.containsKey(binding)) - { - List<LinkedBlockingQueue<MessageTransfer>> list = directEx.get(binding); - list.add(queue); - } - else - { - List<LinkedBlockingQueue<MessageTransfer>> list = new LinkedList<LinkedBlockingQueue<MessageTransfer>>(); - list.add(queue); - directEx.put(binding,list); - } - } - else - { - if (topicEx.containsKey(binding)) - { - List<LinkedBlockingQueue<MessageTransfer>> list = topicEx.get(binding); - list.add(queue); - } - else - { - List<LinkedBlockingQueue<MessageTransfer>> list = new LinkedList<LinkedBlockingQueue<MessageTransfer>>(); - list.add(queue); - topicEx.put(binding,list); - } - } - } - - public boolean route(String dest, String routingKey, MessageTransfer msg) - { - List<LinkedBlockingQueue<MessageTransfer>> queues; - if(DIRECT.equals(dest)) - { - queues = directEx.get(routingKey); - } - else - { - queues = matchWildCard(routingKey); - } - if(queues != null && queues.size()>0) - { - System.out.println("Message stored in " + queues.size() + " queues"); - storeMessage(msg,queues); - return true; - } - else - { - System.out.println("Message unroutable " + msg); - return false; - } - } - - private String normalizeKey(String routingKey) - { - if(routingKey.indexOf(".*")>1) - { - return routingKey.substring(0,routingKey.indexOf(".*")); - } - else - { - return routingKey; - } - } - - private List<LinkedBlockingQueue<MessageTransfer>> matchWildCard(String routingKey) - { - List<LinkedBlockingQueue<MessageTransfer>> selected = new ArrayList<LinkedBlockingQueue<MessageTransfer>>(); - - for(String key: topicEx.keySet()) - { - Pattern p = Pattern.compile(key); - Matcher m = p.matcher(routingKey); - if (m.find()) - { - for(LinkedBlockingQueue<MessageTransfer> queue : topicEx.get(key)) - { - selected.add(queue); - } - } - } - - return selected; - } - - private void storeMessage(MessageTransfer msg,List<LinkedBlockingQueue<MessageTransfer>> selected) - { - for(LinkedBlockingQueue<MessageTransfer> queue : selected) - { - queue.offer(msg); - } - } - -} diff --git a/java/common/src/main/java/org/apache/qpid/codec/AMQCodecFactory.java b/java/common/src/main/java/org/apache/qpid/codec/AMQCodecFactory.java index 591dbd085b..c81af9760b 100644 --- a/java/common/src/main/java/org/apache/qpid/codec/AMQCodecFactory.java +++ b/java/common/src/main/java/org/apache/qpid/codec/AMQCodecFactory.java @@ -20,9 +20,6 @@ */ 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; /** @@ -31,14 +28,11 @@ import org.apache.qpid.protocol.AMQVersionAwareProtocolSession; * * <p/><table id="crc"><caption>CRC Card</caption> * <tr><th> Responsibilities <th> Collaborations. - * <tr><td> Supply the protocol encoder. <td> {@link AMQEncoder} * <tr><td> Supply the protocol decoder. <td> {@link AMQDecoder} * </table> */ -public class AMQCodecFactory implements ProtocolCodecFactory +public class AMQCodecFactory { - /** Holds the protocol encoder. */ - private final AMQEncoder _encoder = new AMQEncoder(); /** Holds the protocol decoder. */ private final AMQDecoder _frameDecoder; @@ -56,15 +50,6 @@ public class AMQCodecFactory implements ProtocolCodecFactory _frameDecoder = new AMQDecoder(expectProtocolInitiation, session); } - /** - * Gets the AMQP encoder. - * - * @return The AMQP encoder. - */ - public ProtocolEncoder getEncoder() - { - return _encoder; - } /** * Gets the AMQP decoder. diff --git a/java/common/src/main/java/org/apache/qpid/codec/AMQDecoder.java b/java/common/src/main/java/org/apache/qpid/codec/AMQDecoder.java index 281c0761d9..69bf73bb49 100644 --- a/java/common/src/main/java/org/apache/qpid/codec/AMQDecoder.java +++ b/java/common/src/main/java/org/apache/qpid/codec/AMQDecoder.java @@ -20,13 +20,9 @@ */ 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 java.io.*; +import java.nio.ByteBuffer; +import java.util.*; import org.apache.qpid.framing.AMQDataBlock; import org.apache.qpid.framing.AMQDataBlockDecoder; @@ -54,11 +50,8 @@ import org.apache.qpid.protocol.AMQVersionAwareProtocolSession; * @todo If protocol initiation decoder not needed, then don't create it. Probably not a big deal, but it adds to the * per-session overhead. */ -public class AMQDecoder extends CumulativeProtocolDecoder +public class AMQDecoder { - - private static final String BUFFER = AMQDecoder.class.getName() + ".Buffer"; - /** Holds the 'normal' AMQP data decoder. */ private AMQDataBlockDecoder _dataBlockDecoder = new AMQDataBlockDecoder(); @@ -67,12 +60,11 @@ public class AMQDecoder extends CumulativeProtocolDecoder /** Flag to indicate whether this decoder needs to handle protocol initiation. */ private boolean _expectProtocolInitiation; - private boolean firstDecode = true; private AMQMethodBodyFactory _bodyFactory; - private ByteBuffer _remainingBuf; - + private List<ByteArrayInputStream> _remainingBufs = new ArrayList<ByteArrayInputStream>(); + /** * Creates a new AMQP decoder. * @@ -84,98 +76,7 @@ public class AMQDecoder extends CumulativeProtocolDecoder _bodyFactory = new AMQMethodBodyFactory(session); } - /** - * Delegates decoding AMQP from the data buffer that Mina has retrieved from the wire, to the data or protocol - * intiation decoders. - * - * @param session The Mina session. - * @param in The raw byte buffer. - * @param out The Mina object output gatherer to write decoded objects to. - * - * @return <tt>true</tt> if the data was decoded, <tt>false<tt> if more is needed and the data should accumulate. - * - * @throws Exception If the data cannot be decoded for any reason. - */ - protected boolean doDecode(IoSession session, ByteBuffer in, ProtocolDecoderOutput out) throws Exception - { - - boolean decoded; - if (_expectProtocolInitiation - || (firstDecode - && (in.remaining() > 0) - && (in.get(in.position()) == (byte)'A'))) - { - decoded = doDecodePI(session, in, out); - } - else - { - decoded = doDecodeDataBlock(session, in, out); - } - if(firstDecode && decoded) - { - firstDecode = false; - } - return decoded; - } - - /** - * Decodes AMQP data, delegating the decoding to an {@link AMQDataBlockDecoder}. - * - * @param session The Mina session. - * @param in The raw byte buffer. - * @param out The Mina object output gatherer to write decoded objects to. - * - * @return <tt>true</tt> if the data was decoded, <tt>false<tt> if more is needed and the data should accumulate. - * - * @throws Exception If the data cannot be decoded for any reason. - */ - protected boolean doDecodeDataBlock(IoSession session, ByteBuffer in, ProtocolDecoderOutput out) throws Exception - { - int pos = in.position(); - boolean enoughData = _dataBlockDecoder.decodable(in.buf()); - in.position(pos); - if (!enoughData) - { - // returning false means it will leave the contents in the buffer and - // call us again when more data has been read - return false; - } - else - { - _dataBlockDecoder.decode(session, in, out); - - return true; - } - } - - /** - * Decodes an AMQP initiation, delegating the decoding to a {@link ProtocolInitiation.Decoder}. - * - * @param session The Mina session. - * @param in The raw byte buffer. - * @param out The Mina object output gatherer to write decoded objects to. - * - * @return <tt>true</tt> if the data was decoded, <tt>false<tt> if more is needed and the data should accumulate. - * - * @throws Exception If the data cannot be decoded for any reason. - */ - private boolean doDecodePI(IoSession session, ByteBuffer in, ProtocolDecoderOutput out) throws Exception - { - boolean enoughData = _piDecoder.decodable(in.buf()); - if (!enoughData) - { - // returning false means it will leave the contents in the buffer and - // call us again when more data has been read - return false; - } - else - { - ProtocolInitiation pi = new ProtocolInitiation(in.buf()); - out.write(pi); - return true; - } - } /** * Sets the protocol initation flag, that determines whether decoding is handled by the data decoder of the protocol @@ -189,151 +90,168 @@ public class AMQDecoder extends CumulativeProtocolDecoder _expectProtocolInitiation = expectProtocolInitiation; } - - /** - * Cumulates content of <tt>in</tt> into internal buffer and forwards - * decoding request to {@link #doDecode(IoSession, ByteBuffer, ProtocolDecoderOutput)}. - * <tt>doDecode()</tt> is invoked repeatedly until it returns <tt>false</tt> - * and the cumulative buffer is compacted after decoding ends. - * - * @throws IllegalStateException if your <tt>doDecode()</tt> returned - * <tt>true</tt> not consuming the cumulative buffer. - */ - public void decode( IoSession session, ByteBuffer in, - ProtocolDecoderOutput out ) throws Exception + private class RemainingByteArrayInputStream extends InputStream { - ByteBuffer buf = ( ByteBuffer ) session.getAttribute( BUFFER ); - // if we have a session buffer, append data to that otherwise - // use the buffer read from the network directly - if( buf != null ) - { - buf.put( in ); - buf.flip(); - } - else + private int _currentListPos; + private int _markPos; + + + @Override + public int read() throws IOException { - buf = in; + ByteArrayInputStream currentStream = _remainingBufs.get(_currentListPos); + if(currentStream.available() > 0) + { + return currentStream.read(); + } + else if((_currentListPos == _remainingBufs.size()) + || (++_currentListPos == _remainingBufs.size())) + { + return -1; + } + else + { + + ByteArrayInputStream stream = _remainingBufs.get(_currentListPos); + stream.mark(0); + return stream.read(); + } } - for( ;; ) + @Override + public int read(final byte[] b, final int off, final int len) throws IOException { - int oldPos = buf.position(); - boolean decoded = doDecode( session, buf, out ); - if( decoded ) + + if(_currentListPos == _remainingBufs.size()) { - if( buf.position() == oldPos ) + return -1; + } + else + { + ByteArrayInputStream currentStream = _remainingBufs.get(_currentListPos); + final int available = currentStream.available(); + int read = currentStream.read(b, off, len > available ? available : len); + if(read < len) { - throw new IllegalStateException( - "doDecode() can't return true when buffer is not consumed." ); + if(_currentListPos++ != _remainingBufs.size()) + { + _remainingBufs.get(_currentListPos).mark(0); + } + int correctRead = read == -1 ? 0 : read; + int subRead = read(b, off+correctRead, len-correctRead); + if(subRead == -1) + { + return read; + } + else + { + return correctRead+subRead; + } } - - if( !buf.hasRemaining() ) + else { - break; + return len; } } - else - { - break; - } } - // if there is any data left that cannot be decoded, we store - // it in a buffer in the session and next time this decoder is - // invoked the session buffer gets appended to - if ( buf.hasRemaining() ) + @Override + public int available() throws IOException { - storeRemainingInSession( buf, session ); + int total = 0; + for(int i = _currentListPos; i < _remainingBufs.size(); i++) + { + total += _remainingBufs.get(i).available(); + } + return total; } - else + + @Override + public void mark(final int readlimit) { - removeSessionBuffer( session ); + _markPos = _currentListPos; + final ByteArrayInputStream stream = _remainingBufs.get(_currentListPos); + if(stream != null) + { + stream.mark(readlimit); + } } - } - - /** - * Releases the cumulative buffer used by the specified <tt>session</tt>. - * Please don't forget to call <tt>super.dispose( session )</tt> when - * you override this method. - */ - public void dispose( IoSession session ) throws Exception - { - removeSessionBuffer( session ); - } - private void removeSessionBuffer(IoSession session) - { - ByteBuffer buf = ( ByteBuffer ) session.getAttribute( BUFFER ); - if( buf != null ) + @Override + public void reset() throws IOException { - buf.release(); - session.removeAttribute( BUFFER ); + _currentListPos = _markPos; + final int size = _remainingBufs.size(); + if(_currentListPos < size) + { + _remainingBufs.get(_currentListPos).reset(); + } + for(int i = _currentListPos+1; i<size; i++) + { + _remainingBufs.get(i).reset(); + } } } - private static final SimpleByteBufferAllocator SIMPLE_BYTE_BUFFER_ALLOCATOR = new SimpleByteBufferAllocator(); - - private void storeRemainingInSession(ByteBuffer buf, IoSession session) - { - ByteBuffer remainingBuf = SIMPLE_BYTE_BUFFER_ALLOCATOR.allocate( buf.remaining(), false ); - remainingBuf.setAutoExpand( true ); - remainingBuf.put( buf ); - session.setAttribute( BUFFER, remainingBuf ); - } - public ArrayList<AMQDataBlock> decodeBuffer(java.nio.ByteBuffer buf) throws AMQFrameDecodingException, AMQProtocolVersionException + public ArrayList<AMQDataBlock> decodeBuffer(ByteBuffer buf) throws AMQFrameDecodingException, AMQProtocolVersionException, IOException { // get prior remaining data from accumulator ArrayList<AMQDataBlock> dataBlocks = new ArrayList<AMQDataBlock>(); - ByteBuffer msg; - // if we have a session buffer, append data to that otherwise - // use the buffer read from the network directly - if( _remainingBuf != null ) + DataInputStream msg; + + + ByteArrayInputStream bais = new ByteArrayInputStream(buf.array(),buf.arrayOffset()+buf.position(), buf.remaining()); + if(!_remainingBufs.isEmpty()) { - _remainingBuf.put(buf); - _remainingBuf.flip(); - msg = _remainingBuf; + _remainingBufs.add(bais); + msg = new DataInputStream(new RemainingByteArrayInputStream()); } else { - msg = ByteBuffer.wrap(buf); + msg = new DataInputStream(bais); } - - 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) { - boolean enoughData = true; - while (enoughData) + if(!_expectProtocolInitiation) { - int pos = msg.position(); - enoughData = _dataBlockDecoder.decodable(msg); - msg.position(pos); if (enoughData) { dataBlocks.add(_dataBlockDecoder.createAndPopulateFrame(_bodyFactory, msg)); } - else + } + else + { + enoughData = _piDecoder.decodable(msg); + if (enoughData) { - _remainingBuf = SIMPLE_BYTE_BUFFER_ALLOCATOR.allocate(msg.remaining(), false); - _remainingBuf.setAutoExpand(true); - _remainingBuf.put(msg); + dataBlocks.add(new ProtocolInitiation(msg)); + } + + } + + if(!enoughData) + { + if(!_remainingBufs.isEmpty()) + { + _remainingBufs.remove(_remainingBufs.size()-1); + ListIterator<ByteArrayInputStream> iterator = _remainingBufs.listIterator(); + while(iterator.hasNext() && iterator.next().available() == 0) + { + iterator.remove(); + } + } + if(bais.available()!=0) + { + byte[] remaining = new byte[bais.available()]; + bais.read(remaining); + _remainingBufs.add(new ByteArrayInputStream(remaining)); } } - } - if(firstDecode && dataBlocks.size() > 0) - { - firstDecode = false; } return dataBlocks; } diff --git a/java/common/src/main/java/org/apache/qpid/codec/AMQEncoder.java b/java/common/src/main/java/org/apache/qpid/codec/AMQEncoder.java deleted file mode 100644 index 53f48ae1c8..0000000000 --- a/java/common/src/main/java/org/apache/qpid/codec/AMQEncoder.java +++ /dev/null @@ -1,66 +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.codec; - -import org.apache.mina.common.IoSession; -import org.apache.mina.filter.codec.ProtocolEncoder; -import org.apache.mina.filter.codec.ProtocolEncoderOutput; - -import org.apache.qpid.framing.AMQDataBlockEncoder; - -/** - * AMQEncoder delegates encoding of AMQP to a data encoder. - * - * <p/><table id="crc"><caption>CRC Card</caption> - * <tr><th> Responsibilities <th> Collaborations - * <tr><td> Delegate AMQP encoding. <td> {@link AMQDataBlockEncoder} - * </table> - * - * @todo This class just delegates to another, so seems to be pointless. Unless it is going to handle some - * responsibilities in the future, then drop it. - */ -public class AMQEncoder implements ProtocolEncoder -{ - /** The data encoder that is delegated to. */ - private AMQDataBlockEncoder _dataBlockEncoder = new AMQDataBlockEncoder(); - - /** - * Encodes AMQP. - * - * @param session The Mina session. - * @param message The data object to encode. - * @param out The Mina writer to output the raw byte data to. - * - * @throws Exception If the data cannot be encoded for any reason. - */ - public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception - { - _dataBlockEncoder.encode(session, message, out); - } - - /** - * Does nothing. Called by Mina to allow this to clean up resources when it is no longer needed. - * - * @param session The Mina session. - */ - public void dispose(IoSession session) - { } -} diff --git a/java/common/src/main/java/org/apache/qpid/configuration/ClientProperties.java b/java/common/src/main/java/org/apache/qpid/configuration/ClientProperties.java index 0dd21238a7..62ded5b2d8 100644 --- a/java/common/src/main/java/org/apache/qpid/configuration/ClientProperties.java +++ b/java/common/src/main/java/org/apache/qpid/configuration/ClientProperties.java @@ -23,7 +23,7 @@ package org.apache.qpid.configuration; */ public class ClientProperties { - + /** * Currently with Qpid it is not possible to change the client ID. * If one is not specified upon connection construction, an id is generated automatically. @@ -68,67 +68,50 @@ public class ClientProperties * by the broker in TuneOK it will be used as the heartbeat interval. * If not a warning will be printed and the max value specified for * heartbeat in TuneOK will be used - * + * * The default idle timeout is set to 120 secs */ public static final String IDLE_TIMEOUT_PROP_NAME = "idle_timeout"; public static final long DEFAULT_IDLE_TIMEOUT = 120000; - + public static final String HEARTBEAT = "qpid.heartbeat"; public static final int HEARTBEAT_DEFAULT = 120; - + /** * This value will be used to determine the default destination syntax type. * Currently the two types are Binding URL (java only) and the Addressing format (used by - * all clients). + * all clients). */ public static final String DEST_SYNTAX = "qpid.dest_syntax"; - + public static final String USE_LEGACY_MAP_MESSAGE_FORMAT = "qpid.use_legacy_map_message"; - /** - * ========================================================== - * Those properties are used when the io size should be bounded - * ========================================================== - */ + public static final String AMQP_VERSION = "qpid.amqp.version"; - /** - * When set to true the io layer throttle down producers and consumers - * when written or read messages are accumulating and exceeding a certain size. - * This is especially useful when a the producer rate is greater than the network - * speed. - * type: boolean - */ - public static final String PROTECTIO_PROP_NAME = "protectio"; + public static final String QPID_VERIFY_CLIENT_ID = "qpid.verify_client_id"; - //=== The following properties are only used when the previous one is true. /** - * Max size of read messages that can be stored within the MINA layer - * type: int + * System properties to change the default timeout used during + * synchronous operations. */ - public static final String READ_BUFFER_LIMIT_PROP_NAME = "qpid.read.buffer.limit"; - public static final String READ_BUFFER_LIMIT_DEFAULT = "262144"; + public static final String QPID_SYNC_OP_TIMEOUT = "qpid.sync_op_timeout"; + public static final String AMQJ_DEFAULT_SYNCWRITE_TIMEOUT = "amqj.default_syncwrite_timeout"; + /** - * Max size of written messages that can be stored within the MINA layer - * type: int + * A default timeout value for synchronous operations */ - public static final String WRITE_BUFFER_LIMIT_PROP_NAME = "qpid.read.buffer.limit"; - public static final String WRITE_BUFFER_LIMIT_DEFAULT = "262144"; + public static final int DEFAULT_SYNC_OPERATION_TIMEOUT = 60000; - public static final String AMQP_VERSION = "qpid.amqp.version"; - - private static ClientProperties _instance = new ClientProperties(); - /* - public static final QpidProperty<Boolean> IGNORE_SET_CLIENTID_PROP_NAME = + public static final QpidProperty<Boolean> IGNORE_SET_CLIENTID_PROP_NAME = QpidProperty.booleanProperty(false,"qpid.ignore_set_client_id","ignore_setclientID"); - + public static final QpidProperty<Boolean> SYNC_PERSISTENT_PROP_NAME = QpidProperty.booleanProperty(false,"qpid.sync_persistence","sync_persistence"); - - + + public static final QpidProperty<Integer> MAX_PREFETCH_PROP_NAME = QpidProperty.intProperty(500,"qpid.max_prefetch","max_prefetch"); */ - - + + } diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQBody.java b/java/common/src/main/java/org/apache/qpid/framing/AMQBody.java index fe04155bb8..ebdad12178 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/AMQBody.java +++ b/java/common/src/main/java/org/apache/qpid/framing/AMQBody.java @@ -20,7 +20,9 @@ */ package org.apache.qpid.framing; -import org.apache.mina.common.ByteBuffer; +import java.io.DataOutputStream; +import java.io.IOException; + import org.apache.qpid.protocol.AMQVersionAwareProtocolSession; import org.apache.qpid.AMQException; @@ -34,7 +36,7 @@ public interface AMQBody */ public abstract int getSize(); - public void writePayload(ByteBuffer buffer); + public void writePayload(DataOutputStream buffer) throws IOException; - void handle(final int channelId, final AMQVersionAwareProtocolSession amqMinaProtocolSession) throws AMQException; + void handle(final int channelId, final AMQVersionAwareProtocolSession amqProtocolSession) throws AMQException; } diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlock.java b/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlock.java index a2fc3a03ef..00c1f5aae5 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlock.java +++ b/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlock.java @@ -20,7 +20,10 @@ */ package org.apache.qpid.framing; -import org.apache.mina.common.ByteBuffer; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + /** * A data block represents something that has a size in bytes and the ability to write itself to a byte @@ -39,25 +42,6 @@ public abstract class AMQDataBlock implements EncodableAMQDataBlock * Writes the datablock to the specified buffer. * @param buffer */ - public abstract void writePayload(ByteBuffer buffer); - - public ByteBuffer toByteBuffer() - { - final ByteBuffer buffer = ByteBuffer.allocate((int)getSize()); - - writePayload(buffer); - buffer.flip(); - return buffer; - } - - public java.nio.ByteBuffer toNioByteBuffer() - { - final java.nio.ByteBuffer buffer = java.nio.ByteBuffer.allocate((int) getSize()); - - ByteBuffer buf = ByteBuffer.wrap(buffer); - writePayload(buf); - buffer.flip(); - return buffer; - } + public abstract void writePayload(DataOutputStream buffer) throws IOException; } diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlockDecoder.java b/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlockDecoder.java index 228867b2b0..2165cadd14 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlockDecoder.java +++ b/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlockDecoder.java @@ -20,18 +20,14 @@ */ 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.protocol.AMQVersionAwareProtocolSession; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.DataInputStream; +import java.io.IOException; + public class AMQDataBlockDecoder { - private static final String SESSION_METHOD_BODY_FACTORY = "QPID_SESSION_METHOD_BODY_FACTORY"; private static final BodyFactory[] _bodiesSupported = new BodyFactory[Byte.MAX_VALUE]; @@ -47,27 +43,32 @@ public class AMQDataBlockDecoder public AMQDataBlockDecoder() { } - public boolean decodable(java.nio.ByteBuffer in) throws AMQFrameDecodingException + public boolean decodable(DataInputStream in) throws AMQFrameDecodingException, IOException { - final int remainingAfterAttributes = in.remaining() - (1 + 2 + 4 + 1); + final int remainingAfterAttributes = in.available() - (1 + 2 + 4 + 1); // type, channel, body length and end byte if (remainingAfterAttributes < 0) { return false; } - in.position(in.position() + 1 + 2); + in.mark(8); + in.skip(1 + 2); + + // Get an unsigned int, lifted from MINA ByteBuffer getUnsignedInt() - final long bodySize = in.getInt() & 0xffffffffL; + final long bodySize = in.readInt() & 0xffffffffL; + + in.reset(); return (remainingAfterAttributes >= bodySize); } - public AMQFrame createAndPopulateFrame(AMQMethodBodyFactory methodBodyFactory, ByteBuffer in) - throws AMQFrameDecodingException, AMQProtocolVersionException + public AMQFrame createAndPopulateFrame(AMQMethodBodyFactory methodBodyFactory, DataInputStream in) + throws AMQFrameDecodingException, AMQProtocolVersionException, IOException { - final byte type = in.get(); + final byte type = in.readByte(); BodyFactory bodyFactory; if (type == AMQMethodBody.TYPE) @@ -84,8 +85,8 @@ public class AMQDataBlockDecoder throw new AMQFrameDecodingException(null, "Unsupported frame type: " + type, null); } - final int channel = in.getUnsignedShort(); - final long bodySize = in.getUnsignedInt(); + final int channel = in.readUnsignedShort(); + final long bodySize = EncodingUtils.readUnsignedInteger(in); // bodySize can be zero if ((channel < 0) || (bodySize < 0)) @@ -96,7 +97,7 @@ public class AMQDataBlockDecoder AMQFrame frame = new AMQFrame(in, channel, bodySize, bodyFactory); - byte marker = in.get(); + byte marker = in.readByte(); if ((marker & 0xFF) != 0xCE) { throw new AMQFrameDecodingException(null, "End of frame marker not found. Read " + marker + " length=" + bodySize @@ -106,26 +107,4 @@ public class AMQDataBlockDecoder return frame; } - public void decode(IoSession session, ByteBuffer in, ProtocolDecoderOutput out) throws Exception - { - 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/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlockEncoder.java b/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlockEncoder.java deleted file mode 100644 index 374644b4f2..0000000000 --- a/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlockEncoder.java +++ /dev/null @@ -1,61 +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.framing; - -import org.apache.mina.common.ByteBuffer; -import org.apache.mina.common.IoSession; -import org.apache.mina.filter.codec.ProtocolEncoderOutput; -import org.apache.mina.filter.codec.demux.MessageEncoder; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Collections; -import java.util.Set; - -public final class AMQDataBlockEncoder implements MessageEncoder -{ - private static final Logger _logger = LoggerFactory.getLogger(AMQDataBlockEncoder.class); - - private final Set _messageTypes = Collections.singleton(EncodableAMQDataBlock.class); - - public AMQDataBlockEncoder() - { } - - public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception - { - final AMQDataBlock frame = (AMQDataBlock) message; - - final ByteBuffer buffer = frame.toByteBuffer(); - - if (_logger.isDebugEnabled()) - { - _logger.debug("Encoded frame byte-buffer is '" + EncodingUtils.convertToHexString(buffer) + "'"); - } - - out.write(buffer); - } - - public Set getMessageTypes() - { - return _messageTypes; - } -} diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQFrame.java b/java/common/src/main/java/org/apache/qpid/framing/AMQFrame.java index 02a46f3748..6acf60a5b3 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/AMQFrame.java +++ b/java/common/src/main/java/org/apache/qpid/framing/AMQFrame.java @@ -20,7 +20,9 @@ */ package org.apache.qpid.framing; -import org.apache.mina.common.ByteBuffer; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; public class AMQFrame extends AMQDataBlock implements EncodableAMQDataBlock { @@ -36,7 +38,7 @@ public class AMQFrame extends AMQDataBlock implements EncodableAMQDataBlock _bodyFrame = bodyFrame; } - public AMQFrame(final ByteBuffer in, final int channel, final long bodySize, final BodyFactory bodyFactory) throws AMQFrameDecodingException + public AMQFrame(final DataInputStream in, final int channel, final long bodySize, final BodyFactory bodyFactory) throws AMQFrameDecodingException, IOException { this._channel = channel; this._bodyFrame = bodyFactory.createBody(in,bodySize); @@ -53,13 +55,13 @@ public class AMQFrame extends AMQDataBlock implements EncodableAMQDataBlock } - public void writePayload(ByteBuffer buffer) + public void writePayload(DataOutputStream buffer) throws IOException { - buffer.put(_bodyFrame.getFrameType()); + buffer.writeByte(_bodyFrame.getFrameType()); EncodingUtils.writeUnsignedShort(buffer, _channel); EncodingUtils.writeUnsignedInteger(buffer, _bodyFrame.getSize()); _bodyFrame.writePayload(buffer); - buffer.put(FRAME_END_BYTE); + buffer.writeByte(FRAME_END_BYTE); } public final int getChannel() @@ -77,48 +79,48 @@ public class AMQFrame extends AMQDataBlock implements EncodableAMQDataBlock return "Frame channelId: " + _channel + ", bodyFrame: " + String.valueOf(_bodyFrame); } - public static void writeFrame(ByteBuffer buffer, final int channel, AMQBody body) + public static void writeFrame(DataOutputStream buffer, final int channel, AMQBody body) throws IOException { - buffer.put(body.getFrameType()); + buffer.writeByte(body.getFrameType()); EncodingUtils.writeUnsignedShort(buffer, channel); EncodingUtils.writeUnsignedInteger(buffer, body.getSize()); body.writePayload(buffer); - buffer.put(FRAME_END_BYTE); + buffer.writeByte(FRAME_END_BYTE); } - public static void writeFrames(ByteBuffer buffer, final int channel, AMQBody body1, AMQBody body2) + public static void writeFrames(DataOutputStream buffer, final int channel, AMQBody body1, AMQBody body2) throws IOException { - buffer.put(body1.getFrameType()); + buffer.writeByte(body1.getFrameType()); EncodingUtils.writeUnsignedShort(buffer, channel); EncodingUtils.writeUnsignedInteger(buffer, body1.getSize()); body1.writePayload(buffer); - buffer.put(FRAME_END_BYTE); - buffer.put(body2.getFrameType()); + buffer.writeByte(FRAME_END_BYTE); + buffer.writeByte(body2.getFrameType()); EncodingUtils.writeUnsignedShort(buffer, channel); EncodingUtils.writeUnsignedInteger(buffer, body2.getSize()); body2.writePayload(buffer); - buffer.put(FRAME_END_BYTE); + buffer.writeByte(FRAME_END_BYTE); } - public static void writeFrames(ByteBuffer buffer, final int channel, AMQBody body1, AMQBody body2, AMQBody body3) + public static void writeFrames(DataOutputStream buffer, final int channel, AMQBody body1, AMQBody body2, AMQBody body3) throws IOException { - buffer.put(body1.getFrameType()); + buffer.writeByte(body1.getFrameType()); EncodingUtils.writeUnsignedShort(buffer, channel); EncodingUtils.writeUnsignedInteger(buffer, body1.getSize()); body1.writePayload(buffer); - buffer.put(FRAME_END_BYTE); - buffer.put(body2.getFrameType()); + buffer.writeByte(FRAME_END_BYTE); + buffer.writeByte(body2.getFrameType()); EncodingUtils.writeUnsignedShort(buffer, channel); EncodingUtils.writeUnsignedInteger(buffer, body2.getSize()); body2.writePayload(buffer); - buffer.put(FRAME_END_BYTE); - buffer.put(body3.getFrameType()); + buffer.writeByte(FRAME_END_BYTE); + buffer.writeByte(body3.getFrameType()); EncodingUtils.writeUnsignedShort(buffer, channel); EncodingUtils.writeUnsignedInteger(buffer, body3.getSize()); body3.writePayload(buffer); - buffer.put(FRAME_END_BYTE); + buffer.writeByte(FRAME_END_BYTE); } diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBody.java b/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBody.java index 4763b22290..a076d0e5a1 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBody.java +++ b/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBody.java @@ -20,12 +20,14 @@ */ package org.apache.qpid.framing; -import org.apache.mina.common.ByteBuffer; import org.apache.qpid.AMQChannelException; import org.apache.qpid.AMQConnectionException; import org.apache.qpid.AMQException; import org.apache.qpid.protocol.AMQConstant; +import java.io.DataOutputStream; +import java.io.IOException; + public interface AMQMethodBody extends AMQBody { public static final byte TYPE = 1; @@ -43,12 +45,12 @@ public interface AMQMethodBody extends AMQBody /** @return unsigned short */ public int getMethod(); - public void writeMethodPayload(ByteBuffer buffer); + public void writeMethodPayload(DataOutputStream buffer) throws IOException; public int getSize(); - public void writePayload(ByteBuffer buffer); + public void writePayload(DataOutputStream buffer) throws IOException; //public abstract void populateMethodBodyFromBuffer(ByteBuffer buffer) throws AMQFrameDecodingException; diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyFactory.java b/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyFactory.java index 1a7022c11b..7fceb082ee 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyFactory.java +++ b/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyFactory.java @@ -20,13 +20,14 @@ */ package org.apache.qpid.framing; -import org.apache.mina.common.ByteBuffer; - import org.apache.qpid.protocol.AMQVersionAwareProtocolSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.DataInputStream; +import java.io.IOException; + public class AMQMethodBodyFactory implements BodyFactory { private static final Logger _log = LoggerFactory.getLogger(AMQMethodBodyFactory.class); @@ -38,7 +39,7 @@ public class AMQMethodBodyFactory implements BodyFactory _protocolSession = protocolSession; } - public AMQBody createBody(ByteBuffer in, long bodySize) throws AMQFrameDecodingException + public AMQBody createBody(DataInputStream in, long bodySize) throws AMQFrameDecodingException, IOException { return _protocolSession.getMethodRegistry().convertToBody(in, bodySize); } diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyImpl.java b/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyImpl.java index cd3d721065..c73c1df701 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyImpl.java +++ b/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyImpl.java @@ -21,13 +21,16 @@ package org.apache.qpid.framing; * */ -import org.apache.mina.common.ByteBuffer; import org.apache.qpid.AMQChannelException; import org.apache.qpid.AMQConnectionException; import org.apache.qpid.AMQException; import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.protocol.AMQVersionAwareProtocolSession; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + public abstract class AMQMethodBodyImpl implements AMQMethodBody { public static final byte TYPE = 1; @@ -98,7 +101,7 @@ public abstract class AMQMethodBodyImpl implements AMQMethodBody return 2 + 2 + getBodySize(); } - public void writePayload(ByteBuffer buffer) + public void writePayload(DataOutputStream buffer) throws IOException { EncodingUtils.writeUnsignedShort(buffer, getClazz()); EncodingUtils.writeUnsignedShort(buffer, getMethod()); @@ -106,12 +109,12 @@ public abstract class AMQMethodBodyImpl implements AMQMethodBody } - protected byte readByte(ByteBuffer buffer) + protected byte readByte(DataInputStream buffer) throws IOException { - return buffer.get(); + return buffer.readByte(); } - protected AMQShortString readAMQShortString(ByteBuffer buffer) + protected AMQShortString readAMQShortString(DataInputStream buffer) throws IOException { return EncodingUtils.readAMQShortString(buffer); } @@ -121,27 +124,27 @@ public abstract class AMQMethodBodyImpl implements AMQMethodBody return EncodingUtils.encodedShortStringLength(string); } - protected void writeByte(ByteBuffer buffer, byte b) + protected void writeByte(DataOutputStream buffer, byte b) throws IOException { - buffer.put(b); + buffer.writeByte(b); } - protected void writeAMQShortString(ByteBuffer buffer, AMQShortString string) + protected void writeAMQShortString(DataOutputStream buffer, AMQShortString string) throws IOException { EncodingUtils.writeShortStringBytes(buffer, string); } - protected int readInt(ByteBuffer buffer) + protected int readInt(DataInputStream buffer) throws IOException { - return buffer.getInt(); + return buffer.readInt(); } - protected void writeInt(ByteBuffer buffer, int i) + protected void writeInt(DataOutputStream buffer, int i) throws IOException { - buffer.putInt(i); + buffer.writeInt(i); } - protected FieldTable readFieldTable(ByteBuffer buffer) throws AMQFrameDecodingException + protected FieldTable readFieldTable(DataInputStream buffer) throws AMQFrameDecodingException, IOException { return EncodingUtils.readFieldTable(buffer); } @@ -151,19 +154,19 @@ public abstract class AMQMethodBodyImpl implements AMQMethodBody return EncodingUtils.encodedFieldTableLength(table); //To change body of created methods use File | Settings | File Templates. } - protected void writeFieldTable(ByteBuffer buffer, FieldTable table) + protected void writeFieldTable(DataOutputStream buffer, FieldTable table) throws IOException { EncodingUtils.writeFieldTableBytes(buffer, table); } - protected long readLong(ByteBuffer buffer) + protected long readLong(DataInputStream buffer) throws IOException { - return buffer.getLong(); + return buffer.readLong(); } - protected void writeLong(ByteBuffer buffer, long l) + protected void writeLong(DataOutputStream buffer, long l) throws IOException { - buffer.putLong(l); + buffer.writeLong(l); } protected int getSizeOf(byte[] response) @@ -171,87 +174,86 @@ public abstract class AMQMethodBodyImpl implements AMQMethodBody return (response == null) ? 4 : response.length + 4; } - protected void writeBytes(ByteBuffer buffer, byte[] data) + protected void writeBytes(DataOutputStream buffer, byte[] data) throws IOException { EncodingUtils.writeBytes(buffer,data); } - protected byte[] readBytes(ByteBuffer buffer) + protected byte[] readBytes(DataInputStream buffer) throws IOException { return EncodingUtils.readBytes(buffer); } - protected short readShort(ByteBuffer buffer) + protected short readShort(DataInputStream buffer) throws IOException { return EncodingUtils.readShort(buffer); } - protected void writeShort(ByteBuffer buffer, short s) + protected void writeShort(DataOutputStream buffer, short s) throws IOException { EncodingUtils.writeShort(buffer, s); } - protected Content readContent(ByteBuffer buffer) + protected Content readContent(DataInputStream buffer) { - return null; //To change body of created methods use File | Settings | File Templates. + return null; } protected int getSizeOf(Content body) { - return 0; //To change body of created methods use File | Settings | File Templates. + return 0; } - protected void writeContent(ByteBuffer buffer, Content body) + protected void writeContent(DataOutputStream buffer, Content body) { - //To change body of created methods use File | Settings | File Templates. } - protected byte readBitfield(ByteBuffer buffer) + protected byte readBitfield(DataInputStream buffer) throws IOException { - return readByte(buffer); //To change body of created methods use File | Settings | File Templates. + return readByte(buffer); } - protected int readUnsignedShort(ByteBuffer buffer) + protected int readUnsignedShort(DataInputStream buffer) throws IOException { - return buffer.getUnsignedShort(); //To change body of created methods use File | Settings | File Templates. + return buffer.readUnsignedShort(); } - protected void writeBitfield(ByteBuffer buffer, byte bitfield0) + protected void writeBitfield(DataOutputStream buffer, byte bitfield0) throws IOException { - buffer.put(bitfield0); + buffer.writeByte(bitfield0); } - protected void writeUnsignedShort(ByteBuffer buffer, int s) + protected void writeUnsignedShort(DataOutputStream buffer, int s) throws IOException { EncodingUtils.writeUnsignedShort(buffer, s); } - protected long readUnsignedInteger(ByteBuffer buffer) + protected long readUnsignedInteger(DataInputStream buffer) throws IOException { - return buffer.getUnsignedInt(); + return EncodingUtils.readUnsignedInteger(buffer); } - protected void writeUnsignedInteger(ByteBuffer buffer, long i) + protected void writeUnsignedInteger(DataOutputStream buffer, long i) throws IOException { EncodingUtils.writeUnsignedInteger(buffer, i); } - protected short readUnsignedByte(ByteBuffer buffer) + protected short readUnsignedByte(DataInputStream buffer) throws IOException { - return buffer.getUnsigned(); + return (short) buffer.readUnsignedByte(); } - protected void writeUnsignedByte(ByteBuffer buffer, short unsignedByte) + protected void writeUnsignedByte(DataOutputStream buffer, short unsignedByte) throws IOException { EncodingUtils.writeUnsignedByte(buffer, unsignedByte); } - protected long readTimestamp(ByteBuffer buffer) + protected long readTimestamp(DataInputStream buffer) throws IOException { return EncodingUtils.readTimestamp(buffer); } - protected void writeTimestamp(ByteBuffer buffer, long t) + protected void writeTimestamp(DataOutputStream buffer, long t) throws IOException { EncodingUtils.writeTimestamp(buffer, t); } diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyInstanceFactory.java b/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyInstanceFactory.java index 0c61d9db3c..df4d8bdcb6 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyInstanceFactory.java +++ b/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyInstanceFactory.java @@ -21,10 +21,11 @@ package org.apache.qpid.framing; -import org.apache.mina.common.ByteBuffer; +import java.io.DataInputStream; +import java.io.IOException; public abstract interface AMQMethodBodyInstanceFactory { - public AMQMethodBody newInstance(ByteBuffer buffer, long size) throws AMQFrameDecodingException; + public AMQMethodBody newInstance(DataInputStream buffer, long size) throws AMQFrameDecodingException, IOException; } diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQMethodFactory.java b/java/common/src/main/java/org/apache/qpid/framing/AMQMethodFactory.java deleted file mode 100644 index bfcc38ad60..0000000000 --- a/java/common/src/main/java/org/apache/qpid/framing/AMQMethodFactory.java +++ /dev/null @@ -1,90 +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.framing; - -import org.apache.mina.common.ByteBuffer; - - -public interface AMQMethodFactory -{ - - // Connection Methods - - ConnectionCloseBody createConnectionClose(); - - // Access Methods - - AccessRequestBody createAccessRequest(boolean active, boolean exclusive, boolean passive, boolean read, AMQShortString realm, boolean write); - - - // Tx Methods - - TxSelectBody createTxSelect(); - - TxCommitBody createTxCommit(); - - TxRollbackBody createTxRollback(); - - // Channel Methods - - ChannelOpenBody createChannelOpen(); - - ChannelCloseBody createChannelClose(int replyCode, AMQShortString replyText); - - ChannelFlowBody createChannelFlow(boolean active); - - - // Exchange Methods - - - ExchangeBoundBody createExchangeBound(AMQShortString exchangeName, - AMQShortString queueName, - AMQShortString routingKey); - - ExchangeDeclareBody createExchangeDeclare(AMQShortString name, AMQShortString type, int ticket); - - - // Queue Methods - - QueueDeclareBody createQueueDeclare(AMQShortString name, FieldTable arguments, boolean autoDelete, boolean durable, boolean exclusive, boolean passive, int ticket); - - QueueBindBody createQueueBind(AMQShortString queueName, AMQShortString exchangeName, AMQShortString routingKey, FieldTable arguments, int ticket); - - QueueDeleteBody createQueueDelete(AMQShortString queueName, boolean ifEmpty, boolean ifUnused, int ticket); - - - // Message Methods - - // In different versions of the protocol we change the class used for message transfer - // abstract this out so the appropriate methods are created - AMQMethodBody createRecover(boolean requeue); - - AMQMethodBody createConsumer(AMQShortString tag, AMQShortString queueName, FieldTable arguments, boolean noAck, boolean exclusive, boolean noLocal, int ticket); - - AMQMethodBody createConsumerCancel(AMQShortString consumerTag); - - AMQMethodBody createAcknowledge(long deliveryTag, boolean multiple); - - AMQMethodBody createRejectBody(long deliveryTag, boolean requeue); - - AMQMethodBody createMessageQos(int prefetchCount, int prefetchSize); - -} diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java b/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java index 39a9beb9e8..cc9a33f4cf 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java +++ b/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java @@ -21,11 +21,12 @@ package org.apache.qpid.framing; -import org.apache.mina.common.ByteBuffer; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; import java.util.*; import java.lang.ref.WeakReference; @@ -37,6 +38,10 @@ import java.lang.ref.WeakReference; */ public final class AMQShortString implements CharSequence, Comparable<AMQShortString> { + /** + * The maximum number of octets in AMQ short string as defined in AMQP specification + */ + public static final int MAX_LENGTH = 255; private static final byte MINUS = (byte)'-'; private static final byte ZERO = (byte) '0'; @@ -118,22 +123,19 @@ public final class AMQShortString implements CharSequence, Comparable<AMQShortSt public AMQShortString(byte[] data) { - + if (data == null) + { + throw new NullPointerException("Cannot create AMQShortString with null data[]"); + } + if (data.length > MAX_LENGTH) + { + throw new IllegalArgumentException("Cannot create AMQShortString with number of octets over 255!"); + } _data = data.clone(); _length = data.length; _offset = 0; } - public AMQShortString(byte[] data, int pos) - { - final int size = data[pos++]; - final byte[] dataCopy = new byte[size]; - System.arraycopy(data,pos,dataCopy,0,size); - _length = size; - _data = dataCopy; - _offset = 0; - } - public AMQShortString(String data) { this((data == null) ? EMPTY_CHAR_ARRAY : data.toCharArray()); @@ -146,7 +148,12 @@ public final class AMQShortString implements CharSequence, Comparable<AMQShortSt { throw new NullPointerException("Cannot create AMQShortString with null char[]"); } - + // the current implementation of 0.8/0.9.x short string encoding + // supports only ASCII characters + if (data.length> MAX_LENGTH) + { + throw new IllegalArgumentException("Cannot create AMQShortString with number of octets over 255!"); + } final int length = data.length; final byte[] stringBytes = new byte[length]; int hash = 0; @@ -165,6 +172,17 @@ public final class AMQShortString implements CharSequence, Comparable<AMQShortSt public AMQShortString(CharSequence charSequence) { + if (charSequence == null) + { + // it should be possible to create short string for null data + charSequence = ""; + } + // the current implementation of 0.8/0.9.x short string encoding + // supports only ASCII characters + if (charSequence.length() > MAX_LENGTH) + { + throw new IllegalArgumentException("Cannot create AMQShortString with number of octets over 255!"); + } final int length = charSequence.length(); final byte[] stringBytes = new byte[length]; int hash = 0; @@ -182,31 +200,33 @@ public final class AMQShortString implements CharSequence, Comparable<AMQShortSt } - private AMQShortString(ByteBuffer data, final int length) + private AMQShortString(DataInputStream data, final int length) throws IOException { - if(data.isDirect() || data.isReadOnly()) - { - byte[] dataBytes = new byte[length]; - data.get(dataBytes); - _data = dataBytes; - _offset = 0; - } - else + if (length > MAX_LENGTH) { - - _data = data.array(); - _offset = data.arrayOffset() + data.position(); - data.skip(length); - + throw new IllegalArgumentException("Cannot create AMQShortString with number of octets over 255!"); } + byte[] dataBytes = new byte[length]; + data.read(dataBytes); + _data = dataBytes; + _offset = 0; _length = length; } private AMQShortString(final byte[] data, final int from, final int to) { + if (data == null) + { + throw new NullPointerException("Cannot create AMQShortString with null data[]"); + } + int length = to - from; + if (length > MAX_LENGTH) + { + throw new IllegalArgumentException("Cannot create AMQShortString with number of octets over 255!"); + } _offset = from; - _length = to - from; + _length = length; _data = data; } @@ -245,32 +265,9 @@ public final class AMQShortString implements CharSequence, Comparable<AMQShortSt return new CharSubSequence(start, end); } - public int writeToByteArray(byte[] encoding, int pos) - { - final int size = length(); - encoding[pos++] = (byte) size; - System.arraycopy(_data,_offset,encoding,pos,size); - return pos+size; - } - - public static AMQShortString readFromByteArray(byte[] byteEncodedDestination, int pos) - { - - - final AMQShortString shortString = new AMQShortString(byteEncodedDestination, pos); - if(shortString.length() == 0) - { - return null; - } - else - { - return shortString; - } - } - - public static AMQShortString readFromBuffer(ByteBuffer buffer) + public static AMQShortString readFromBuffer(DataInputStream buffer) throws IOException { - final short length = buffer.getUnsigned(); + final int length = buffer.readUnsignedByte(); if (length == 0) { return null; @@ -296,13 +293,13 @@ public final class AMQShortString implements CharSequence, Comparable<AMQShortSt } } - public void writeToBuffer(ByteBuffer buffer) + public void writeToBuffer(DataOutputStream buffer) throws IOException { final int size = length(); //buffer.setAutoExpand(true); - buffer.put((byte) size); - buffer.put(_data, _offset, size); + buffer.write((byte) size); + buffer.write(_data, _offset, size); } @@ -690,6 +687,10 @@ public final class AMQShortString implements CharSequence, Comparable<AMQShortSt size += term.length(); } + if (size > MAX_LENGTH) + { + throw new IllegalArgumentException("Cannot create AMQShortString with number of octets over 255!"); + } byte[] data = new byte[size]; int pos = 0; final byte[] delimData = delim._data; diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQType.java b/java/common/src/main/java/org/apache/qpid/framing/AMQType.java index 14fb63da03..f3da64e639 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/AMQType.java +++ b/java/common/src/main/java/org/apache/qpid/framing/AMQType.java @@ -20,8 +20,9 @@ */ package org.apache.qpid.framing; -import org.apache.mina.common.ByteBuffer; - +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; import java.math.BigDecimal; /** @@ -60,12 +61,12 @@ public enum AMQType } } - public void writeValueImpl(Object value, ByteBuffer buffer) + public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException { EncodingUtils.writeLongStringBytes(buffer, (String) value); } - public Object readValueFromBuffer(ByteBuffer buffer) + public Object readValueFromBuffer(DataInputStream buffer) throws IOException { return EncodingUtils.readLongString(buffer); } @@ -106,12 +107,12 @@ public enum AMQType } } - public void writeValueImpl(Object value, ByteBuffer buffer) + public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException { EncodingUtils.writeUnsignedInteger(buffer, (Long) value); } - public Object readValueFromBuffer(ByteBuffer buffer) + public Object readValueFromBuffer(DataInputStream buffer) throws IOException { return EncodingUtils.readUnsignedInteger(buffer); } @@ -137,7 +138,7 @@ public enum AMQType } } - public void writeValueImpl(Object value, ByteBuffer buffer) + public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException { BigDecimal bd = (BigDecimal) value; @@ -150,7 +151,7 @@ public enum AMQType EncodingUtils.writeInteger(buffer, unscaled); } - public Object readValueFromBuffer(ByteBuffer buffer) + public Object readValueFromBuffer(DataInputStream buffer) throws IOException { byte places = EncodingUtils.readByte(buffer); @@ -182,12 +183,12 @@ public enum AMQType } } - public void writeValueImpl(Object value, ByteBuffer buffer) + public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException { EncodingUtils.writeLong(buffer, (Long) value); } - public Object readValueFromBuffer(ByteBuffer buffer) + public Object readValueFromBuffer(DataInputStream buffer) throws IOException { return EncodingUtils.readLong(buffer); } @@ -246,7 +247,7 @@ public enum AMQType * @param value An instance of the type. * @param buffer The byte buffer to write it to. */ - public void writeValueImpl(Object value, ByteBuffer buffer) + public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException { // Ensure that the value is a FieldTable. if (!(value instanceof FieldTable)) @@ -267,7 +268,7 @@ public enum AMQType * * @return An instance of the type. */ - public Object readValueFromBuffer(ByteBuffer buffer) + public Object readValueFromBuffer(DataInputStream buffer) throws IOException { try { @@ -301,10 +302,10 @@ public enum AMQType } } - public void writeValueImpl(Object value, ByteBuffer buffer) + public void writeValueImpl(Object value, DataOutputStream buffer) { } - public Object readValueFromBuffer(ByteBuffer buffer) + public Object readValueFromBuffer(DataInputStream buffer) { return null; } @@ -330,12 +331,12 @@ public enum AMQType } } - public void writeValueImpl(Object value, ByteBuffer buffer) + public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException { EncodingUtils.writeLongstr(buffer, (byte[]) value); } - public Object readValueFromBuffer(ByteBuffer buffer) + public Object readValueFromBuffer(DataInputStream buffer) throws IOException { return EncodingUtils.readLongstr(buffer); } @@ -360,12 +361,12 @@ public enum AMQType } } - public void writeValueImpl(Object value, ByteBuffer buffer) + public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException { EncodingUtils.writeLongStringBytes(buffer, (String) value); } - public Object readValueFromBuffer(ByteBuffer buffer) + public Object readValueFromBuffer(DataInputStream buffer) throws IOException { return EncodingUtils.readLongString(buffer); } @@ -391,12 +392,12 @@ public enum AMQType } } - public void writeValueImpl(Object value, ByteBuffer buffer) + public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException { EncodingUtils.writeLongStringBytes(buffer, (String) value); } - public Object readValueFromBuffer(ByteBuffer buffer) + public Object readValueFromBuffer(DataInputStream buffer) throws IOException { return EncodingUtils.readLongString(buffer); } @@ -426,12 +427,12 @@ public enum AMQType } } - public void writeValueImpl(Object value, ByteBuffer buffer) + public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException { EncodingUtils.writeBoolean(buffer, (Boolean) value); } - public Object readValueFromBuffer(ByteBuffer buffer) + public Object readValueFromBuffer(DataInputStream buffer) throws IOException { return EncodingUtils.readBoolean(buffer); } @@ -461,12 +462,12 @@ public enum AMQType } } - public void writeValueImpl(Object value, ByteBuffer buffer) + public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException { EncodingUtils.writeChar(buffer, (Character) value); } - public Object readValueFromBuffer(ByteBuffer buffer) + public Object readValueFromBuffer(DataInputStream buffer) throws IOException { return EncodingUtils.readChar(buffer); } @@ -496,12 +497,12 @@ public enum AMQType } } - public void writeValueImpl(Object value, ByteBuffer buffer) + public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException { EncodingUtils.writeByte(buffer, (Byte) value); } - public Object readValueFromBuffer(ByteBuffer buffer) + public Object readValueFromBuffer(DataInputStream buffer) throws IOException { return EncodingUtils.readByte(buffer); } @@ -535,12 +536,12 @@ public enum AMQType } } - public void writeValueImpl(Object value, ByteBuffer buffer) + public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException { EncodingUtils.writeShort(buffer, (Short) value); } - public Object readValueFromBuffer(ByteBuffer buffer) + public Object readValueFromBuffer(DataInputStream buffer) throws IOException { return EncodingUtils.readShort(buffer); } @@ -577,12 +578,12 @@ public enum AMQType } } - public void writeValueImpl(Object value, ByteBuffer buffer) + public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException { EncodingUtils.writeInteger(buffer, (Integer) value); } - public Object readValueFromBuffer(ByteBuffer buffer) + public Object readValueFromBuffer(DataInputStream buffer) throws IOException { return EncodingUtils.readInteger(buffer); } @@ -624,12 +625,12 @@ public enum AMQType } } - public void writeValueImpl(Object value, ByteBuffer buffer) + public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException { EncodingUtils.writeLong(buffer, (Long) value); } - public Object readValueFromBuffer(ByteBuffer buffer) + public Object readValueFromBuffer(DataInputStream buffer) throws IOException { return EncodingUtils.readLong(buffer); } @@ -659,12 +660,12 @@ public enum AMQType } } - public void writeValueImpl(Object value, ByteBuffer buffer) + public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException { EncodingUtils.writeFloat(buffer, (Float) value); } - public Object readValueFromBuffer(ByteBuffer buffer) + public Object readValueFromBuffer(DataInputStream buffer) throws IOException { return EncodingUtils.readFloat(buffer); } @@ -698,12 +699,12 @@ public enum AMQType } } - public void writeValueImpl(Object value, ByteBuffer buffer) + public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException { EncodingUtils.writeDouble(buffer, (Double) value); } - public Object readValueFromBuffer(ByteBuffer buffer) + public Object readValueFromBuffer(DataInputStream buffer) throws IOException { return EncodingUtils.readDouble(buffer); } @@ -770,9 +771,9 @@ public enum AMQType * @param value An instance of the type. * @param buffer The byte buffer to write it to. */ - public void writeToBuffer(Object value, ByteBuffer buffer) + public void writeToBuffer(Object value, DataOutputStream buffer) throws IOException { - buffer.put(identifier()); + buffer.writeByte(identifier()); writeValueImpl(value, buffer); } @@ -782,7 +783,7 @@ public enum AMQType * @param value An instance of the type. * @param buffer The byte buffer to write it to. */ - abstract void writeValueImpl(Object value, ByteBuffer buffer); + abstract void writeValueImpl(Object value, DataOutputStream buffer) throws IOException; /** * Reads an instance of the type from a specified byte buffer. @@ -791,5 +792,5 @@ public enum AMQType * * @return An instance of the type. */ - abstract Object readValueFromBuffer(ByteBuffer buffer); + abstract Object readValueFromBuffer(DataInputStream buffer) throws IOException; } diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java b/java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java index 647d531476..1dbedca362 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java +++ b/java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java @@ -20,8 +20,9 @@ */ package org.apache.qpid.framing; -import org.apache.mina.common.ByteBuffer; - +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; import java.util.Date; import java.util.Map; import java.math.BigDecimal; @@ -60,7 +61,7 @@ public class AMQTypedValue _value = type.toNativeValue(value); } - private AMQTypedValue(AMQType type, ByteBuffer buffer) + private AMQTypedValue(AMQType type, DataInputStream buffer) throws IOException { _type = type; _value = type.readValueFromBuffer(buffer); @@ -76,7 +77,7 @@ public class AMQTypedValue return _value; } - public void writeToBuffer(ByteBuffer buffer) + public void writeToBuffer(DataOutputStream buffer) throws IOException { _type.writeToBuffer(_value, buffer); } @@ -86,9 +87,9 @@ public class AMQTypedValue return _type.getEncodingSize(_value); } - public static AMQTypedValue readFromBuffer(ByteBuffer buffer) + public static AMQTypedValue readFromBuffer(DataInputStream buffer) throws IOException { - AMQType type = AMQTypeMap.getType(buffer.get()); + AMQType type = AMQTypeMap.getType(buffer.readByte()); return new AMQTypedValue(type, buffer); } diff --git a/java/common/src/main/java/org/apache/qpid/framing/BasicContentHeaderProperties.java b/java/common/src/main/java/org/apache/qpid/framing/BasicContentHeaderProperties.java index c7d89a9927..57622b5054 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/BasicContentHeaderProperties.java +++ b/java/common/src/main/java/org/apache/qpid/framing/BasicContentHeaderProperties.java @@ -20,7 +20,9 @@ */ package org.apache.qpid.framing; -import org.apache.mina.common.ByteBuffer; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -35,27 +37,6 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti private static final AMQShortString ZERO_STRING = null; - /** - * We store the encoded form when we decode the content header so that if we need to write it out without modifying - * it we can do so without incurring the expense of reencoding it - */ - private byte[] _encodedForm; - - /** Flag indicating whether the entire content header has been decoded yet */ - private boolean _decoded = true; - - /** - * We have some optimisations for partial decoding for maximum performance. The headers are used in the broker for - * routing in some cases so we can decode that separately. - */ - private boolean _decodedHeaders = true; - - /** - * We have some optimisations for partial decoding for maximum performance. The content type is used by all clients - * to determine the message type - */ - private boolean _decodedContentType = true; - private AMQShortString _contentType; private AMQShortString _encoding; @@ -86,10 +67,10 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti private int _propertyFlags = 0; private static final int CONTENT_TYPE_MASK = 1 << 15; - private static final int ENCONDING_MASK = 1 << 14; + private static final int ENCODING_MASK = 1 << 14; private static final int HEADERS_MASK = 1 << 13; private static final int DELIVERY_MODE_MASK = 1 << 12; - private static final int PROPRITY_MASK = 1 << 11; + private static final int PRIORITY_MASK = 1 << 11; private static final int CORRELATION_ID_MASK = 1 << 10; private static final int REPLY_TO_MASK = 1 << 9; private static final int EXPIRATION_MASK = 1 << 8; @@ -101,34 +82,11 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti private static final int CLUSTER_ID_MASK = 1 << 2; - /** - * This is 0_10 specific. We use this property to check if some message properties have been changed. - */ - private boolean _hasBeenUpdated = false; - - public boolean reset() - { - boolean result = _hasBeenUpdated; - _hasBeenUpdated = false; - return result; - } - - public void updated() - { - _hasBeenUpdated = true; - } - public BasicContentHeaderProperties() { } public int getPropertyListSize() { - if (_encodedForm != null) - { - return _encodedForm.length; - } - else - { int size = 0; if ((_propertyFlags & (CONTENT_TYPE_MASK)) > 0) @@ -136,7 +94,7 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti size += EncodingUtils.encodedShortStringLength(_contentType); } - if ((_propertyFlags & ENCONDING_MASK) > 0) + if ((_propertyFlags & ENCODING_MASK) > 0) { size += EncodingUtils.encodedShortStringLength(_encoding); } @@ -151,7 +109,7 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti size += 1; } - if ((_propertyFlags & PROPRITY_MASK) > 0) + if ((_propertyFlags & PRIORITY_MASK) > 0) { size += 1; } @@ -209,23 +167,10 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti } return size; - } - } - - private void clearEncodedForm() - { - if (!_decoded && (_encodedForm != null)) - { - // decode(); - } - - _encodedForm = null; } public void setPropertyFlags(int propertyFlags) { - _hasBeenUpdated = true; - clearEncodedForm(); _propertyFlags = propertyFlags; } @@ -234,94 +179,87 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti return _propertyFlags; } - public void writePropertyListPayload(ByteBuffer buffer) + public void writePropertyListPayload(DataOutputStream buffer) throws IOException { - if (_encodedForm != null) + if ((_propertyFlags & (CONTENT_TYPE_MASK)) != 0) { - buffer.put(_encodedForm); + EncodingUtils.writeShortStringBytes(buffer, _contentType); } - else + + if ((_propertyFlags & ENCODING_MASK) != 0) { - if ((_propertyFlags & (CONTENT_TYPE_MASK)) != 0) - { - EncodingUtils.writeShortStringBytes(buffer, _contentType); - } + EncodingUtils.writeShortStringBytes(buffer, _encoding); + } - if ((_propertyFlags & ENCONDING_MASK) != 0) - { - EncodingUtils.writeShortStringBytes(buffer, _encoding); - } + if ((_propertyFlags & HEADERS_MASK) != 0) + { + EncodingUtils.writeFieldTableBytes(buffer, _headers); + } - if ((_propertyFlags & HEADERS_MASK) != 0) - { - EncodingUtils.writeFieldTableBytes(buffer, _headers); - } + if ((_propertyFlags & DELIVERY_MODE_MASK) != 0) + { + buffer.writeByte(_deliveryMode); + } - if ((_propertyFlags & DELIVERY_MODE_MASK) != 0) - { - buffer.put(_deliveryMode); - } + if ((_propertyFlags & PRIORITY_MASK) != 0) + { + buffer.writeByte(_priority); + } - if ((_propertyFlags & PROPRITY_MASK) != 0) - { - buffer.put(_priority); - } + if ((_propertyFlags & CORRELATION_ID_MASK) != 0) + { + EncodingUtils.writeShortStringBytes(buffer, _correlationId); + } - if ((_propertyFlags & CORRELATION_ID_MASK) != 0) - { - EncodingUtils.writeShortStringBytes(buffer, _correlationId); - } + if ((_propertyFlags & REPLY_TO_MASK) != 0) + { + EncodingUtils.writeShortStringBytes(buffer, _replyTo); + } - if ((_propertyFlags & REPLY_TO_MASK) != 0) + if ((_propertyFlags & EXPIRATION_MASK) != 0) + { + if (_expiration == 0L) { - EncodingUtils.writeShortStringBytes(buffer, _replyTo); + EncodingUtils.writeShortStringBytes(buffer, ZERO_STRING); } - - if ((_propertyFlags & EXPIRATION_MASK) != 0) + else { - if (_expiration == 0L) - { - EncodingUtils.writeShortStringBytes(buffer, ZERO_STRING); - } - else - { - EncodingUtils.writeShortStringBytes(buffer, String.valueOf(_expiration)); - } + EncodingUtils.writeShortStringBytes(buffer, String.valueOf(_expiration)); } + } - if ((_propertyFlags & MESSAGE_ID_MASK) != 0) - { - EncodingUtils.writeShortStringBytes(buffer, _messageId); - } + if ((_propertyFlags & MESSAGE_ID_MASK) != 0) + { + EncodingUtils.writeShortStringBytes(buffer, _messageId); + } - if ((_propertyFlags & TIMESTAMP_MASK) != 0) - { - EncodingUtils.writeTimestamp(buffer, _timestamp); - } + if ((_propertyFlags & TIMESTAMP_MASK) != 0) + { + EncodingUtils.writeTimestamp(buffer, _timestamp); + } - if ((_propertyFlags & TYPE_MASK) != 0) - { - EncodingUtils.writeShortStringBytes(buffer, _type); - } + if ((_propertyFlags & TYPE_MASK) != 0) + { + EncodingUtils.writeShortStringBytes(buffer, _type); + } - if ((_propertyFlags & USER_ID_MASK) != 0) - { - EncodingUtils.writeShortStringBytes(buffer, _userId); - } + if ((_propertyFlags & USER_ID_MASK) != 0) + { + EncodingUtils.writeShortStringBytes(buffer, _userId); + } - if ((_propertyFlags & APPLICATION_ID_MASK) != 0) - { - EncodingUtils.writeShortStringBytes(buffer, _appId); - } + if ((_propertyFlags & APPLICATION_ID_MASK) != 0) + { + EncodingUtils.writeShortStringBytes(buffer, _appId); + } - if ((_propertyFlags & CLUSTER_ID_MASK) != 0) - { - EncodingUtils.writeShortStringBytes(buffer, _clusterId); - } + if ((_propertyFlags & CLUSTER_ID_MASK) != 0) + { + EncodingUtils.writeShortStringBytes(buffer, _clusterId); } } - public void populatePropertiesFromBuffer(ByteBuffer buffer, int propertyFlags, int size) throws AMQFrameDecodingException + public void populatePropertiesFromBuffer(DataInputStream buffer, int propertyFlags, int size) throws AMQFrameDecodingException, IOException { _propertyFlags = propertyFlags; @@ -331,25 +269,18 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti } decode(buffer); - /*_encodedForm = new byte[size]; - buffer.get(_encodedForm, 0, size); - _decoded = false; - _decodedHeaders = false; - _decodedContentType = false;*/ } - private void decode(ByteBuffer buffer) + private void decode(DataInputStream buffer) throws IOException, AMQFrameDecodingException { // ByteBuffer buffer = ByteBuffer.wrap(_encodedForm); - int pos = buffer.position(); - try - { + if ((_propertyFlags & (CONTENT_TYPE_MASK)) != 0) { _contentType = EncodingUtils.readAMQShortString(buffer); } - if ((_propertyFlags & ENCONDING_MASK) != 0) + if ((_propertyFlags & ENCODING_MASK) != 0) { _encoding = EncodingUtils.readAMQShortString(buffer); } @@ -361,12 +292,12 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti if ((_propertyFlags & DELIVERY_MODE_MASK) != 0) { - _deliveryMode = buffer.get(); + _deliveryMode = buffer.readByte(); } - if ((_propertyFlags & PROPRITY_MASK) != 0) + if ((_propertyFlags & PRIORITY_MASK) != 0) { - _priority = buffer.get(); + _priority = buffer.readByte(); } if ((_propertyFlags & CORRELATION_ID_MASK) != 0) @@ -413,116 +344,29 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti { _clusterId = EncodingUtils.readAMQShortString(buffer); } - } - catch (AMQFrameDecodingException e) - { - throw new RuntimeException("Error in content header data: " + e, e); - } - final int endPos = buffer.position(); - buffer.position(pos); - final int len = endPos - pos; - _encodedForm = new byte[len]; - final int limit = buffer.limit(); - buffer.limit(endPos); - buffer.get(_encodedForm, 0, len); - buffer.limit(limit); - buffer.position(endPos); - _decoded = true; - } - private void decodeUpToHeaders() - { - ByteBuffer buffer = ByteBuffer.wrap(_encodedForm); - try - { - if ((_propertyFlags & (CONTENT_TYPE_MASK)) != 0) - { - byte length = buffer.get(); - buffer.skip(length); - } - - if ((_propertyFlags & ENCONDING_MASK) != 0) - { - byte length = buffer.get(); - buffer.skip(length); - } - - if ((_propertyFlags & HEADERS_MASK) != 0) - { - _headers = EncodingUtils.readFieldTable(buffer); - - } - - _decodedHeaders = true; - } - catch (AMQFrameDecodingException e) - { - throw new RuntimeException("Error in content header data: " + e, e); - } } - private void decodeUpToContentType() - { - ByteBuffer buffer = ByteBuffer.wrap(_encodedForm); - - if ((_propertyFlags & (CONTENT_TYPE_MASK)) != 0) - { - _contentType = EncodingUtils.readAMQShortString(buffer); - } - - _decodedContentType = true; - } - - private void decodeIfNecessary() - { - if (!_decoded) - { - // decode(); - } - } - - private void decodeHeadersIfNecessary() - { - if (!_decoded && !_decodedHeaders) - { - decodeUpToHeaders(); - } - } - - private void decodeContentTypeIfNecessary() - { - if (!_decoded && !_decodedContentType) - { - decodeUpToContentType(); - } - } public AMQShortString getContentType() { - decodeContentTypeIfNecessary(); - return _contentType; } public String getContentTypeAsString() { - decodeContentTypeIfNecessary(); - return (_contentType == null) ? null : _contentType.toString(); } public void setContentType(AMQShortString contentType) { - _hasBeenUpdated = true; - clearEncodedForm(); _propertyFlags |= (CONTENT_TYPE_MASK); _contentType = contentType; } public void setContentType(String contentType) { - _hasBeenUpdated = true; setContentType((contentType == null) ? null : new AMQShortString(contentType)); } @@ -534,31 +378,23 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti public AMQShortString getEncoding() { - decodeIfNecessary(); - return _encoding; } public void setEncoding(String encoding) { - _hasBeenUpdated = true; - clearEncodedForm(); - _propertyFlags |= ENCONDING_MASK; + _propertyFlags |= ENCODING_MASK; _encoding = (encoding == null) ? null : new AMQShortString(encoding); } public void setEncoding(AMQShortString encoding) { - _hasBeenUpdated = true; - clearEncodedForm(); - _propertyFlags |= ENCONDING_MASK; + _propertyFlags |= ENCODING_MASK; _encoding = encoding; } public FieldTable getHeaders() { - decodeHeadersIfNecessary(); - if (_headers == null) { setHeaders(FieldTableFactory.newFieldTable()); @@ -569,191 +405,146 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti public void setHeaders(FieldTable headers) { - _hasBeenUpdated = true; - clearEncodedForm(); _propertyFlags |= HEADERS_MASK; _headers = headers; } public byte getDeliveryMode() { - decodeIfNecessary(); - return _deliveryMode; } public void setDeliveryMode(byte deliveryMode) { - clearEncodedForm(); _propertyFlags |= DELIVERY_MODE_MASK; _deliveryMode = deliveryMode; } public byte getPriority() { - decodeIfNecessary(); - return _priority; } public void setPriority(byte priority) { - clearEncodedForm(); - _propertyFlags |= PROPRITY_MASK; + _propertyFlags |= PRIORITY_MASK; _priority = priority; } public AMQShortString getCorrelationId() { - decodeIfNecessary(); - return _correlationId; } public String getCorrelationIdAsString() { - decodeIfNecessary(); - return (_correlationId == null) ? null : _correlationId.toString(); } public void setCorrelationId(String correlationId) { - _hasBeenUpdated = true; setCorrelationId((correlationId == null) ? null : new AMQShortString(correlationId)); } public void setCorrelationId(AMQShortString correlationId) { - _hasBeenUpdated = true; - clearEncodedForm(); _propertyFlags |= CORRELATION_ID_MASK; _correlationId = correlationId; } public String getReplyToAsString() { - decodeIfNecessary(); - return (_replyTo == null) ? null : _replyTo.toString(); } public AMQShortString getReplyTo() { - decodeIfNecessary(); - return _replyTo; } public void setReplyTo(String replyTo) { - _hasBeenUpdated = true; setReplyTo((replyTo == null) ? null : new AMQShortString(replyTo)); } public void setReplyTo(AMQShortString replyTo) { - _hasBeenUpdated = true; - clearEncodedForm(); _propertyFlags |= REPLY_TO_MASK; _replyTo = replyTo; } public long getExpiration() { - decodeIfNecessary(); return _expiration; } public void setExpiration(long expiration) { - clearEncodedForm(); _propertyFlags |= EXPIRATION_MASK; _expiration = expiration; } public AMQShortString getMessageId() { - decodeIfNecessary(); - return _messageId; } public String getMessageIdAsString() { - decodeIfNecessary(); - return (_messageId == null) ? null : _messageId.toString(); } public void setMessageId(String messageId) { - _hasBeenUpdated = true; - clearEncodedForm(); _propertyFlags |= MESSAGE_ID_MASK; _messageId = (messageId == null) ? null : new AMQShortString(messageId); } public void setMessageId(AMQShortString messageId) { - _hasBeenUpdated = true; - clearEncodedForm(); _propertyFlags |= MESSAGE_ID_MASK; _messageId = messageId; } public long getTimestamp() { - decodeIfNecessary(); return _timestamp; } public void setTimestamp(long timestamp) { - clearEncodedForm(); _propertyFlags |= TIMESTAMP_MASK; _timestamp = timestamp; } public String getTypeAsString() { - decodeIfNecessary(); - return (_type == null) ? null : _type.toString(); } public AMQShortString getType() { - decodeIfNecessary(); - return _type; } public void setType(String type) { - _hasBeenUpdated = true; setType((type == null) ? null : new AMQShortString(type)); } public void setType(AMQShortString type) { - _hasBeenUpdated = true; - clearEncodedForm(); _propertyFlags |= TYPE_MASK; _type = type; } public String getUserIdAsString() { - decodeIfNecessary(); - return (_userId == null) ? null : _userId.toString(); } public AMQShortString getUserId() { - decodeIfNecessary(); - return _userId; } @@ -764,65 +555,48 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti public void setUserId(AMQShortString userId) { - _hasBeenUpdated = true; - clearEncodedForm(); _propertyFlags |= USER_ID_MASK; _userId = userId; } public String getAppIdAsString() { - decodeIfNecessary(); - return (_appId == null) ? null : _appId.toString(); } public AMQShortString getAppId() { - decodeIfNecessary(); - return _appId; } public void setAppId(String appId) { - _hasBeenUpdated = true; setAppId((appId == null) ? null : new AMQShortString(appId)); } public void setAppId(AMQShortString appId) { - _hasBeenUpdated = true; - clearEncodedForm(); _propertyFlags |= APPLICATION_ID_MASK; _appId = appId; - _hasBeenUpdated = true; } public String getClusterIdAsString() { - _hasBeenUpdated = true; - decodeIfNecessary(); return (_clusterId == null) ? null : _clusterId.toString(); } public AMQShortString getClusterId() { - _hasBeenUpdated = true; - decodeIfNecessary(); return _clusterId; } public void setClusterId(String clusterId) { - _hasBeenUpdated = true; setClusterId((clusterId == null) ? null : new AMQShortString(clusterId)); } public void setClusterId(AMQShortString clusterId) { - _hasBeenUpdated = true; - clearEncodedForm(); _propertyFlags |= CLUSTER_ID_MASK; _clusterId = clusterId; } diff --git a/java/common/src/main/java/org/apache/qpid/framing/BodyFactory.java b/java/common/src/main/java/org/apache/qpid/framing/BodyFactory.java index 59646577e1..f9580d82b1 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/BodyFactory.java +++ b/java/common/src/main/java/org/apache/qpid/framing/BodyFactory.java @@ -20,12 +20,13 @@ */ package org.apache.qpid.framing; -import org.apache.mina.common.ByteBuffer; +import java.io.DataInputStream; +import java.io.IOException; /** * Any class that is capable of turning a stream of bytes into an AMQ structure must implement this interface. */ public interface BodyFactory { - AMQBody createBody(ByteBuffer in, long bodySize) throws AMQFrameDecodingException; + AMQBody createBody(DataInputStream in, long bodySize) throws AMQFrameDecodingException, IOException; } diff --git a/java/common/src/main/java/org/apache/qpid/framing/CompositeAMQDataBlock.java b/java/common/src/main/java/org/apache/qpid/framing/CompositeAMQDataBlock.java index 94030f383e..15bc20c52d 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/CompositeAMQDataBlock.java +++ b/java/common/src/main/java/org/apache/qpid/framing/CompositeAMQDataBlock.java @@ -20,7 +20,8 @@ */ package org.apache.qpid.framing; -import org.apache.mina.common.ByteBuffer; +import java.io.DataOutputStream; +import java.io.IOException; public class CompositeAMQDataBlock extends AMQDataBlock implements EncodableAMQDataBlock { @@ -49,7 +50,7 @@ public class CompositeAMQDataBlock extends AMQDataBlock implements EncodableAMQD return frameSize; } - public void writePayload(ByteBuffer buffer) + public void writePayload(DataOutputStream buffer) throws IOException { for (int i = 0; i < _blocks.length; i++) { diff --git a/java/common/src/main/java/org/apache/qpid/framing/ContentBody.java b/java/common/src/main/java/org/apache/qpid/framing/ContentBody.java index 9d39f8aa86..aedb35f92a 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/ContentBody.java +++ b/java/common/src/main/java/org/apache/qpid/framing/ContentBody.java @@ -20,7 +20,10 @@ */ package org.apache.qpid.framing; -import org.apache.mina.common.ByteBuffer; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + import org.apache.qpid.protocol.AMQVersionAwareProtocolSession; import org.apache.qpid.AMQException; @@ -28,27 +31,22 @@ public class ContentBody implements AMQBody { public static final byte TYPE = 3; - public ByteBuffer payload; + public byte[] _payload; public ContentBody() { } - public ContentBody(ByteBuffer buffer, long size) throws AMQFrameDecodingException + public ContentBody(DataInputStream buffer, long size) throws AMQFrameDecodingException, IOException { - if (size > 0) - { - payload = buffer.slice(); - payload.limit((int) size); - buffer.skip((int) size); - } - + _payload = new byte[(int)size]; + buffer.read(_payload); } - public ContentBody(ByteBuffer payload) + public ContentBody(byte[] payload) { - this.payload = payload; + _payload = payload; } public byte getFrameType() @@ -58,23 +56,12 @@ public class ContentBody implements AMQBody public int getSize() { - return (payload == null ? 0 : payload.limit()); + return _payload == null ? 0 : _payload.length; } - public void writePayload(ByteBuffer buffer) + public void writePayload(DataOutputStream buffer) throws IOException { - if (payload != null) - { - if(payload.isDirect() || payload.isReadOnly()) - { - ByteBuffer copy = payload.duplicate(); - buffer.put(copy.rewind()); - } - else - { - buffer.put(payload.array(),payload.arrayOffset(),payload.limit()); - } - } + buffer.write(_payload); } public void handle(final int channelId, final AMQVersionAwareProtocolSession session) @@ -83,32 +70,18 @@ public class ContentBody implements AMQBody session.contentBodyReceived(channelId, this); } - protected void populateFromBuffer(ByteBuffer buffer, long size) throws AMQFrameDecodingException + protected void populateFromBuffer(DataInputStream buffer, long size) throws AMQFrameDecodingException, IOException { if (size > 0) { - payload = buffer.slice(); - payload.limit((int) size); - buffer.skip((int) size); + _payload = new byte[(int)size]; + buffer.read(_payload); } } public void reduceBufferToFit() { - if (payload != null && (payload.remaining() < payload.capacity() / 2)) - { - int size = payload.limit(); - ByteBuffer newPayload = ByteBuffer.allocate(size); - - newPayload.put(payload); - newPayload.flip(); - - //reduce reference count on payload - payload.release(); - - payload = newPayload; - } } diff --git a/java/common/src/main/java/org/apache/qpid/framing/ContentBodyFactory.java b/java/common/src/main/java/org/apache/qpid/framing/ContentBodyFactory.java index c42995d148..a0b030ab6b 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/ContentBodyFactory.java +++ b/java/common/src/main/java/org/apache/qpid/framing/ContentBodyFactory.java @@ -20,7 +20,8 @@ */ package org.apache.qpid.framing; -import org.apache.mina.common.ByteBuffer; +import java.io.DataInputStream; +import java.io.IOException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -41,7 +42,7 @@ public class ContentBodyFactory implements BodyFactory _log.debug("Creating content body factory"); } - public AMQBody createBody(ByteBuffer in, long bodySize) throws AMQFrameDecodingException + public AMQBody createBody(DataInputStream in, long bodySize) throws AMQFrameDecodingException, IOException { return new ContentBody(in, bodySize); } diff --git a/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderBody.java b/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderBody.java index 83e5a7e341..18d0f26152 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderBody.java +++ b/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderBody.java @@ -20,7 +20,10 @@ */ package org.apache.qpid.framing; -import org.apache.mina.common.ByteBuffer; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + import org.apache.qpid.protocol.AMQVersionAwareProtocolSession; import org.apache.qpid.AMQException; @@ -36,18 +39,18 @@ public class ContentHeaderBody implements AMQBody public long bodySize; /** must never be null */ - public ContentHeaderProperties properties; + private ContentHeaderProperties properties; public ContentHeaderBody() { } - public ContentHeaderBody(ByteBuffer buffer, long size) throws AMQFrameDecodingException + public ContentHeaderBody(DataInputStream buffer, long size) throws AMQFrameDecodingException, IOException { - classId = buffer.getUnsignedShort(); - weight = buffer.getUnsignedShort(); - bodySize = buffer.getLong(); - int propertyFlags = buffer.getUnsignedShort(); + classId = buffer.readUnsignedShort(); + weight = buffer.readUnsignedShort(); + bodySize = buffer.readLong(); + int propertyFlags = buffer.readUnsignedShort(); ContentHeaderPropertiesFactory factory = ContentHeaderPropertiesFactory.getInstance(); properties = factory.createContentHeaderProperties(classId, propertyFlags, buffer, (int)size - 14); @@ -72,13 +75,13 @@ public class ContentHeaderBody implements AMQBody return TYPE; } - protected void populateFromBuffer(ByteBuffer buffer, long size) - throws AMQFrameDecodingException, AMQProtocolVersionException + protected void populateFromBuffer(DataInputStream buffer, long size) + throws AMQFrameDecodingException, AMQProtocolVersionException, IOException { - classId = buffer.getUnsignedShort(); - weight = buffer.getUnsignedShort(); - bodySize = buffer.getLong(); - int propertyFlags = buffer.getUnsignedShort(); + classId = buffer.readUnsignedShort(); + weight = buffer.readUnsignedShort(); + bodySize = buffer.readLong(); + int propertyFlags = buffer.readUnsignedShort(); ContentHeaderPropertiesFactory factory = ContentHeaderPropertiesFactory.getInstance(); properties = factory.createContentHeaderProperties(classId, propertyFlags, buffer, (int)size - 14); } @@ -90,8 +93,8 @@ public class ContentHeaderBody implements AMQBody * @return * @throws AMQFrameDecodingException */ - public static ContentHeaderBody createFromBuffer(ByteBuffer buffer, long size) - throws AMQFrameDecodingException, AMQProtocolVersionException + public static ContentHeaderBody createFromBuffer(DataInputStream buffer, long size) + throws AMQFrameDecodingException, AMQProtocolVersionException, IOException { ContentHeaderBody body = new ContentHeaderBody(buffer, size); @@ -103,11 +106,11 @@ public class ContentHeaderBody implements AMQBody return 2 + 2 + 8 + 2 + properties.getPropertyListSize(); } - public void writePayload(ByteBuffer buffer) + public void writePayload(DataOutputStream buffer) throws IOException { EncodingUtils.writeUnsignedShort(buffer, classId); EncodingUtils.writeUnsignedShort(buffer, weight); - buffer.putLong(bodySize); + buffer.writeLong(bodySize); EncodingUtils.writeUnsignedShort(buffer, properties.getPropertyFlags()); properties.writePropertyListPayload(buffer); } @@ -128,4 +131,25 @@ public class ContentHeaderBody implements AMQBody { return new AMQFrame(channelId, body); } + + public ContentHeaderProperties getProperties() + { + return properties; + } + + public void setProperties(ContentHeaderProperties props) + { + properties = props; + } + + @Override + public String toString() + { + return "ContentHeaderBody{" + + "classId=" + classId + + ", weight=" + weight + + ", bodySize=" + bodySize + + ", properties=" + properties + + '}'; + } } diff --git a/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderBodyFactory.java b/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderBodyFactory.java index 8d5e2f9fb4..a474e337b7 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderBodyFactory.java +++ b/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderBodyFactory.java @@ -20,7 +20,8 @@ */ package org.apache.qpid.framing; -import org.apache.mina.common.ByteBuffer; +import java.io.DataInputStream; +import java.io.IOException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -41,7 +42,7 @@ public class ContentHeaderBodyFactory implements BodyFactory _log.debug("Creating content header body factory"); } - public AMQBody createBody(ByteBuffer in, long bodySize) throws AMQFrameDecodingException + public AMQBody createBody(DataInputStream in, long bodySize) throws AMQFrameDecodingException, IOException { // all content headers are the same - it is only the properties that differ. // the content header body further delegates construction of properties diff --git a/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderProperties.java b/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderProperties.java index 7ef538cfdc..237929f9a3 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderProperties.java +++ b/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderProperties.java @@ -20,7 +20,10 @@ */ package org.apache.qpid.framing; -import org.apache.mina.common.ByteBuffer; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + /** * There will be an implementation of this interface for each content type. All content types have associated @@ -32,7 +35,7 @@ public interface ContentHeaderProperties * Writes the property list to the buffer, in a suitably encoded form. * @param buffer The buffer to write to */ - void writePropertyListPayload(ByteBuffer buffer); + void writePropertyListPayload(DataOutputStream buffer) throws IOException; /** * Populates the properties from buffer. @@ -40,8 +43,8 @@ public interface ContentHeaderProperties * @param propertyFlags he property flags. * @throws AMQFrameDecodingException when the buffer does not contain valid data */ - void populatePropertiesFromBuffer(ByteBuffer buffer, int propertyFlags, int size) - throws AMQFrameDecodingException; + void populatePropertiesFromBuffer(DataInputStream buffer, int propertyFlags, int size) + throws AMQFrameDecodingException, IOException; /** * @return the size of the encoded property list in bytes. @@ -56,5 +59,4 @@ public interface ContentHeaderProperties */ int getPropertyFlags(); - void updated(); } diff --git a/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderPropertiesFactory.java b/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderPropertiesFactory.java index 46189b63d7..43ee8cd1f1 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderPropertiesFactory.java +++ b/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderPropertiesFactory.java @@ -20,7 +20,8 @@ */ package org.apache.qpid.framing; -import org.apache.mina.common.ByteBuffer; +import java.io.DataInputStream; +import java.io.IOException; import org.apache.qpid.framing.amqp_8_0.BasicConsumeBodyImpl; @@ -38,8 +39,8 @@ public class ContentHeaderPropertiesFactory } public ContentHeaderProperties createContentHeaderProperties(int classId, int propertyFlags, - ByteBuffer buffer, int size) - throws AMQFrameDecodingException + DataInputStream buffer, int size) + throws AMQFrameDecodingException, IOException { ContentHeaderProperties properties; // AMQP version change: "Hardwired" version to major=8, minor=0 diff --git a/java/common/src/main/java/org/apache/qpid/framing/DeferredDataBlock.java b/java/common/src/main/java/org/apache/qpid/framing/DeferredDataBlock.java deleted file mode 100644 index f6795ff200..0000000000 --- a/java/common/src/main/java/org/apache/qpid/framing/DeferredDataBlock.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.apache.qpid.framing; - -import org.apache.mina.common.ByteBuffer; - -/* -* -* 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. -* -*/ -public abstract class DeferredDataBlock extends AMQDataBlock -{ - private AMQDataBlock _underlyingDataBlock; - - - public long getSize() - { - if(_underlyingDataBlock == null) - { - _underlyingDataBlock = createAMQDataBlock(); - } - return _underlyingDataBlock.getSize(); - } - - public void writePayload(ByteBuffer buffer) - { - if(_underlyingDataBlock == null) - { - _underlyingDataBlock = createAMQDataBlock(); - } - _underlyingDataBlock.writePayload(buffer); - } - - abstract protected AMQDataBlock createAMQDataBlock(); - -} diff --git a/java/common/src/main/java/org/apache/qpid/framing/EncodingUtils.java b/java/common/src/main/java/org/apache/qpid/framing/EncodingUtils.java index 6425f8c591..2d7e27405c 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/EncodingUtils.java +++ b/java/common/src/main/java/org/apache/qpid/framing/EncodingUtils.java @@ -20,11 +20,12 @@ */ package org.apache.qpid.framing; -import org.apache.mina.common.ByteBuffer; +import java.io.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.nio.ByteBuffer; import java.nio.charset.Charset; public class EncodingUtils @@ -218,7 +219,7 @@ public class EncodingUtils return 0; } - public static void writeShortStringBytes(ByteBuffer buffer, String s) + public static void writeShortStringBytes(DataOutputStream buffer, String s) throws IOException { if (s != null) { @@ -231,18 +232,18 @@ public class EncodingUtils // TODO: check length fits in an unsigned byte writeUnsignedByte(buffer, (short)encodedString.length); - buffer.put(encodedString); + buffer.write(encodedString); } else { // really writing out unsigned byte - buffer.put((byte) 0); + buffer.write((byte) 0); } } - public static void writeShortStringBytes(ByteBuffer buffer, AMQShortString s) + public static void writeShortStringBytes(DataOutputStream buffer, AMQShortString s) throws IOException { if (s != null) { @@ -252,11 +253,11 @@ public class EncodingUtils else { // really writing out unsigned byte - buffer.put((byte) 0); + buffer.write((byte) 0); } } - public static void writeLongStringBytes(ByteBuffer buffer, String s) + public static void writeLongStringBytes(DataOutputStream buffer, String s) throws IOException { assert (s == null) || (s.length() <= 0xFFFE); if (s != null) @@ -270,7 +271,7 @@ public class EncodingUtils encodedString[i] = (byte) cha[i]; } - buffer.put(encodedString); + buffer.write(encodedString); } else { @@ -278,7 +279,7 @@ public class EncodingUtils } } - public static void writeLongStringBytes(ByteBuffer buffer, char[] s) + public static void writeLongStringBytes(DataOutputStream buffer, char[] s) throws IOException { assert (s == null) || (s.length <= 0xFFFE); if (s != null) @@ -291,7 +292,7 @@ public class EncodingUtils encodedString[i] = (byte) s[i]; } - buffer.put(encodedString); + buffer.write(encodedString); } else { @@ -299,13 +300,13 @@ public class EncodingUtils } } - public static void writeLongStringBytes(ByteBuffer buffer, byte[] bytes) + public static void writeLongStringBytes(DataOutputStream buffer, byte[] bytes) throws IOException { assert (bytes == null) || (bytes.length <= 0xFFFE); if (bytes != null) { writeUnsignedInteger(buffer, bytes.length); - buffer.put(bytes); + buffer.write(bytes); } else { @@ -313,24 +314,24 @@ public class EncodingUtils } } - public static void writeUnsignedByte(ByteBuffer buffer, short b) + public static void writeUnsignedByte(DataOutputStream buffer, short b) throws IOException { byte bv = (byte) b; - buffer.put(bv); + buffer.write(bv); } - public static void writeUnsignedShort(ByteBuffer buffer, int s) + public static void writeUnsignedShort(DataOutputStream buffer, int s) throws IOException { // TODO: Is this comparison safe? Do I need to cast RHS to long? if (s < Short.MAX_VALUE) { - buffer.putShort((short) s); + buffer.writeShort(s); } else { short sv = (short) s; - buffer.put((byte) (0xFF & (sv >> 8))); - buffer.put((byte) (0xFF & sv)); + buffer.write((byte) (0xFF & (sv >> 8))); + buffer.write((byte) (0xFF & sv)); } } @@ -339,12 +340,12 @@ public class EncodingUtils return 4; } - public static void writeUnsignedInteger(ByteBuffer buffer, long l) + public static void writeUnsignedInteger(DataOutputStream buffer, long l) throws IOException { // TODO: Is this comparison safe? Do I need to cast RHS to long? if (l < Integer.MAX_VALUE) { - buffer.putInt((int) l); + buffer.writeInt((int) l); } else { @@ -352,14 +353,14 @@ public class EncodingUtils // FIXME: This *may* go faster if we build this into a local 4-byte array and then // put the array in a single call. - buffer.put((byte) (0xFF & (iv >> 24))); - buffer.put((byte) (0xFF & (iv >> 16))); - buffer.put((byte) (0xFF & (iv >> 8))); - buffer.put((byte) (0xFF & iv)); + buffer.write((byte) (0xFF & (iv >> 24))); + buffer.write((byte) (0xFF & (iv >> 16))); + buffer.write((byte) (0xFF & (iv >> 8))); + buffer.write((byte) (0xFF & iv)); } } - public static void writeFieldTableBytes(ByteBuffer buffer, FieldTable table) + public static void writeFieldTableBytes(DataOutputStream buffer, FieldTable table) throws IOException { if (table != null) { @@ -371,12 +372,12 @@ public class EncodingUtils } } - public static void writeContentBytes(ByteBuffer buffer, Content content) + public static void writeContentBytes(DataOutputStream buffer, Content content) { // TODO: New Content class required for AMQP 0-9. } - public static void writeBooleans(ByteBuffer buffer, boolean[] values) + public static void writeBooleans(DataOutputStream buffer, boolean[] values) throws IOException { byte packedValue = 0; for (int i = 0; i < values.length; i++) @@ -387,16 +388,16 @@ public class EncodingUtils } } - buffer.put(packedValue); + buffer.write(packedValue); } - public static void writeBooleans(ByteBuffer buffer, boolean value) + public static void writeBooleans(DataOutputStream buffer, boolean value) throws IOException { - buffer.put(value ? (byte) 1 : (byte) 0); + buffer.write(value ? (byte) 1 : (byte) 0); } - public static void writeBooleans(ByteBuffer buffer, boolean value0, boolean value1) + public static void writeBooleans(DataOutputStream buffer, boolean value0, boolean value1) throws IOException { byte packedValue = value0 ? (byte) 1 : (byte) 0; @@ -405,10 +406,10 @@ public class EncodingUtils packedValue = (byte) (packedValue | (byte) (1 << 1)); } - buffer.put(packedValue); + buffer.write(packedValue); } - public static void writeBooleans(ByteBuffer buffer, boolean value0, boolean value1, boolean value2) + public static void writeBooleans(DataOutputStream buffer, boolean value0, boolean value1, boolean value2) throws IOException { byte packedValue = value0 ? (byte) 1 : (byte) 0; @@ -422,10 +423,10 @@ public class EncodingUtils packedValue = (byte) (packedValue | (byte) (1 << 2)); } - buffer.put(packedValue); + buffer.write(packedValue); } - public static void writeBooleans(ByteBuffer buffer, boolean value0, boolean value1, boolean value2, boolean value3) + public static void writeBooleans(DataOutputStream buffer, boolean value0, boolean value1, boolean value2, boolean value3) throws IOException { byte packedValue = value0 ? (byte) 1 : (byte) 0; @@ -444,11 +445,11 @@ public class EncodingUtils packedValue = (byte) (packedValue | (byte) (1 << 3)); } - buffer.put(packedValue); + buffer.write(packedValue); } - public static void writeBooleans(ByteBuffer buffer, boolean value0, boolean value1, boolean value2, boolean value3, - boolean value4) + public static void writeBooleans(DataOutputStream buffer, boolean value0, boolean value1, boolean value2, boolean value3, + boolean value4) throws IOException { byte packedValue = value0 ? (byte) 1 : (byte) 0; @@ -472,11 +473,11 @@ public class EncodingUtils packedValue = (byte) (packedValue | (byte) (1 << 4)); } - buffer.put(packedValue); + buffer.write(packedValue); } - public static void writeBooleans(ByteBuffer buffer, boolean value0, boolean value1, boolean value2, boolean value3, - boolean value4, boolean value5) + public static void writeBooleans(DataOutputStream buffer, boolean value0, boolean value1, boolean value2, boolean value3, + boolean value4, boolean value5) throws IOException { byte packedValue = value0 ? (byte) 1 : (byte) 0; @@ -505,11 +506,11 @@ public class EncodingUtils packedValue = (byte) (packedValue | (byte) (1 << 5)); } - buffer.put(packedValue); + buffer.write(packedValue); } - public static void writeBooleans(ByteBuffer buffer, boolean value0, boolean value1, boolean value2, boolean value3, - boolean value4, boolean value5, boolean value6) + public static void writeBooleans(DataOutputStream buffer, boolean value0, boolean value1, boolean value2, boolean value3, + boolean value4, boolean value5, boolean value6) throws IOException { byte packedValue = value0 ? (byte) 1 : (byte) 0; @@ -543,11 +544,11 @@ public class EncodingUtils packedValue = (byte) (packedValue | (byte) (1 << 6)); } - buffer.put(packedValue); + buffer.write(packedValue); } - public static void writeBooleans(ByteBuffer buffer, boolean value0, boolean value1, boolean value2, boolean value3, - boolean value4, boolean value5, boolean value6, boolean value7) + public static void writeBooleans(DataOutputStream buffer, boolean value0, boolean value1, boolean value2, boolean value3, + boolean value4, boolean value5, boolean value6, boolean value7) throws IOException { byte packedValue = value0 ? (byte) 1 : (byte) 0; @@ -586,7 +587,7 @@ public class EncodingUtils packedValue = (byte) (packedValue | (byte) (1 << 7)); } - buffer.put(packedValue); + buffer.write(packedValue); } /** @@ -595,12 +596,12 @@ public class EncodingUtils * @param buffer * @param data */ - public static void writeLongstr(ByteBuffer buffer, byte[] data) + public static void writeLongstr(DataOutputStream buffer, byte[] data) throws IOException { if (data != null) { writeUnsignedInteger(buffer, data.length); - buffer.put(data); + buffer.write(data); } else { @@ -608,14 +609,14 @@ public class EncodingUtils } } - public static void writeTimestamp(ByteBuffer buffer, long timestamp) + public static void writeTimestamp(DataOutputStream buffer, long timestamp) throws IOException { writeLong(buffer, timestamp); } - public static boolean[] readBooleans(ByteBuffer buffer) + public static boolean[] readBooleans(DataInputStream buffer) throws IOException { - final byte packedValue = buffer.get(); + final byte packedValue = buffer.readByte(); if (packedValue == 0) { return ALL_FALSE_ARRAY; @@ -640,9 +641,9 @@ public class EncodingUtils return result; } - public static FieldTable readFieldTable(ByteBuffer buffer) throws AMQFrameDecodingException + public static FieldTable readFieldTable(DataInputStream buffer) throws AMQFrameDecodingException, IOException { - long length = buffer.getUnsignedInt(); + long length = ((long)(buffer.readInt())) & 0xFFFFFFFFL; if (length == 0) { return null; @@ -653,21 +654,21 @@ public class EncodingUtils } } - public static Content readContent(ByteBuffer buffer) throws AMQFrameDecodingException + public static Content readContent(DataInputStream buffer) throws AMQFrameDecodingException { // TODO: New Content class required for AMQP 0-9. return null; } - public static AMQShortString readAMQShortString(ByteBuffer buffer) + public static AMQShortString readAMQShortString(DataInputStream buffer) throws IOException { return AMQShortString.readFromBuffer(buffer); } - public static String readShortString(ByteBuffer buffer) + public static String readShortString(DataInputStream buffer) throws IOException { - short length = buffer.getUnsigned(); + short length = (short) (((short)buffer.readByte()) & 0xFF); if (length == 0) { return null; @@ -680,7 +681,7 @@ public class EncodingUtils // this approach here is valid since we know that all the chars are // ASCII (0-127) byte[] stringBytes = new byte[length]; - buffer.get(stringBytes, 0, length); + buffer.read(stringBytes, 0, length); char[] stringChars = new char[length]; for (int i = 0; i < stringChars.length; i++) { @@ -691,9 +692,9 @@ public class EncodingUtils } } - public static String readLongString(ByteBuffer buffer) + public static String readLongString(DataInputStream buffer) throws IOException { - long length = buffer.getUnsignedInt(); + long length = ((long)(buffer.readInt())) & 0xFFFFFFFFL; if (length == 0) { return ""; @@ -706,7 +707,7 @@ public class EncodingUtils // this approach here is valid since we know that all the chars are // ASCII (0-127) byte[] stringBytes = new byte[(int) length]; - buffer.get(stringBytes, 0, (int) length); + buffer.read(stringBytes, 0, (int) length); char[] stringChars = new char[(int) length]; for (int i = 0; i < stringChars.length; i++) { @@ -717,9 +718,9 @@ public class EncodingUtils } } - public static byte[] readLongstr(ByteBuffer buffer) + public static byte[] readLongstr(DataInputStream buffer) throws IOException { - long length = buffer.getUnsignedInt(); + long length = ((long)(buffer.readInt())) & 0xFFFFFFFFL; if (length == 0) { return null; @@ -727,17 +728,17 @@ public class EncodingUtils else { byte[] result = new byte[(int) length]; - buffer.get(result); + buffer.read(result); return result; } } - public static long readTimestamp(ByteBuffer buffer) + public static long readTimestamp(DataInputStream buffer) throws IOException { // Discard msb from AMQ timestamp // buffer.getUnsignedInt(); - return buffer.getLong(); + return buffer.readLong(); } static byte[] hexToByteArray(String id) @@ -817,14 +818,14 @@ public class EncodingUtils // AMQP_BOOLEAN_PROPERTY_PREFIX - public static void writeBoolean(ByteBuffer buffer, Boolean aBoolean) + public static void writeBoolean(DataOutputStream buffer, Boolean aBoolean) throws IOException { - buffer.put((byte) (aBoolean ? 1 : 0)); + buffer.write(aBoolean ? 1 : 0); } - public static boolean readBoolean(ByteBuffer buffer) + public static boolean readBoolean(DataInputStream buffer) throws IOException { - byte packedValue = buffer.get(); + byte packedValue = buffer.readByte(); return (packedValue == 1); } @@ -835,14 +836,14 @@ public class EncodingUtils } // AMQP_BYTE_PROPERTY_PREFIX - public static void writeByte(ByteBuffer buffer, Byte aByte) + public static void writeByte(DataOutputStream buffer, Byte aByte) throws IOException { - buffer.put(aByte); + buffer.writeByte(aByte); } - public static byte readByte(ByteBuffer buffer) + public static byte readByte(DataInputStream buffer) throws IOException { - return buffer.get(); + return buffer.readByte(); } public static int encodedByteLength() @@ -851,14 +852,14 @@ public class EncodingUtils } // AMQP_SHORT_PROPERTY_PREFIX - public static void writeShort(ByteBuffer buffer, Short aShort) + public static void writeShort(DataOutputStream buffer, Short aShort) throws IOException { - buffer.putShort(aShort); + buffer.writeShort(aShort); } - public static short readShort(ByteBuffer buffer) + public static short readShort(DataInputStream buffer) throws IOException { - return buffer.getShort(); + return buffer.readShort(); } public static int encodedShortLength() @@ -867,14 +868,14 @@ public class EncodingUtils } // INTEGER_PROPERTY_PREFIX - public static void writeInteger(ByteBuffer buffer, Integer aInteger) + public static void writeInteger(DataOutputStream buffer, Integer aInteger) throws IOException { - buffer.putInt(aInteger); + buffer.writeInt(aInteger); } - public static int readInteger(ByteBuffer buffer) + public static int readInteger(DataInputStream buffer) throws IOException { - return buffer.getInt(); + return buffer.readInt(); } public static int encodedIntegerLength() @@ -883,14 +884,14 @@ public class EncodingUtils } // AMQP_LONG_PROPERTY_PREFIX - public static void writeLong(ByteBuffer buffer, Long aLong) + public static void writeLong(DataOutputStream buffer, Long aLong) throws IOException { - buffer.putLong(aLong); + buffer.writeLong(aLong); } - public static long readLong(ByteBuffer buffer) + public static long readLong(DataInputStream buffer) throws IOException { - return buffer.getLong(); + return buffer.readLong(); } public static int encodedLongLength() @@ -899,14 +900,14 @@ public class EncodingUtils } // Float_PROPERTY_PREFIX - public static void writeFloat(ByteBuffer buffer, Float aFloat) + public static void writeFloat(DataOutputStream buffer, Float aFloat) throws IOException { - buffer.putFloat(aFloat); + buffer.writeFloat(aFloat); } - public static float readFloat(ByteBuffer buffer) + public static float readFloat(DataInputStream buffer) throws IOException { - return buffer.getFloat(); + return buffer.readFloat(); } public static int encodedFloatLength() @@ -915,14 +916,14 @@ public class EncodingUtils } // Double_PROPERTY_PREFIX - public static void writeDouble(ByteBuffer buffer, Double aDouble) + public static void writeDouble(DataOutputStream buffer, Double aDouble) throws IOException { - buffer.putDouble(aDouble); + buffer.writeDouble(aDouble); } - public static double readDouble(ByteBuffer buffer) + public static double readDouble(DataInputStream buffer) throws IOException { - return buffer.getDouble(); + return buffer.readDouble(); } public static int encodedDoubleLength() @@ -930,9 +931,9 @@ public class EncodingUtils return 8; } - public static byte[] readBytes(ByteBuffer buffer) + public static byte[] readBytes(DataInputStream buffer) throws IOException { - long length = buffer.getUnsignedInt(); + long length = ((long)(buffer.readInt())) & 0xFFFFFFFFL; if (length == 0) { return null; @@ -940,19 +941,19 @@ public class EncodingUtils else { byte[] dataBytes = new byte[(int)length]; - buffer.get(dataBytes, 0, (int)length); + buffer.read(dataBytes, 0, (int) length); return dataBytes; } } - public static void writeBytes(ByteBuffer buffer, byte[] data) + public static void writeBytes(DataOutputStream buffer, byte[] data) throws IOException { if (data != null) { // TODO: check length fits in an unsigned byte writeUnsignedInteger(buffer, (long)data.length); - buffer.put(data); + buffer.write(data); } else { @@ -968,35 +969,35 @@ public class EncodingUtils return encodedByteLength(); } - public static char readChar(ByteBuffer buffer) + public static char readChar(DataInputStream buffer) throws IOException { // This is valid as we know that the Character is ASCII 0..127 - return (char) buffer.get(); + return (char) buffer.read(); } - public static void writeChar(ByteBuffer buffer, char character) + public static void writeChar(DataOutputStream buffer, char character) throws IOException { // This is valid as we know that the Character is ASCII 0..127 writeByte(buffer, (byte) character); } - public static long readLongAsShortString(ByteBuffer buffer) + public static long readLongAsShortString(DataInputStream buffer) throws IOException { - short length = buffer.getUnsigned(); + short length = (short) buffer.readUnsignedByte(); short pos = 0; if (length == 0) { return 0L; } - byte digit = buffer.get(); + byte digit = buffer.readByte(); boolean isNegative; long result = 0; if (digit == (byte) '-') { isNegative = true; pos++; - digit = buffer.get(); + digit = buffer.readByte(); } else { @@ -1009,7 +1010,7 @@ public class EncodingUtils while (pos < length) { pos++; - digit = buffer.get(); + digit = buffer.readByte(); result = (result << 3) + (result << 1); result += digit - (byte) '0'; } @@ -1017,15 +1018,15 @@ public class EncodingUtils return result; } - public static long readUnsignedInteger(ByteBuffer buffer) + public static long readUnsignedInteger(DataInputStream buffer) throws IOException { - long l = 0xFF & buffer.get(); + long l = 0xFF & buffer.readByte(); l <<= 8; - l = l | (0xFF & buffer.get()); + l = l | (0xFF & buffer.readByte()); l <<= 8; - l = l | (0xFF & buffer.get()); + l = l | (0xFF & buffer.readByte()); l <<= 8; - l = l | (0xFF & buffer.get()); + l = l | (0xFF & buffer.readByte()); return l; } diff --git a/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java b/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java index 22205d49f8..721c821bab 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java +++ b/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java @@ -20,12 +20,16 @@ */ package org.apache.qpid.framing; -import org.apache.mina.common.ByteBuffer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.qpid.AMQPInvalidClassException; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; import java.math.BigDecimal; import java.util.Collections; import java.util.Enumeration; @@ -43,8 +47,8 @@ public class FieldTable private static final String STRICT_AMQP = "STRICT_AMQP"; private final boolean _strictAMQP = Boolean.valueOf(System.getProperty(STRICT_AMQP, "false")); - private ByteBuffer _encodedForm; - private LinkedHashMap<AMQShortString, AMQTypedValue> _properties; + private byte[] _encodedForm; + private LinkedHashMap<AMQShortString, AMQTypedValue> _properties = null; private long _encodedSize; private static final int INITIAL_HASHMAP_CAPACITY = 16; private static final int INITIAL_ENCODED_FORM_SIZE = 256; @@ -52,9 +56,6 @@ public class FieldTable public FieldTable() { super(); - // _encodedForm = ByteBuffer.allocate(INITIAL_ENCODED_FORM_SIZE); - // _encodedForm.setAutoExpand(true); - // _encodedForm.limit(0); } /** @@ -63,16 +64,12 @@ public class FieldTable * @param buffer the buffer from which to read data. The length byte must be read already * @param length the length of the field table. Must be > 0. */ - public FieldTable(ByteBuffer buffer, long length) + public FieldTable(DataInputStream buffer, long length) throws IOException { this(); - ByteBuffer encodedForm = buffer.slice(); - encodedForm.limit((int) length); - _encodedForm = ByteBuffer.allocate((int)length); - _encodedForm.put(encodedForm); - _encodedForm.flip(); + _encodedForm = new byte[(int) length]; + buffer.read(_encodedForm); _encodedSize = length; - buffer.skip((int) length); } public AMQTypedValue getProperty(AMQShortString string) @@ -108,13 +105,19 @@ public class FieldTable { try { - setFromBuffer(_encodedForm, _encodedSize); + setFromBuffer(); } catch (AMQFrameDecodingException e) { _logger.error("Error decoding FieldTable in deferred decoding mode ", e); throw new IllegalArgumentException(e); } + catch (IOException e) + { + _logger.error("Unexpected IO exception decoding field table"); + throw new IllegalArgumentException(e); + + } } private AMQTypedValue setProperty(AMQShortString key, AMQTypedValue val) @@ -766,7 +769,7 @@ public class FieldTable // ************************* Byte Buffer Processing - public void writeToBuffer(ByteBuffer buffer) + public void writeToBuffer(DataOutputStream buffer) throws IOException { final boolean trace = _logger.isDebugEnabled(); @@ -786,17 +789,21 @@ public class FieldTable public byte[] getDataAsBytes() { - final int encodedSize = (int) getEncodedSize(); - final ByteBuffer buffer = ByteBuffer.allocate(encodedSize); // FIXME XXX: Is cast a problem? - - putDataInBuffer(buffer); - - final byte[] result = new byte[encodedSize]; - buffer.flip(); - buffer.get(result); - buffer.release(); + if(_encodedForm == null) + { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try + { + putDataInBuffer(new DataOutputStream(baos)); + return baos.toByteArray(); + } + catch (IOException e) + { + throw new IllegalArgumentException("IO Exception should never be thrown here"); + } - return result; + } + return _encodedForm.clone(); } public long getEncodedSize() @@ -926,15 +933,8 @@ public class FieldTable public Iterator<Map.Entry<AMQShortString, AMQTypedValue>> iterator() { - if(_encodedForm != null) - { - return new FieldTableIterator(_encodedForm.duplicate().rewind(),(int)_encodedSize); - } - else - { - initMapIfNecessary(); - return _properties.entrySet().iterator(); - } + initMapIfNecessary(); + return _properties.entrySet().iterator(); } public Object get(String key) @@ -1002,26 +1002,12 @@ public class FieldTable return _properties.keySet(); } - private void putDataInBuffer(ByteBuffer buffer) + private void putDataInBuffer(DataOutputStream buffer) throws IOException { if (_encodedForm != null) { - if(buffer.isDirect() || buffer.isReadOnly()) - { - ByteBuffer encodedForm = _encodedForm.duplicate(); - - if (encodedForm.position() != 0) - { - encodedForm.flip(); - } - - buffer.put(encodedForm); - } - else - { - buffer.put(_encodedForm.array(),_encodedForm.arrayOffset(),(int)_encodedSize); - } + buffer.write(_encodedForm); } else if (_properties != null) { @@ -1035,41 +1021,27 @@ public class FieldTable final Map.Entry<AMQShortString, AMQTypedValue> me = it.next(); try { - if (_logger.isDebugEnabled()) - { - _logger.debug("Writing Property:" + me.getKey() + " Type:" + me.getValue().getType() + " Value:" - + me.getValue().getValue()); - _logger.debug("Buffer Position:" + buffer.position() + " Remaining:" + buffer.remaining()); - } - // Write the actual parameter name EncodingUtils.writeShortStringBytes(buffer, me.getKey()); me.getValue().writeToBuffer(buffer); } catch (Exception e) { - if (_logger.isDebugEnabled()) - { - _logger.debug("Exception thrown:" + e); - _logger.debug("Writing Property:" + me.getKey() + " Type:" + me.getValue().getType() + " Value:" - + me.getValue().getValue()); - _logger.debug("Buffer Position:" + buffer.position() + " Remaining:" + buffer.remaining()); - } - throw new RuntimeException(e); } } } } - private void setFromBuffer(ByteBuffer buffer, long length) throws AMQFrameDecodingException + private void setFromBuffer() throws AMQFrameDecodingException, IOException { + final ByteArrayInputStream in = new ByteArrayInputStream(_encodedForm); + DataInputStream buffer = new DataInputStream(in); final boolean trace = _logger.isDebugEnabled(); - if (length > 0) + if (_encodedSize > 0) { - final int expectedRemaining = buffer.remaining() - (int) length; _properties = new LinkedHashMap<AMQShortString, AMQTypedValue>(INITIAL_HASHMAP_CAPACITY); @@ -1077,121 +1049,16 @@ public class FieldTable { final AMQShortString key = EncodingUtils.readAMQShortString(buffer); - - _logger.debug("FieldTable::PropFieldTable(buffer," + length + "): Read key '" + key); - AMQTypedValue value = AMQTypedValue.readFromBuffer(buffer); - - if (trace) - { - _logger.debug("FieldTable::PropFieldTable(buffer," + length + "): Read type '" + value.getType() - + "', key '" + key + "', value '" + value.getValue() + "'"); - } - _properties.put(key, value); } - while (buffer.remaining() > expectedRemaining); - - } - - _encodedSize = length; - - if (trace) - { - _logger.debug("FieldTable::FieldTable(buffer," + length + "): Done."); - } - } - - private static final class FieldTableEntry implements Map.Entry<AMQShortString, AMQTypedValue> - { - private final AMQTypedValue _value; - private final AMQShortString _key; - - public FieldTableEntry(final AMQShortString key, final AMQTypedValue value) - { - _key = key; - _value = value; - } - - public AMQShortString getKey() - { - return _key; - } - - public AMQTypedValue getValue() - { - return _value; - } - - public AMQTypedValue setValue(final AMQTypedValue value) - { - throw new UnsupportedOperationException(); - } - - public boolean equals(Object o) - { - if(o instanceof FieldTableEntry) - { - FieldTableEntry other = (FieldTableEntry) o; - return (_key == null ? other._key == null : _key.equals(other._key)) - && (_value == null ? other._value == null : _value.equals(other._value)); - } - else - { - return false; - } - } - - public int hashCode() - { - return (getKey()==null ? 0 : getKey().hashCode()) - ^ (getValue()==null ? 0 : getValue().hashCode()); - } - - } - - - private static final class FieldTableIterator implements Iterator<Map.Entry<AMQShortString, AMQTypedValue>> - { + while (in.available() > 0); - private final ByteBuffer _buffer; - private int _expectedRemaining; - - public FieldTableIterator(ByteBuffer buffer, int length) - { - _buffer = buffer; - _expectedRemaining = buffer.remaining() - length; - } - - public boolean hasNext() - { - return (_buffer.remaining() > _expectedRemaining); } - public Map.Entry<AMQShortString, AMQTypedValue> next() - { - if(hasNext()) - { - final AMQShortString key = EncodingUtils.readAMQShortString(_buffer); - AMQTypedValue value = AMQTypedValue.readFromBuffer(_buffer); - return new FieldTableEntry(key, value); - } - else - { - return null; - } - } - - public void remove() - { - throw new UnsupportedOperationException(); - } } - - - public int hashCode() { initMapIfNecessary(); diff --git a/java/common/src/main/java/org/apache/qpid/framing/FieldTableFactory.java b/java/common/src/main/java/org/apache/qpid/framing/FieldTableFactory.java index e9d75137ef..438a46f28b 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/FieldTableFactory.java +++ b/java/common/src/main/java/org/apache/qpid/framing/FieldTableFactory.java @@ -20,7 +20,8 @@ */ package org.apache.qpid.framing; -import org.apache.mina.common.ByteBuffer; +import java.io.DataInputStream; +import java.io.IOException; public class FieldTableFactory { @@ -29,7 +30,7 @@ public class FieldTableFactory return new FieldTable(); } - public static FieldTable newFieldTable(ByteBuffer byteBuffer, long length) throws AMQFrameDecodingException + public static FieldTable newFieldTable(DataInputStream byteBuffer, long length) throws AMQFrameDecodingException, IOException { return new FieldTable(byteBuffer, length); } diff --git a/java/common/src/main/java/org/apache/qpid/framing/HeartbeatBody.java b/java/common/src/main/java/org/apache/qpid/framing/HeartbeatBody.java index 18ab05ffa1..a6ce721a50 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/HeartbeatBody.java +++ b/java/common/src/main/java/org/apache/qpid/framing/HeartbeatBody.java @@ -20,7 +20,10 @@ */ package org.apache.qpid.framing; -import org.apache.mina.common.ByteBuffer; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + import org.apache.qpid.protocol.AMQVersionAwareProtocolSession; import org.apache.qpid.AMQException; @@ -34,12 +37,12 @@ public class HeartbeatBody implements AMQBody } - public HeartbeatBody(ByteBuffer buffer, long size) + public HeartbeatBody(DataInputStream buffer, long size) throws IOException { if(size > 0) { //allow other implementations to have a payload, but ignore it: - buffer.skip((int) size); + buffer.skip(size); } } @@ -53,7 +56,7 @@ public class HeartbeatBody implements AMQBody return 0;//heartbeats we generate have no payload } - public void writePayload(ByteBuffer buffer) + public void writePayload(DataOutputStream buffer) { } @@ -63,12 +66,12 @@ public class HeartbeatBody implements AMQBody session.heartbeatBodyReceived(channelId, this); } - protected void populateFromBuffer(ByteBuffer buffer, long size) throws AMQFrameDecodingException + protected void populateFromBuffer(DataInputStream buffer, long size) throws AMQFrameDecodingException, IOException { if(size > 0) { //allow other implementations to have a payload, but ignore it: - buffer.skip((int) size); + buffer.skip(size); } } diff --git a/java/common/src/main/java/org/apache/qpid/framing/HeartbeatBodyFactory.java b/java/common/src/main/java/org/apache/qpid/framing/HeartbeatBodyFactory.java index c7ada708dc..dfc49c6167 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/HeartbeatBodyFactory.java +++ b/java/common/src/main/java/org/apache/qpid/framing/HeartbeatBodyFactory.java @@ -20,11 +20,11 @@ */ package org.apache.qpid.framing; -import org.apache.mina.common.ByteBuffer; +import java.io.DataInputStream; public class HeartbeatBodyFactory implements BodyFactory { - public AMQBody createBody(ByteBuffer in, long bodySize) throws AMQFrameDecodingException + public AMQBody createBody(DataInputStream in, long bodySize) throws AMQFrameDecodingException { return new HeartbeatBody(); } diff --git a/java/common/src/main/java/org/apache/qpid/framing/ProtocolInitiation.java b/java/common/src/main/java/org/apache/qpid/framing/ProtocolInitiation.java index fb3dd89717..8c018316f0 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/ProtocolInitiation.java +++ b/java/common/src/main/java/org/apache/qpid/framing/ProtocolInitiation.java @@ -22,6 +22,10 @@ package org.apache.qpid.framing; import org.apache.qpid.AMQException; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.util.Arrays; @@ -62,35 +66,30 @@ public class ProtocolInitiation extends AMQDataBlock implements EncodableAMQData pv.equals(ProtocolVersion.v0_91) ? 1 : pv.getMinorVersion()); } - public ProtocolInitiation(ByteBuffer in) + public ProtocolInitiation(DataInputStream in) throws IOException { _protocolHeader = new byte[4]; - in.get(_protocolHeader); + in.read(_protocolHeader); - _protocolClass = in.get(); - _protocolInstance = in.get(); - _protocolMajor = in.get(); - _protocolMinor = in.get(); + _protocolClass = in.readByte(); + _protocolInstance = in.readByte(); + _protocolMajor = in.readByte(); + _protocolMinor = in.readByte(); } - public void writePayload(org.apache.mina.common.ByteBuffer buffer) - { - writePayload(buffer.buf()); - } - public long getSize() { return 4 + 1 + 1 + 1 + 1; } - public void writePayload(ByteBuffer buffer) + public void writePayload(DataOutputStream buffer) throws IOException { - buffer.put(_protocolHeader); - buffer.put(_protocolClass); - buffer.put(_protocolInstance); - buffer.put(_protocolMajor); - buffer.put(_protocolMinor); + buffer.write(_protocolHeader); + buffer.write(_protocolClass); + buffer.write(_protocolInstance); + buffer.write(_protocolMajor); + buffer.write(_protocolMinor); } public boolean equals(Object o) @@ -144,9 +143,9 @@ 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(ByteBuffer in) + public boolean decodable(DataInputStream in) throws IOException { - return (in.remaining() >= 8); + return (in.available() >= 8); } } diff --git a/java/common/src/main/java/org/apache/qpid/framing/SmallCompositeAMQDataBlock.java b/java/common/src/main/java/org/apache/qpid/framing/SmallCompositeAMQDataBlock.java index bd763599b0..d2925d13a8 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/SmallCompositeAMQDataBlock.java +++ b/java/common/src/main/java/org/apache/qpid/framing/SmallCompositeAMQDataBlock.java @@ -21,7 +21,8 @@ package org.apache.qpid.framing; -import org.apache.mina.common.ByteBuffer; +import java.io.DataOutputStream; +import java.io.IOException; public class SmallCompositeAMQDataBlock extends AMQDataBlock implements EncodableAMQDataBlock { @@ -68,7 +69,7 @@ public class SmallCompositeAMQDataBlock extends AMQDataBlock implements Encodabl return frameSize; } - public void writePayload(ByteBuffer buffer) + public void writePayload(DataOutputStream buffer) throws IOException { if (_firstFrame != null) { diff --git a/java/common/src/main/java/org/apache/qpid/framing/VersionSpecificRegistry.java b/java/common/src/main/java/org/apache/qpid/framing/VersionSpecificRegistry.java index 76c154581d..ed9136f7c9 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/VersionSpecificRegistry.java +++ b/java/common/src/main/java/org/apache/qpid/framing/VersionSpecificRegistry.java @@ -20,7 +20,8 @@ */ package org.apache.qpid.framing; -import org.apache.mina.common.ByteBuffer; +import java.io.DataInputStream; +import java.io.IOException; import org.apache.qpid.framing.abstraction.ProtocolVersionMethodConverter; @@ -144,7 +145,7 @@ public class VersionSpecificRegistry } - public AMQMethodBody get(short classID, short methodID, ByteBuffer in, long size) throws AMQFrameDecodingException + public AMQMethodBody get(short classID, short methodID, DataInputStream in, long size) throws AMQFrameDecodingException, IOException { AMQMethodBodyInstanceFactory bodyFactory; try diff --git a/java/common/src/main/java/org/apache/qpid/framing/abstraction/ContentChunk.java b/java/common/src/main/java/org/apache/qpid/framing/abstraction/ContentChunk.java index 0695349f76..470b7b05e3 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/abstraction/ContentChunk.java +++ b/java/common/src/main/java/org/apache/qpid/framing/abstraction/ContentChunk.java @@ -21,12 +21,10 @@ package org.apache.qpid.framing.abstraction; -import org.apache.mina.common.ByteBuffer; - public interface ContentChunk { int getSize(); - ByteBuffer getData(); + byte[] getData(); void reduceToFit(); } diff --git a/java/common/src/main/java/org/apache/qpid/framing/abstraction/ProtocolVersionMethodConverter.java b/java/common/src/main/java/org/apache/qpid/framing/abstraction/ProtocolVersionMethodConverter.java index 7544d9b7e7..d1e53d6907 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/abstraction/ProtocolVersionMethodConverter.java +++ b/java/common/src/main/java/org/apache/qpid/framing/abstraction/ProtocolVersionMethodConverter.java @@ -23,8 +23,6 @@ package org.apache.qpid.framing.abstraction; import org.apache.qpid.framing.AMQBody; -import java.nio.ByteBuffer; - public interface ProtocolVersionMethodConverter extends MessagePublishInfoConverter { AMQBody convertToBody(ContentChunk contentBody); @@ -32,5 +30,5 @@ public interface ProtocolVersionMethodConverter extends MessagePublishInfoConver void configure(); - AMQBody convertToBody(ByteBuffer buf); + AMQBody convertToBody(byte[] input); } diff --git a/java/common/src/main/java/org/apache/qpid/framing/amqp_0_9/MethodConverter_0_9.java b/java/common/src/main/java/org/apache/qpid/framing/amqp_0_9/MethodConverter_0_9.java index 1c4a29b106..90a730d6f7 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/amqp_0_9/MethodConverter_0_9.java +++ b/java/common/src/main/java/org/apache/qpid/framing/amqp_0_9/MethodConverter_0_9.java @@ -21,16 +21,13 @@ package org.apache.qpid.framing.amqp_0_9; -import org.apache.mina.common.ByteBuffer; - import org.apache.qpid.framing.abstraction.AbstractMethodConverter; import org.apache.qpid.framing.abstraction.ProtocolVersionMethodConverter; import org.apache.qpid.framing.abstraction.ContentChunk; import org.apache.qpid.framing.abstraction.MessagePublishInfo; import org.apache.qpid.framing.abstraction.MessagePublishInfoImpl; import org.apache.qpid.framing.*; -import org.apache.qpid.framing.amqp_0_9.*; -import org.apache.qpid.framing.amqp_0_9.BasicPublishBodyImpl; + public class MethodConverter_0_9 extends AbstractMethodConverter implements ProtocolVersionMethodConverter { @@ -72,9 +69,9 @@ public class MethodConverter_0_9 extends AbstractMethodConverter implements Prot } - public AMQBody convertToBody(java.nio.ByteBuffer buf) + public AMQBody convertToBody(byte[] data) { - return new ContentBody(ByteBuffer.wrap(buf)); + return new ContentBody(data); } public MessagePublishInfo convertToInfo(AMQMethodBody methodBody) @@ -116,9 +113,9 @@ public class MethodConverter_0_9 extends AbstractMethodConverter implements Prot return _contentBodyChunk.getSize(); } - public ByteBuffer getData() + public byte[] getData() { - return _contentBodyChunk.payload; + return _contentBodyChunk._payload; } public void reduceToFit() diff --git a/java/common/src/main/java/org/apache/qpid/framing/amqp_0_91/MethodConverter_0_91.java b/java/common/src/main/java/org/apache/qpid/framing/amqp_0_91/MethodConverter_0_91.java index 6e330574bc..3b0cc3cebc 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/amqp_0_91/MethodConverter_0_91.java +++ b/java/common/src/main/java/org/apache/qpid/framing/amqp_0_91/MethodConverter_0_91.java @@ -21,8 +21,6 @@ package org.apache.qpid.framing.amqp_0_91; -import org.apache.mina.common.ByteBuffer; - import org.apache.qpid.framing.abstraction.AbstractMethodConverter; import org.apache.qpid.framing.abstraction.ProtocolVersionMethodConverter; import org.apache.qpid.framing.abstraction.ContentChunk; @@ -70,9 +68,9 @@ public class MethodConverter_0_91 extends AbstractMethodConverter implements Pro } - public AMQBody convertToBody(java.nio.ByteBuffer buf) + public AMQBody convertToBody(byte[] data) { - return new ContentBody(ByteBuffer.wrap(buf)); + return new ContentBody(data); } public MessagePublishInfo convertToInfo(AMQMethodBody methodBody) @@ -114,9 +112,9 @@ public class MethodConverter_0_91 extends AbstractMethodConverter implements Pro return _contentBodyChunk.getSize(); } - public ByteBuffer getData() + public byte[] getData() { - return _contentBodyChunk.payload; + return _contentBodyChunk._payload; } public void reduceToFit() diff --git a/java/common/src/main/java/org/apache/qpid/framing/amqp_8_0/MethodConverter_8_0.java b/java/common/src/main/java/org/apache/qpid/framing/amqp_8_0/MethodConverter_8_0.java index c87820b9b2..e6d0482f0d 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/amqp_8_0/MethodConverter_8_0.java +++ b/java/common/src/main/java/org/apache/qpid/framing/amqp_8_0/MethodConverter_8_0.java @@ -26,11 +26,8 @@ import org.apache.qpid.framing.abstraction.ContentChunk; import org.apache.qpid.framing.abstraction.MessagePublishInfo; import org.apache.qpid.framing.abstraction.AbstractMethodConverter; import org.apache.qpid.framing.abstraction.MessagePublishInfoImpl; -import org.apache.qpid.framing.amqp_8_0.BasicPublishBodyImpl; import org.apache.qpid.framing.*; -import org.apache.mina.common.ByteBuffer; - public class MethodConverter_8_0 extends AbstractMethodConverter implements ProtocolVersionMethodConverter { private int _basicPublishClassId; @@ -60,9 +57,9 @@ public class MethodConverter_8_0 extends AbstractMethodConverter implements Prot return contentBodyChunk.getSize(); } - public ByteBuffer getData() + public byte[] getData() { - return contentBodyChunk.payload; + return contentBodyChunk._payload; } public void reduceToFit() @@ -81,9 +78,9 @@ public class MethodConverter_8_0 extends AbstractMethodConverter implements Prot } - public AMQBody convertToBody(java.nio.ByteBuffer buf) + public AMQBody convertToBody(byte[] data) { - return new ContentBody(ByteBuffer.wrap(buf)); + return new ContentBody(data); } public MessagePublishInfo convertToInfo(AMQMethodBody methodBody) diff --git a/java/common/src/main/java/org/apache/qpid/pool/Job.java b/java/common/src/main/java/org/apache/qpid/pool/Job.java deleted file mode 100644 index 82b600de88..0000000000 --- a/java/common/src/main/java/org/apache/qpid/pool/Job.java +++ /dev/null @@ -1,253 +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.ConcurrentLinkedQueue; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.RejectedExecutionException; -import java.util.concurrent.atomic.AtomicBoolean; - -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. - * The {@link Event}s themselves provide methods to process themselves, so processing a job simply consists of sequentially - * processing all of its aggregated events. - * - * The constructor accepts a maximum number of events for the job, and only runs up to that maximum number when - * processing the job, but the add method does not enforce this maximum. In other words, not all the enqueued events - * may be processed in each run of the job, several runs may be required to clear the queue. - * - * <p/><table id="crc"><caption>CRC Card</caption> - * <tr><th> Responsibilities <th> Collaborations - * <tr><td> Aggregate many coninuations together into a single continuation. - * <tr><td> Sequentially process aggregated continuations. <td> {@link Event} - * <tr><td> Provide running and completion status of the aggregate continuation. - * <tr><td> Execute a terminal continuation upon job completion. <td> {@link JobCompletionHandler} - * </table> - * - * @todo Could make Job implement Runnable, FutureTask, or a custom Continuation interface, to clarify its status as a - * continuation. Job is a continuation that aggregates other continuations and as such is a usefull re-usable - * piece of code. There may be other palces than the mina filter chain where continuation batching is used within - * qpid, so abstracting this out could provide a usefull building block. This also opens the way to different - * kinds of job with a common interface, e.g. parallel or sequential jobs etc. - * - * @todo For better re-usability could make the completion handler optional. Only run it when one is set. - */ -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<Runnable> _eventQueue = new ConcurrentLinkedQueue<Runnable>(); - - /** Holds a status flag, that indicates when the job is actively running. */ - private final AtomicBoolean _active = new AtomicBoolean(); - - private final boolean _readJob; - - private ReferenceCountingExecutorService _poolReference; - - private final static Logger _logger = LoggerFactory.getLogger(Job.class); - - public Job(ReferenceCountingExecutorService poolReference, int maxEvents, boolean readJob) - { - _poolReference = poolReference; - _maxEvents = maxEvents; - _readJob = readJob; - } - - /** - * Enqueus a continuation for sequential processing by this job. - * - * @param evt The continuation to enqueue. - */ - public void add(Runnable evt) - { - _eventQueue.add(evt); - } - - /** - * Sequentially processes, up to the maximum number per job, the aggregated continuations in enqueued in this job. - */ - boolean processAll() - { - // limit the number of events processed in one run - int i = _maxEvents; - while( --i != 0 ) - { - Runnable e = _eventQueue.poll(); - if (e == null) - { - return true; - } - else - { - e.run(); - } - } - return false; - } - - /** - * Tests if there are no more enqueued continuations to process. - * - * @return <tt>true</tt> if there are no enqueued continuations in this job, <tt>false</tt> otherwise. - */ - public boolean isComplete() - { - return _eventQueue.peek() == null; - } - - /** - * Marks this job as active if it is inactive. This method is thread safe. - * - * @return <tt>true</tt> if this job was inactive and has now been marked as active, <tt>false</tt> otherwise. - */ - public boolean activate() - { - return _active.compareAndSet(false, true); - } - - /** - * Marks this job as inactive. This method is thread safe. - */ - public void deactivate() - { - _active.set(false); - } - - /** - * Processes a batch of aggregated continuations, marks this job as inactive and call the terminal continuation. - */ - public void run() - { - if(processAll()) - { - deactivate(); - completed(); - } - else - { - notCompleted(); - } - } - - public boolean isRead() - { - return _readJob; - } - - /** - * 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, Runnable 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"); - } - } - - } - - /** - * 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/java/common/src/main/java/org/apache/qpid/protocol/AMQConstant.java b/java/common/src/main/java/org/apache/qpid/protocol/AMQConstant.java index f0f2652ce3..14d1befaf1 100644 --- a/java/common/src/main/java/org/apache/qpid/protocol/AMQConstant.java +++ b/java/common/src/main/java/org/apache/qpid/protocol/AMQConstant.java @@ -80,7 +80,7 @@ public final class AMQConstant /** * An operator intervened to close the connection for some reason. The client may retry at some later date. */ - public static final AMQConstant CONTEXT_IN_USE = new AMQConstant(320, "context in use", true); + public static final AMQConstant CONNECTION_FORCED = new AMQConstant(320, "connection forced", true); /** The client tried to work with an unknown virtual host or cluster. */ public static final AMQConstant INVALID_PATH = new AMQConstant(402, "invalid path", true); @@ -104,7 +104,7 @@ public final class AMQConstant public static final AMQConstant REQUEST_TIMEOUT = new AMQConstant(408, "Request Timeout", true); - public static final AMQConstant INVALID_ARGUMENT = new AMQConstant(409, "argument invalid", true); + public static final AMQConstant ARGUMENT_INVALID = new AMQConstant(409, "argument invalid", true); /** * The client sent a malformed frame that the server could not decode. This strongly implies a programming error @@ -153,10 +153,7 @@ public final class AMQConstant public static final AMQConstant FRAME_MIN_SIZE = new AMQConstant(4096, "frame min size", true); - /** - * The server does not support the protocol version - */ - public static final AMQConstant UNSUPPORTED_BROKER_PROTOCOL_ERROR = new AMQConstant(542, "broker unsupported protocol", true); + public static final AMQConstant INVALID_ARGUMENT = new AMQConstant(542, "invalid argument", true); /** * The client imp does not support the protocol version */ diff --git a/java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngine.java b/java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngine.java index 31953ea6ab..fd651a2b66 100644 --- a/java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngine.java +++ b/java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngine.java @@ -21,10 +21,11 @@ package org.apache.qpid.protocol; import java.net.SocketAddress; +import java.nio.ByteBuffer; -import org.apache.qpid.framing.AMQDataBlock; -import org.apache.qpid.transport.NetworkDriver; import org.apache.qpid.transport.Receiver; +import org.apache.qpid.transport.Sender; +import org.apache.qpid.transport.network.NetworkConnection; /** * A ProtocolEngine is a Receiver for java.nio.ByteBuffers. It takes the data passed to it in the received @@ -32,9 +33,6 @@ import org.apache.qpid.transport.Receiver; */ public interface ProtocolEngine extends Receiver<java.nio.ByteBuffer> { - // Sets the network driver providing data for this ProtocolEngine - void setNetworkDriver (NetworkDriver driver); - // Returns the remote address of the NetworkDriver SocketAddress getRemoteAddress(); @@ -58,4 +56,6 @@ public interface ProtocolEngine extends Receiver<java.nio.ByteBuffer> void readerIdle(); + public void setNetworkConnection(NetworkConnection network, Sender<ByteBuffer> sender); + }
\ No newline at end of file diff --git a/java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngineFactory.java b/java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngineFactory.java index 9df84eef90..7378edff0c 100644 --- a/java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngineFactory.java +++ b/java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngineFactory.java @@ -20,12 +20,12 @@ */ package org.apache.qpid.protocol; -import org.apache.qpid.transport.NetworkDriver; +import org.apache.qpid.transport.network.NetworkConnection; public interface ProtocolEngineFactory { // Returns a new instance of a ProtocolEngine - ProtocolEngine newProtocolEngine(NetworkDriver networkDriver); + ProtocolEngine newProtocolEngine(); }
\ No newline at end of file diff --git a/java/common/src/main/java/org/apache/qpid/security/AMQPCallbackHandler.java b/java/common/src/main/java/org/apache/qpid/protocol/ServerProtocolEngine.java index a3dad9acdc..e8362f79f0 100644 --- a/java/common/src/main/java/org/apache/qpid/security/AMQPCallbackHandler.java +++ b/java/common/src/main/java/org/apache/qpid/protocol/ServerProtocolEngine.java @@ -7,9 +7,9 @@ * 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 @@ -18,11 +18,12 @@ * under the License. * */ -package org.apache.qpid.security; - -import javax.security.auth.callback.CallbackHandler; +package org.apache.qpid.protocol; -public interface AMQPCallbackHandler extends CallbackHandler +public interface ServerProtocolEngine extends ProtocolEngine { - void initialise(String username,String password); + /** + * Gets the connection ID associated with this ProtocolEngine + */ + long getConnectionId(); } diff --git a/java/common/src/main/java/org/apache/qpid/security/UsernamePasswordCallbackHandler.java b/java/common/src/main/java/org/apache/qpid/security/UsernamePasswordCallbackHandler.java deleted file mode 100644 index 89a63abeab..0000000000 --- a/java/common/src/main/java/org/apache/qpid/security/UsernamePasswordCallbackHandler.java +++ /dev/null @@ -1,60 +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.security; - -import java.io.IOException; - -import javax.security.auth.callback.Callback; -import javax.security.auth.callback.NameCallback; -import javax.security.auth.callback.PasswordCallback; -import javax.security.auth.callback.UnsupportedCallbackException; - -public class UsernamePasswordCallbackHandler implements AMQPCallbackHandler -{ - private String _username; - private String _password; - - public void initialise(String username,String password) - { - _username = username; - _password = password; - } - - public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException - { - for (int i = 0; i < callbacks.length; i++) - { - Callback cb = callbacks[i]; - if (cb instanceof NameCallback) - { - ((NameCallback)cb).setName(_username); - } - else if (cb instanceof PasswordCallback) - { - ((PasswordCallback)cb).setPassword((_password).toCharArray()); - } - else - { - throw new UnsupportedCallbackException(cb); - } - } - } -} diff --git a/java/common/src/main/java/org/apache/qpid/ssl/SSLContextFactory.java b/java/common/src/main/java/org/apache/qpid/ssl/SSLContextFactory.java index 702746b3da..01f13408b0 100644 --- a/java/common/src/main/java/org/apache/qpid/ssl/SSLContextFactory.java +++ b/java/common/src/main/java/org/apache/qpid/ssl/SSLContextFactory.java @@ -20,18 +20,17 @@ */ package org.apache.qpid.ssl; -import java.io.File; -import java.io.FileInputStream; import java.io.IOException; -import java.io.InputStream; import java.security.GeneralSecurityException; import java.security.KeyStore; import javax.net.ssl.KeyManager; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; +import org.apache.qpid.transport.network.security.ssl.QpidClientX509KeyManager; import org.apache.qpid.transport.network.security.ssl.SSLUtil; /** @@ -39,157 +38,92 @@ import org.apache.qpid.transport.network.security.ssl.SSLUtil; * before this will work. * */ -public class SSLContextFactory { - - /** - * Path to the Java keystore file - */ - private String _keyStorePath; - - /** - * Password for the keystore - */ - private String _keyStorePassword; - - /** - * Cert type to use in keystore - */ - private String _keyStoreCertType; - - /** - * Path to the Java truststore file - */ - private String _trustStorePath; - - /** - * Password for the truststore - */ - private String _trustStorePassword; - - /** - * Cert type to use in truststore - */ - private String _trustStoreCertType; - - private KeyManager customKeyManager; - - public SSLContextFactory(String trustStorePath, String trustStorePassword, - String trustStoreCertType) +public class SSLContextFactory +{ + public static final String JAVA_KEY_STORE_CODE = "JKS"; + public static final String TRANSPORT_LAYER_SECURITY_CODE = "TLS"; + public static final String KEY_STORE_CERTIFICATE_TYPE = "SunX509"; + + private SSLContextFactory() { - this(trustStorePath,trustStorePassword,trustStoreCertType, - trustStorePath,trustStorePassword,trustStoreCertType); + //no instances } - /** - * Create a factory instance - * @param keystorePath path to the Java keystore file - * @param keystorePassword password for the Java keystore - * @param certType certificate type - */ - public SSLContextFactory(String trustStorePath, String trustStorePassword, String trustStoreCertType, - String keyStorePath, String keyStorePassword, String keyStoreCertType) - { + public static SSLContext buildServerContext(final String keyStorePath, + final String keyStorePassword, final String keyStoreCertType) + throws GeneralSecurityException, IOException + { + return buildContext(null, null, null, keyStorePath, keyStorePassword, + keyStoreCertType, null); + } - _trustStorePath = trustStorePath; - _trustStorePassword = trustStorePassword; - - if (_trustStorePassword != null && _trustStorePassword.equals("none")) - { - _trustStorePassword = null; - } - _trustStoreCertType = trustStoreCertType; - - _keyStorePath = keyStorePath; - _keyStorePassword = keyStorePassword; - - if (_keyStorePassword != null && _keyStorePassword.equals("none")) - { - _keyStorePassword = null; - } - _keyStoreCertType = keyStoreCertType; - - if (_trustStorePath == null) { - throw new IllegalArgumentException("A TrustStore path or KeyStore path must be specified"); - } - if (_trustStoreCertType == null) { - throw new IllegalArgumentException("Cert type must be specified"); - } - } - - public SSLContextFactory(String trustStorePath, String trustStorePassword, String trustStoreCertType, - KeyManager customKeyManager) + public static SSLContext buildClientContext(final String trustStorePath, + final String trustStorePassword, final String trustStoreCertType, + final String keyStorePath, final String keyStorePassword, + final String keyStoreCertType, final String certAlias) + throws GeneralSecurityException, IOException + { + return buildContext(trustStorePath, trustStorePassword, + trustStoreCertType, keyStorePath, keyStorePassword, + keyStoreCertType, certAlias); + } + + private static SSLContext buildContext(final String trustStorePath, + final String trustStorePassword, final String trustStoreCertType, + final String keyStorePath, final String keyStorePassword, + final String keyStoreCertType, final String certAlias) + throws GeneralSecurityException, IOException { + // Initialize the SSLContext to work with our key managers. + final SSLContext sslContext = SSLContext + .getInstance(TRANSPORT_LAYER_SECURITY_CODE); - _trustStorePath = trustStorePath; - _trustStorePassword = trustStorePassword; - - if (_trustStorePassword != null && _trustStorePassword.equals("none")) + final TrustManager[] trustManagers; + final KeyManager[] keyManagers; + + if (trustStorePath != null) { - _trustStorePassword = null; - } - _trustStoreCertType = trustStoreCertType; - - if (_trustStorePath == null) { - throw new IllegalArgumentException("A TrustStore path or KeyStore path must be specified"); + final KeyStore ts = SSLUtil.getInitializedKeyStore(trustStorePath, + trustStorePassword); + final TrustManagerFactory tmf = TrustManagerFactory + .getInstance(trustStoreCertType); + tmf.init(ts); + + trustManagers = tmf.getTrustManagers(); } - if (_trustStoreCertType == null) { - throw new IllegalArgumentException("Cert type must be specified"); + else + { + trustManagers = null; } - - this.customKeyManager = customKeyManager; - } - - - /** - * Builds a SSLContext appropriate for use with a server - * @return SSLContext - * @throws GeneralSecurityException - * @throws IOException - */ - public SSLContext buildServerContext() throws GeneralSecurityException, IOException - { - KeyStore ts = SSLUtil.getInitializedKeyStore(_trustStorePath,_trustStorePassword); - TrustManagerFactory tmf = TrustManagerFactory.getInstance(_trustStoreCertType); - tmf.init(ts); - - // Initialize the SSLContext to work with our key managers. - SSLContext sslContext = SSLContext.getInstance("TLS"); - - if (customKeyManager != null) + if (keyStorePath != null) { - sslContext.init(new KeyManager[]{customKeyManager}, - tmf.getTrustManagers(), null); - + if (certAlias != null) + { + keyManagers = new KeyManager[] { new QpidClientX509KeyManager( + certAlias, keyStorePath, keyStorePassword, + keyStoreCertType) }; + } + else + { + final KeyStore ks = SSLUtil.getInitializedKeyStore( + keyStorePath, keyStorePassword); + + char[] keyStoreCharPassword = keyStorePassword == null ? null : keyStorePassword.toCharArray(); + // Set up key manager factory to use our key store + final KeyManagerFactory kmf = KeyManagerFactory + .getInstance(keyStoreCertType); + kmf.init(ks, keyStoreCharPassword); + keyManagers = kmf.getKeyManagers(); + } } else { - // Create keystore - KeyStore ks = SSLUtil.getInitializedKeyStore(_keyStorePath,_keyStorePassword); - // Set up key manager factory to use our key store - KeyManagerFactory kmf = KeyManagerFactory.getInstance(_keyStoreCertType); - kmf.init(ks, _keyStorePassword.toCharArray()); - - sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + keyManagers = null; } - - return sslContext; - } - - /** - * Creates a SSLContext factory appropriate for use with a client - * @return SSLContext - * @throws GeneralSecurityException - * @throws IOException - */ - public SSLContext buildClientContext() throws GeneralSecurityException, IOException - { - KeyStore ks = SSLUtil.getInitializedKeyStore(_trustStorePath,_trustStorePassword); - TrustManagerFactory tmf = TrustManagerFactory.getInstance(_trustStoreCertType); - tmf.init(ks); - SSLContext context = SSLContext.getInstance("TLS"); - context.init(null, tmf.getTrustManagers(), null); - return context; - } - + + sslContext.init(keyManagers, trustManagers, null); + + return sslContext; + } } diff --git a/java/common/src/main/java/org/apache/qpid/thread/QpidThreadExecutor.java b/java/common/src/main/java/org/apache/qpid/thread/QpidThreadExecutor.java index 38f60c04fe..30010a2d89 100644 --- a/java/common/src/main/java/org/apache/qpid/thread/QpidThreadExecutor.java +++ b/java/common/src/main/java/org/apache/qpid/thread/QpidThreadExecutor.java @@ -23,7 +23,7 @@ package org.apache.qpid.thread; import org.apache.qpid.thread.Threading; -import edu.emory.mathcs.backport.java.util.concurrent.Executor; +import java.util.concurrent.Executor; public class QpidThreadExecutor implements Executor { diff --git a/java/common/src/main/java/org/apache/qpid/transport/ClientDelegate.java b/java/common/src/main/java/org/apache/qpid/transport/ClientDelegate.java index 0d9f8c0b28..9bdad6b00e 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/ClientDelegate.java +++ b/java/common/src/main/java/org/apache/qpid/transport/ClientDelegate.java @@ -20,28 +20,20 @@ */ package org.apache.qpid.transport; -import org.ietf.jgss.GSSContext; -import org.ietf.jgss.GSSException; -import org.ietf.jgss.GSSManager; -import org.ietf.jgss.GSSName; -import org.ietf.jgss.Oid; - -import org.apache.qpid.security.UsernamePasswordCallbackHandler; import static org.apache.qpid.transport.Connection.State.OPEN; import static org.apache.qpid.transport.Connection.State.RESUMING; -import org.apache.qpid.transport.util.Logger; -import javax.security.sasl.Sasl; -import javax.security.sasl.SaslClient; -import javax.security.sasl.SaslException; import java.lang.management.ManagementFactory; import java.lang.management.RuntimeMXBean; -import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import javax.security.sasl.SaslClient; +import javax.security.sasl.SaslException; + +import org.apache.qpid.transport.util.Logger; + /** * ClientDelegate @@ -52,31 +44,13 @@ public class ClientDelegate extends ConnectionDelegate { private static final Logger log = Logger.get(ClientDelegate.class); - private static final String KRB5_OID_STR = "1.2.840.113554.1.2.2"; - protected static final Oid KRB5_OID; - static - { - Oid oid; - try - { - oid = new Oid(KRB5_OID_STR); - } - catch (GSSException ignore) - { - oid = null; - } - KRB5_OID = oid; - } - - private List<String> clientMechs; - private ConnectionSettings conSettings; + protected final ConnectionSettings _conSettings; public ClientDelegate(ConnectionSettings settings) { - this.conSettings = settings; - this.clientMechs = Arrays.asList(settings.getSaslMechs().split(" ")); + this._conSettings = settings; } public void init(Connection conn, ProtocolHeader hdr) @@ -92,9 +66,9 @@ public class ClientDelegate extends ConnectionDelegate { Map<String,Object> clientProperties = new HashMap<String,Object>(); - if(this.conSettings.getClientProperties() != null) + if(this._conSettings.getClientProperties() != null) { - clientProperties.putAll(this.conSettings.getClientProperties()); + clientProperties.putAll(_conSettings.getClientProperties()); } clientProperties.put("qpid.session_flow", 1); @@ -109,41 +83,12 @@ public class ClientDelegate extends ConnectionDelegate (clientProperties, null, null, conn.getLocale()); return; } - - List<String> choosenMechs = new ArrayList<String>(); - for (String mech:clientMechs) - { - if (brokerMechs.contains(mech)) - { - choosenMechs.add(mech); - } - } - - if (choosenMechs.size() == 0) - { - conn.exception(new ConnectionException("The following SASL mechanisms " + - clientMechs.toString() + - " specified by the client are not supported by the broker")); - return; - } - - String[] mechs = new String[choosenMechs.size()]; - choosenMechs.toArray(mechs); - conn.setServerProperties(start.getServerProperties()); try { - Map<String,Object> saslProps = new HashMap<String,Object>(); - if (conSettings.isUseSASLEncryption()) - { - saslProps.put(Sasl.QOP, "auth-conf"); - } - UsernamePasswordCallbackHandler handler = - new UsernamePasswordCallbackHandler(); - handler.initialise(conSettings.getUsername(), conSettings.getPassword()); - SaslClient sc = Sasl.createSaslClient - (mechs, null, conSettings.getSaslProtocol(), conSettings.getSaslServerName(), saslProps, handler); + final SaslClient sc = createSaslClient(brokerMechs); + conn.setSaslClient(sc); byte[] response = sc.hasInitialResponse() ? @@ -152,12 +97,22 @@ public class ClientDelegate extends ConnectionDelegate (clientProperties, sc.getMechanismName(), response, conn.getLocale()); } + catch (ConnectionException ce) + { + conn.exception(ce); + } catch (SaslException e) { conn.exception(e); } } + + protected SaslClient createSaslClient(List<Object> brokerMechs) throws ConnectionException, SaslException + { + throw new UnsupportedOperationException(); + } + @Override public void connectionSecure(Connection conn, ConnectionSecure secure) { @@ -176,7 +131,7 @@ public class ClientDelegate extends ConnectionDelegate @Override public void connectionTune(Connection conn, ConnectionTune tune) { - int hb_interval = calculateHeartbeatInterval(conSettings.getHeartbeatInterval(), + int hb_interval = calculateHeartbeatInterval(_conSettings.getHeartbeatInterval(), tune.getHeartbeatMin(), tune.getHeartbeatMax() ); @@ -191,32 +146,12 @@ public class ClientDelegate extends ConnectionDelegate //(or that forced by protocol limitations [0xFFFF]) conn.setChannelMax(channelMax == 0 ? Connection.MAX_CHANNEL_MAX : channelMax); - conn.connectionOpen(conSettings.getVhost(), null, Option.INSIST); + conn.connectionOpen(_conSettings.getVhost(), null, Option.INSIST); } @Override public void connectionOpenOk(Connection conn, ConnectionOpenOk ok) { - SaslClient sc = conn.getSaslClient(); - if (sc != null) - { - if (sc.getMechanismName().equals("GSSAPI")) - { - String id = getKerberosUser(); - if (id != null) - { - conn.setUserID(id); - } - } - else if (sc.getMechanismName().equals("EXTERNAL")) - { - if (conn.getSecurityLayer() != null) - { - conn.setUserID(conn.getSecurityLayer().getUserID()); - } - } - } - if (conn.isConnectionResuming()) { conn.setState(RESUMING); @@ -247,7 +182,7 @@ public class ClientDelegate extends ConnectionDelegate int i = heartbeat; if (i == 0) { - log.warn("Idle timeout is zero. Heartbeats are disabled"); + log.info("Idle timeout is 0 sec. Heartbeats are disabled."); return 0; // heartbeats are disabled. } else if (i >= min && i <= max) @@ -256,8 +191,8 @@ public class ClientDelegate extends ConnectionDelegate } else { - log.warn("Ignoring the idle timeout %s set by the connection," + - " using the brokers max value %s", i,max); + log.info("The broker does not support the configured connection idle timeout of %s sec," + + " using the brokers max supported value of %s sec instead.", i,max); return max; } } @@ -286,35 +221,7 @@ public class ClientDelegate extends ConnectionDelegate } - private String getKerberosUser() - { - log.debug("Obtaining userID from kerberos"); - String service = conSettings.getSaslProtocol() + "@" + conSettings.getSaslServerName(); - GSSManager manager = GSSManager.getInstance(); - - try - { - GSSName acceptorName = manager.createName(service, - GSSName.NT_HOSTBASED_SERVICE, KRB5_OID); - - GSSContext secCtx = manager.createContext(acceptorName, - KRB5_OID, - null, - GSSContext.INDEFINITE_LIFETIME); - secCtx.initSecContext(new byte[0], 0, 1); - if (secCtx.getSrcName() != null) - { - return secCtx.getSrcName().toString(); - } - } - catch (GSSException e) - { - log.warn("Unable to retrieve userID from Kerberos due to error",e); - } - - return null; - } } diff --git a/java/common/src/main/java/org/apache/qpid/transport/Connection.java b/java/common/src/main/java/org/apache/qpid/transport/Connection.java index e5e10c0e07..06c5c83031 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/Connection.java +++ b/java/common/src/main/java/org/apache/qpid/transport/Connection.java @@ -25,21 +25,29 @@ import static org.apache.qpid.transport.Connection.State.CLOSING; import static org.apache.qpid.transport.Connection.State.NEW; import static org.apache.qpid.transport.Connection.State.OPEN; import static org.apache.qpid.transport.Connection.State.OPENING; -import static org.apache.qpid.transport.Connection.State.RESUMING; +import java.nio.ByteBuffer; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicLong; import javax.security.sasl.SaslClient; import javax.security.sasl.SaslServer; +import org.apache.qpid.framing.ProtocolVersion; +import org.apache.qpid.transport.network.Assembler; +import org.apache.qpid.transport.network.Disassembler; +import org.apache.qpid.transport.network.InputHandler; +import org.apache.qpid.transport.network.NetworkConnection; +import org.apache.qpid.transport.network.OutgoingNetworkTransport; +import org.apache.qpid.transport.network.Transport; import org.apache.qpid.transport.network.security.SecurityLayer; +import org.apache.qpid.transport.network.security.SecurityLayerFactory; import org.apache.qpid.transport.util.Logger; import org.apache.qpid.transport.util.Waiter; import org.apache.qpid.util.Strings; @@ -65,6 +73,7 @@ public class Connection extends ConnectionInvoker public static final int MAX_CHANNEL_MAX = 0xFFFF; public static final int MIN_USABLE_CHANNEL_NUM = 0; + public enum State { NEW, CLOSED, OPENING, OPEN, CLOSING, CLOSE_RCVD, RESUMING } static class DefaultConnectionListener implements ConnectionListener @@ -112,17 +121,14 @@ public class Connection extends ConnectionInvoker private SaslServer saslServer; private SaslClient saslClient; private int idleTimeout = 0; - private String _authorizationID; private Map<String,Object> _serverProperties; private String userID; private ConnectionSettings conSettings; private SecurityLayer securityLayer; private String _clientId; - - private static final AtomicLong idGenerator = new AtomicLong(0); - private final long _connectionId = idGenerator.incrementAndGet(); + private final AtomicBoolean connectionLost = new AtomicBoolean(false); - + public Connection() {} public void setConnectionDelegate(ConnectionDelegate delegate) @@ -233,14 +239,24 @@ public class Connection extends ConnectionInvoker conSettings = settings; state = OPENING; userID = settings.getUsername(); - delegate = new ClientDelegate(settings); - - TransportBuilder transport = new TransportBuilder(); - transport.init(this); - this.sender = transport.buildSenderPipe(); - transport.buildReceiverPipe(this); - this.securityLayer = transport.getSecurityLayer(); - + + securityLayer = SecurityLayerFactory.newInstance(getConnectionSettings()); + + OutgoingNetworkTransport transport = Transport.getOutgoingTransportInstance(ProtocolVersion.v0_10); + Receiver<ByteBuffer> secureReceiver = securityLayer.receiver(new InputHandler(new Assembler(this))); + if(secureReceiver instanceof ConnectionListener) + { + addConnectionListener((ConnectionListener)secureReceiver); + } + + NetworkConnection network = transport.connect(settings, secureReceiver, null); + final Sender<ByteBuffer> secureSender = securityLayer.sender(network.getSender()); + if(secureSender instanceof ConnectionListener) + { + addConnectionListener((ConnectionListener)secureSender); + } + sender = new Disassembler(secureSender, settings.getMaxFrameSize()); + send(new ProtocolHeader(1, 0, 10)); Waiter w = new Waiter(lock, timeout); @@ -321,23 +337,31 @@ public class Connection extends ConnectionInvoker Waiter w = new Waiter(lock, timeout); while (w.hasTime() && state != OPEN && error == null) { - w.await(); + w.await(); } - + if (state != OPEN) { throw new ConnectionException("Timed out waiting for connection to be ready. Current state is :" + state); } - + Session ssn = _sessionFactory.newSession(this, name, expiry); - sessions.put(name, ssn); + registerSession(ssn); map(ssn); ssn.attach(); return ssn; } } - void removeSession(Session ssn) + public void registerSession(Session ssn) + { + synchronized (lock) + { + sessions.put(ssn.getName(),ssn); + } + } + + public void removeSession(Session ssn) { synchronized (lock) { @@ -352,11 +376,6 @@ public class Connection extends ConnectionInvoker _sessionFactory = sessionFactory; } - public long getConnectionId() - { - return _connectionId; - } - public ConnectionDelegate getConnectionDelegate() { return delegate; @@ -405,7 +424,7 @@ public class Connection extends ConnectionInvoker else { throw new ProtocolViolationException( - "Received frames for an already dettached session", null); + "Received frames for an already detached session", null); } } @@ -454,7 +473,7 @@ public class Connection extends ConnectionInvoker } } - protected Session getSession(int channel) + public Session getSession(int channel) { synchronized (lock) { @@ -468,18 +487,10 @@ public class Connection extends ConnectionInvoker { for (Session ssn : sessions.values()) { - if (ssn.isTransacted()) - { - removeSession(ssn); - ssn.setState(Session.State.CLOSED); - } - else - { - map(ssn); - ssn.attach(); - ssn.resume(); - } + map(ssn); + ssn.resume(); } + setState(OPEN); } } @@ -515,10 +526,6 @@ public class Connection extends ConnectionInvoker { synchronized (lock) { - for (Session ssn : channels.values()) - { - ssn.closeCode(close); - } ConnectionCloseCode code = close.getReplyCode(); if (code != ConnectionCloseCode.NORMAL) { @@ -566,12 +573,12 @@ public class Connection extends ConnectionInvoker { close(ConnectionCloseCode.NORMAL, null); } - + public void mgmtClose() { close(ConnectionCloseCode.CONNECTION_FORCED, "The connection was closed using the broker's management interface."); } - + public void close(ConnectionCloseCode replyCode, String replyText, Option ... _options) { synchronized (lock) @@ -645,16 +652,6 @@ public class Connection extends ConnectionInvoker return idleTimeout; } - public void setAuthorizationID(String authorizationID) - { - _authorizationID = authorizationID; - } - - public String getAuthorizationID() - { - return _authorizationID; - } - public String getUserID() { return userID; @@ -684,15 +681,33 @@ public class Connection extends ConnectionInvoker { return conSettings; } - + public SecurityLayer getSecurityLayer() { return securityLayer; } - + public boolean isConnectionResuming() { return connectionLost.get(); } + protected Collection<Session> getChannels() + { + return channels.values(); + } + + public boolean hasSessionWithName(final String name) + { + return sessions.containsKey(new Binary(name.getBytes())); + } + + public void notifyFailoverRequired() + { + List<Session> values = new ArrayList<Session>(channels.values()); + for (Session ssn : values) + { + ssn.notifyFailoverRequired(); + } + } } diff --git a/java/common/src/main/java/org/apache/qpid/transport/ConnectionDelegate.java b/java/common/src/main/java/org/apache/qpid/transport/ConnectionDelegate.java index 88dd2d6afa..393301659d 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/ConnectionDelegate.java +++ b/java/common/src/main/java/org/apache/qpid/transport/ConnectionDelegate.java @@ -85,7 +85,7 @@ public abstract class ConnectionDelegate @Override public void sessionDetach(Connection conn, SessionDetach dtc) { Session ssn = conn.getSession(dtc.getChannel()); - ssn.sessionDetached(dtc.getName(), SessionDetachCode.NORMAL); + ssn.sessionDetached(dtc.getName(), ssn.getDetachCode() == null? SessionDetachCode.NORMAL: ssn.getDetachCode()); conn.unmap(ssn); ssn.closed(); } @@ -95,6 +95,7 @@ public abstract class ConnectionDelegate Session ssn = conn.getSession(dtc.getChannel()); if (ssn != null) { + ssn.setDetachCode(dtc.getCode()); conn.unmap(ssn); ssn.closed(); } diff --git a/java/common/src/main/java/org/apache/qpid/transport/ConnectionSettings.java b/java/common/src/main/java/org/apache/qpid/transport/ConnectionSettings.java index 08678b213b..37a8e594c0 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/ConnectionSettings.java +++ b/java/common/src/main/java/org/apache/qpid/transport/ConnectionSettings.java @@ -30,6 +30,8 @@ import java.util.Map; */ public class ConnectionSettings { + public static final String WILDCARD_ADDRESS = "*"; + String protocol = "tcp"; String host = "localhost"; String vhost; @@ -56,7 +58,7 @@ public class ConnectionSettings boolean verifyHostname; // SASL props - String saslMechs = System.getProperty("qpid.sasl_mechs", "PLAIN"); + String saslMechs = System.getProperty("qpid.sasl_mechs", null); String saslProtocol = System.getProperty("qpid.sasl_protocol", "AMQP"); String saslServerName = System.getProperty("qpid.sasl_server_name", "localhost"); boolean useSASLEncryption; diff --git a/java/common/src/main/java/org/apache/qpid/transport/NetworkDriver.java b/java/common/src/main/java/org/apache/qpid/transport/NetworkDriver.java deleted file mode 100644 index 86af97bf7e..0000000000 --- a/java/common/src/main/java/org/apache/qpid/transport/NetworkDriver.java +++ /dev/null @@ -1,63 +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.transport; - -import java.net.BindException; -import java.net.InetAddress; -import java.net.SocketAddress; - -import org.apache.qpid.protocol.ProtocolEngine; -import org.apache.qpid.protocol.ProtocolEngineFactory; -import org.apache.qpid.ssl.SSLContextFactory; - -public interface NetworkDriver extends Sender<java.nio.ByteBuffer> -{ - // Creates a NetworkDriver which attempts to connect to destination on port and attaches the ProtocolEngine to - // it using the SSLContextFactory if provided - void open(int port, InetAddress destination, ProtocolEngine engine, - 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 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; - - // 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 - */ - 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/java/common/src/main/java/org/apache/qpid/transport/NetworkDriverConfiguration.java b/java/common/src/main/java/org/apache/qpid/transport/NetworkTransportConfiguration.java index c38afe5dd5..8d3f7a779a 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/NetworkDriverConfiguration.java +++ b/java/common/src/main/java/org/apache/qpid/transport/NetworkTransportConfiguration.java @@ -25,20 +25,22 @@ package org.apache.qpid.transport; * 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 +public interface NetworkTransportConfiguration { // Taken from Socket - Boolean getKeepAlive(); - Boolean getOOBInline(); - Boolean getReuseAddress(); - Integer getSoLinger(); // null means off - Integer getSoTimeout(); Boolean getTcpNoDelay(); - Integer getTrafficClass(); // The amount of memory in bytes to allocate to the incoming buffer Integer getReceiveBufferSize(); // The amount of memory in bytes to allocate to the outgoing buffer - Integer getSendBufferSize(); -} + Integer getSendBufferSize(); + + Integer getPort(); + + String getHost(); + + String getTransport(); + + Integer getConnectorProcessors(); +} diff --git a/java/common/src/main/java/org/apache/mina/filter/WriteBufferFullExeception.java b/java/common/src/main/java/org/apache/qpid/transport/SenderClosedException.java index 47f19aa76d..924c327861 100644 --- a/java/common/src/main/java/org/apache/mina/filter/WriteBufferFullExeception.java +++ b/java/common/src/main/java/org/apache/qpid/transport/SenderClosedException.java @@ -1,6 +1,4 @@ -package org.apache.mina.filter; - -import org.apache.mina.common.IoFilter;/* +/* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -20,29 +18,35 @@ import org.apache.mina.common.IoFilter;/* * under the License. * */ +package org.apache.qpid.transport; + -public class WriteBufferFullExeception extends RuntimeException +/** + * SenderClosedException + * + */ + +public class SenderClosedException extends SenderException { - private IoFilter.WriteRequest _writeRequest; - public WriteBufferFullExeception() + public SenderClosedException(String message, Throwable cause) { - this(null); + super(message, cause); } - public WriteBufferFullExeception(IoFilter.WriteRequest writeRequest) + public SenderClosedException(String message) { - _writeRequest = writeRequest; + super(message); } - - public void setWriteRequest(IoFilter.WriteRequest writeRequest) + public SenderClosedException(Throwable cause) { - _writeRequest = writeRequest; + super(cause); } - public IoFilter.WriteRequest getWriteRequest() + public void rethrow() { - return _writeRequest; + throw new SenderClosedException(getMessage(), this); } + } diff --git a/java/common/src/main/java/org/apache/qpid/transport/ServerDelegate.java b/java/common/src/main/java/org/apache/qpid/transport/ServerDelegate.java index f21df251da..82fa6ca473 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/ServerDelegate.java +++ b/java/common/src/main/java/org/apache/qpid/transport/ServerDelegate.java @@ -75,10 +75,7 @@ public class ServerDelegate extends ConnectionDelegate if (mechanism == null || mechanism.length() == 0) { - conn.connectionTune - (getChannelMax(), - org.apache.qpid.transport.network.ConnectionBinding.MAX_FRAME_SIZE, - 0, getHeartbeatMax()); + tuneAuthorizedConnection(conn); return; } @@ -97,8 +94,7 @@ public class ServerDelegate extends ConnectionDelegate } catch (SaslException e) { - conn.exception(e); - conn.connectionClose(ConnectionCloseCode.CONNECTION_FORCED, e.getMessage()); + connectionAuthFailed(conn, e); } } @@ -109,33 +105,52 @@ public class ServerDelegate extends ConnectionDelegate return ss; } - private void secure(Connection conn, byte[] response) + protected void secure(final SaslServer ss, final Connection conn, final byte[] response) { - SaslServer ss = conn.getSaslServer(); try { byte[] challenge = ss.evaluateResponse(response); if (ss.isComplete()) { ss.dispose(); - conn.connectionTune - (getChannelMax(), - org.apache.qpid.transport.network.ConnectionBinding.MAX_FRAME_SIZE, - 0, getHeartbeatMax()); - conn.setAuthorizationID(ss.getAuthorizationID()); + tuneAuthorizedConnection(conn); } else { - conn.connectionSecure(challenge); + connectionAuthContinue(conn, challenge); } } catch (SaslException e) { - conn.exception(e); - conn.connectionClose(ConnectionCloseCode.CONNECTION_FORCED, e.getMessage()); + connectionAuthFailed(conn, e); } } + protected void connectionAuthFailed(final Connection conn, Exception e) + { + conn.exception(e); + conn.connectionClose(ConnectionCloseCode.CONNECTION_FORCED, e.getMessage()); + } + + protected void connectionAuthContinue(final Connection conn, byte[] challenge) + { + conn.connectionSecure(challenge); + } + + protected void tuneAuthorizedConnection(final Connection conn) + { + conn.connectionTune + (getChannelMax(), + org.apache.qpid.transport.network.ConnectionBinding.MAX_FRAME_SIZE, + 0, getHeartbeatMax()); + } + + protected void secure(final Connection conn, final byte[] response) + { + final SaslServer ss = conn.getSaslServer(); + secure(ss, conn, response); + } + protected int getHeartbeatMax() { return 0xFFFF; @@ -155,22 +170,7 @@ public class ServerDelegate extends ConnectionDelegate @Override public void connectionTuneOk(Connection conn, ConnectionTuneOk ok) { - int okChannelMax = ok.getChannelMax(); - - if (okChannelMax > getChannelMax()) - { - _logger.error("Connection '" + conn.getConnectionId() + "' being severed, " + - "client connectionTuneOk returned a channelMax (" + okChannelMax + - ") above the servers offered limit (" + getChannelMax() +")"); - //Due to the error we must forcefully close the connection without negotiation - conn.getSender().close(); - return; - } - - //0 means no implied limit, except available server resources - //(or that forced by protocol limitations [0xFFFF]) - conn.setChannelMax(okChannelMax == 0 ? Connection.MAX_CHANNEL_MAX : okChannelMax); } @Override @@ -200,4 +200,11 @@ public class ServerDelegate extends ConnectionDelegate ssn.sessionAttached(atc.getName()); ssn.setState(Session.State.OPEN); } + + protected void setConnectionTuneOkChannelMax(final Connection conn, final int okChannelMax) + { + //0 means no implied limit, except available server resources + //(or that forced by protocol limitations [0xFFFF]) + conn.setChannelMax(okChannelMax == 0 ? Connection.MAX_CHANNEL_MAX : okChannelMax); + } } diff --git a/java/common/src/main/java/org/apache/qpid/transport/Session.java b/java/common/src/main/java/org/apache/qpid/transport/Session.java index 214d4534c1..321e5256b2 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/Session.java +++ b/java/common/src/main/java/org/apache/qpid/transport/Session.java @@ -30,6 +30,8 @@ import static org.apache.qpid.transport.Session.State.DETACHED; import static org.apache.qpid.transport.Session.State.NEW; import static org.apache.qpid.transport.Session.State.OPEN; import static org.apache.qpid.transport.Session.State.RESUMING; + +import org.apache.qpid.configuration.ClientProperties; import org.apache.qpid.transport.network.Frame; import static org.apache.qpid.transport.util.Functions.mod; import org.apache.qpid.transport.util.Logger; @@ -42,10 +44,13 @@ import static org.apache.qpid.util.Serial.max; import static org.apache.qpid.util.Strings.toUTF8; import java.nio.ByteBuffer; +import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; /** * Session @@ -55,7 +60,6 @@ import java.util.concurrent.TimeUnit; public class Session extends SessionInvoker { - private static final Logger log = Logger.get(Session.class); public enum State { NEW, DETACHED, RESUMING, OPEN, CLOSING, CLOSED } @@ -89,7 +93,9 @@ public class Session extends SessionInvoker private int channel; private SessionDelegate delegate; private SessionListener listener = new DefaultSessionListener(); - private long timeout = 60000; + private final long timeout = Long.getLong(ClientProperties.QPID_SYNC_OP_TIMEOUT, + Long.getLong(ClientProperties.AMQJ_DEFAULT_SYNCWRITE_TIMEOUT, + ClientProperties.DEFAULT_SYNC_OPERATION_TIMEOUT)); private boolean autoSync = false; private boolean incomingInit; @@ -117,7 +123,11 @@ public class Session extends SessionInvoker private Thread resumer = null; private boolean transacted = false; - + private SessionDetachCode detachCode; + private final Object stateLock = new Object(); + + private final AtomicBoolean _failoverRequired = new AtomicBoolean(false); + protected Session(Connection connection, Binary name, long expiry) { this(connection, new SessionDelegate(), name, expiry); @@ -250,8 +260,11 @@ public class Session extends SessionInvoker void resume() { + _failoverRequired.set(false); synchronized (commands) { + attach(); + for (int i = maxComplete + 1; lt(i, commandsOut); i++) { Method m = commands[mod(i, commands.length)]; @@ -262,16 +275,48 @@ public class Session extends SessionInvoker } else if (m instanceof MessageTransfer) { - ((MessageTransfer)m).getHeader().get(DeliveryProperties.class).setRedelivered(true); + MessageTransfer xfr = (MessageTransfer)m; + + if (xfr.getHeader() != null) + { + if (xfr.getHeader().get(DeliveryProperties.class) != null) + { + xfr.getHeader().get(DeliveryProperties.class).setRedelivered(true); + } + else + { + Struct[] structs = xfr.getHeader().getStructs(); + DeliveryProperties deliveryProps = new DeliveryProperties(); + deliveryProps.setRedelivered(true); + + List<Struct> list = Arrays.asList(structs); + list.add(deliveryProps); + xfr.setHeader(new Header(list)); + } + + } + else + { + DeliveryProperties deliveryProps = new DeliveryProperties(); + deliveryProps.setRedelivered(true); + xfr.setHeader(new Header(deliveryProps)); + } } sessionCommandPoint(m.getId(), 0); send(m); } - + sessionCommandPoint(commandsOut, 0); + sessionFlush(COMPLETED); resumer = Thread.currentThread(); state = RESUMING; + + if(isTransacted()) + { + txSelect(); + } + listener.resumed(this); resumer = null; } @@ -418,11 +463,14 @@ public class Session extends SessionInvoker synchronized (commands) { - if (state == DETACHED || state == CLOSING) + if (state == DETACHED || state == CLOSING || state == CLOSED) { return; } - sessionCompleted(copy, options); + if (copy.size() > 0) + { + sessionCompleted(copy, options); + } } } @@ -532,17 +580,6 @@ public class Session extends SessionInvoker { if (m.getEncodedTrack() == Frame.L4) { - - if (state == DETACHED && transacted) - { - state = CLOSED; - delegate.closed(this); - connection.removeSession(this); - throw new SessionException( - "Session failed over, possibly in the middle of a transaction. " + - "Closing the session. Any Transaction in progress will be rolledback."); - } - if (m.hasPayload()) { acquireCredit(); @@ -562,11 +599,12 @@ public class Session extends SessionInvoker if (state != OPEN && state != CLOSED && state != CLOSING) { Thread current = Thread.currentThread(); - if (!current.equals(resumer)) + if (!current.equals(resumer) ) { Waiter w = new Waiter(commands, timeout); while (w.hasTime() && (state != OPEN && state != CLOSED)) { + checkFailoverRequired("Command was interrupted because of failover, before being sent"); w.await(); } } @@ -635,6 +673,7 @@ public class Session extends SessionInvoker } } } + checkFailoverRequired("Command was interrupted because of failover, before being sent"); w.await(); } } @@ -661,7 +700,12 @@ public class Session extends SessionInvoker { sessionCommandPoint(0, 0); } - if ((!closing && !transacted && m instanceof MessageTransfer) || m.hasCompletionListener()) + + boolean replayTransfer = !closing && !transacted && + m instanceof MessageTransfer && + ! m.isUnreliable(); + + if ((replayTransfer) || m.hasCompletionListener()) { commands[mod(next, commands.length)] = m; commandBytes += m.getBodySize(); @@ -724,6 +768,14 @@ public class Session extends SessionInvoker } } + private void checkFailoverRequired(String message) + { + if (_failoverRequired.get()) + { + throw new SessionException(message); + } + } + protected boolean shouldIssueFlush(int next) { return (next % 65536) == 0; @@ -749,6 +801,7 @@ public class Session extends SessionInvoker Waiter w = new Waiter(commands, timeout); while (w.hasTime() && state != CLOSED && lt(maxComplete, point)) { + checkFailoverRequired("Session sync was interrupted by failover."); log.debug("%s waiting for[%d]: %d, %s", this, point, maxComplete, commands); w.await(); } @@ -809,13 +862,6 @@ public class Session extends SessionInvoker } } - private ConnectionClose close = null; - - void closeCode(ConnectionClose close) - { - this.close = close; - } - ExecutionException getException() { synchronized (results) @@ -866,6 +912,7 @@ public class Session extends SessionInvoker Waiter w = new Waiter(this, timeout); while (w.hasTime() && state != CLOSED && !isDone()) { + checkFailoverRequired("Operation was interrupted by failover."); log.debug("%s waiting for result: %s", Session.this, this); w.await(); } @@ -877,7 +924,12 @@ public class Session extends SessionInvoker } else if (state == CLOSED) { - throw new SessionException(getException()); + ExecutionException ex = getException(); + if(ex == null) + { + throw new SessionClosedException(); + } + throw new SessionException(ex); } else { @@ -926,16 +978,29 @@ public class Session extends SessionInvoker public void close() { + if (log.isDebugEnabled()) + { + log.debug("Closing [%s] in state [%s]", this, state); + } synchronized (commands) { - state = CLOSING; - setClose(true); - sessionRequestTimeout(0); - sessionDetach(name.getBytes()); - - awaitClose(); - - + switch(state) + { + case DETACHED: + state = CLOSED; + delegate.closed(this); + connection.removeSession(this); + listener.closed(this); + break; + case CLOSED: + break; + default: + state = CLOSING; + setClose(true); + sessionRequestTimeout(0); + sessionDetach(name.getBytes()); + awaitClose(); + } } } @@ -944,6 +1009,7 @@ public class Session extends SessionInvoker Waiter w = new Waiter(commands, timeout); while (w.hasTime() && state != CLOSED) { + checkFailoverRequired("close() was interrupted by failover."); w.await(); } @@ -995,7 +1061,8 @@ public class Session extends SessionInvoker if(state == CLOSED) { - connection.removeSession(this); + connection.removeSession(this); + listener.closed(this); } } @@ -1008,13 +1075,78 @@ public class Session extends SessionInvoker { return String.format("ssn:%s", name); } - + public void setTransacted(boolean b) { this.transacted = b; } - + public boolean isTransacted(){ return transacted; } - + + public void setDetachCode(SessionDetachCode dtc) + { + this.detachCode = dtc; + } + + public SessionDetachCode getDetachCode() + { + return this.detachCode; + } + + public void awaitOpen() + { + switch (state) + { + case NEW: + synchronized(stateLock) + { + Waiter w = new Waiter(stateLock, timeout); + while (w.hasTime() && state == NEW) + { + checkFailoverRequired("Session opening was interrupted by failover."); + w.await(); + } + } + + if (state != OPEN) + { + throw new SessionException("Timed out waiting for Session to open"); + } + break; + case DETACHED: + case CLOSING: + case CLOSED: + throw new SessionException("Session closed"); + default : + break; + } + } + + public Object getStateLock() + { + return stateLock; + } + + protected void notifyFailoverRequired() + { + //ensure any operations waiting are aborted to + //prevent them waiting for timeout for 60 seconds + //and possibly preventing failover proceeding + _failoverRequired.set(true); + synchronized (commands) + { + commands.notifyAll(); + } + synchronized (results) + { + for (ResultFuture<?> result : results.values()) + { + synchronized(result) + { + result.notifyAll(); + } + } + } + } } diff --git a/java/common/src/main/java/org/apache/qpid/transport/SessionDelegate.java b/java/common/src/main/java/org/apache/qpid/transport/SessionDelegate.java index 5d8e4d5565..3341149e5f 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/SessionDelegate.java +++ b/java/common/src/main/java/org/apache/qpid/transport/SessionDelegate.java @@ -76,6 +76,10 @@ public class SessionDelegate @Override public void sessionAttached(Session ssn, SessionAttached atc) { ssn.setState(Session.State.OPEN); + synchronized (ssn.getStateLock()) + { + ssn.getStateLock().notifyAll(); + } } @Override public void sessionTimeout(Session ssn, SessionTimeout t) @@ -202,11 +206,19 @@ public class SessionDelegate public void closed(Session session) { - log.warn("CLOSED: [%s]", session); + log.debug("CLOSED: [%s]", session); + synchronized (session.getStateLock()) + { + session.getStateLock().notifyAll(); + } } public void detached(Session session) { - log.warn("DETACHED: [%s]", session); + log.debug("DETACHED: [%s]", session); + synchronized (session.getStateLock()) + { + session.getStateLock().notifyAll(); + } } } diff --git a/java/common/src/main/java/org/apache/qpid/transport/TransportBuilder.java b/java/common/src/main/java/org/apache/qpid/transport/TransportBuilder.java deleted file mode 100644 index c08909c6e4..0000000000 --- a/java/common/src/main/java/org/apache/qpid/transport/TransportBuilder.java +++ /dev/null @@ -1,78 +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.transport; - -import java.nio.ByteBuffer; - -import org.apache.qpid.transport.network.Assembler; -import org.apache.qpid.transport.network.Disassembler; -import org.apache.qpid.transport.network.InputHandler; -import org.apache.qpid.transport.network.NetworkTransport; -import org.apache.qpid.transport.network.Transport; -import org.apache.qpid.transport.network.security.SecurityLayer; - -public class TransportBuilder -{ - private Connection con; - private ConnectionSettings settings; - private NetworkTransport transport; - private SecurityLayer securityLayer = new SecurityLayer(); - - public void init(Connection con) throws TransportException - { - this.con = con; - this.settings = con.getConnectionSettings(); - transport = Transport.getTransport(); - transport.init(settings); - securityLayer.init(con); - } - - public Sender<ProtocolEvent> buildSenderPipe() - { - ConnectionSettings settings = con.getConnectionSettings(); - - // Io layer - Sender<ByteBuffer> sender = transport.sender(); - - // Security layer - sender = securityLayer.sender(sender); - - Disassembler dis = new Disassembler(sender, settings.getMaxFrameSize()); - return dis; - } - - public void buildReceiverPipe(Receiver<ProtocolEvent> delegate) - { - Receiver<ByteBuffer> receiver = new InputHandler(new Assembler(delegate)); - - // Security layer - receiver = securityLayer.receiver(receiver); - - //Io layer - transport.receiver(receiver); - } - - public SecurityLayer getSecurityLayer() - { - return securityLayer; - } - -}
\ No newline at end of file diff --git a/java/common/src/main/java/org/apache/qpid/transport/codec/AbstractEncoder.java b/java/common/src/main/java/org/apache/qpid/transport/codec/AbstractEncoder.java index 908d14a307..0ccfcfcb70 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/codec/AbstractEncoder.java +++ b/java/common/src/main/java/org/apache/qpid/transport/codec/AbstractEncoder.java @@ -63,6 +63,7 @@ abstract class AbstractEncoder implements Encoder ENCODINGS.put(Double.class, Type.DOUBLE); ENCODINGS.put(Character.class, Type.CHAR); ENCODINGS.put(byte[].class, Type.VBIN32); + ENCODINGS.put(UUID.class, Type.UUID); } private final Map<String,byte[]> str8cache = new LinkedHashMap<String,byte[]>() diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/IncomingNetworkTransport.java b/java/common/src/main/java/org/apache/qpid/transport/network/IncomingNetworkTransport.java new file mode 100644 index 0000000000..b371df639e --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/network/IncomingNetworkTransport.java @@ -0,0 +1,31 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.transport.network; + +import javax.net.ssl.SSLContext; + +import org.apache.qpid.protocol.ProtocolEngineFactory; +import org.apache.qpid.transport.NetworkTransportConfiguration; + +public interface IncomingNetworkTransport extends NetworkTransport +{ + public void accept(NetworkTransportConfiguration config, ProtocolEngineFactory factory, SSLContext sslContext); +}
\ No newline at end of file diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/NetworkConnection.java b/java/common/src/main/java/org/apache/qpid/transport/network/NetworkConnection.java new file mode 100644 index 0000000000..7384702525 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/network/NetworkConnection.java @@ -0,0 +1,49 @@ +/* + * + * 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; + +import java.net.SocketAddress; +import java.nio.ByteBuffer; + +import org.apache.qpid.transport.Sender; + +public interface NetworkConnection +{ + Sender<ByteBuffer> getSender(); + + void start(); + + void close(); + + /** + * Returns the remote address of the underlying socket. + */ + SocketAddress getRemoteAddress(); + + /** + * Returns the local address of the underlying socket. + */ + SocketAddress getLocalAddress(); + + void setMaxWriteIdle(int sec); + + void setMaxReadIdle(int sec); +}
\ No newline at end of file diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/NetworkTransport.java b/java/common/src/main/java/org/apache/qpid/transport/network/NetworkTransport.java index 5e12d7e7c6..f71d39c381 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/network/NetworkTransport.java +++ b/java/common/src/main/java/org/apache/qpid/transport/network/NetworkTransport.java @@ -20,19 +20,11 @@ */ package org.apache.qpid.transport.network; -import java.nio.ByteBuffer; - -import org.apache.qpid.transport.Receiver; -import org.apache.qpid.transport.Sender; -import org.apache.qpid.transport.ConnectionSettings; - +/** + * A network transport is responsible for the establishment of network connections. + * NetworkTransport implementations are pluggable via the {@link Transport} class. + */ public interface NetworkTransport { - public void init(ConnectionSettings settings); - - public Sender<ByteBuffer> sender(); - - public void receiver(Receiver<ByteBuffer> delegate); - public void close(); -}
\ No newline at end of file +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/OutgoingNetworkTransport.java b/java/common/src/main/java/org/apache/qpid/transport/network/OutgoingNetworkTransport.java new file mode 100644 index 0000000000..c3c248761c --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/network/OutgoingNetworkTransport.java @@ -0,0 +1,35 @@ +/* + * + * 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; + +import java.nio.ByteBuffer; + +import javax.net.ssl.SSLContext; + +import org.apache.qpid.transport.ConnectionSettings; +import org.apache.qpid.transport.Receiver; + +public interface OutgoingNetworkTransport extends NetworkTransport +{ + public NetworkConnection getConnection(); + + public NetworkConnection connect(ConnectionSettings settings, Receiver<ByteBuffer> delegate, SSLContext sslContext); +}
\ No newline at end of file diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/Transport.java b/java/common/src/main/java/org/apache/qpid/transport/network/Transport.java index f0bf04d04f..da4349ba86 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/network/Transport.java +++ b/java/common/src/main/java/org/apache/qpid/transport/network/Transport.java @@ -1,5 +1,5 @@ /* - * + * * 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 @@ -7,50 +7,128 @@ * 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; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.apache.qpid.framing.ProtocolVersion; import org.apache.qpid.transport.TransportException; public class Transport -{ - private final static Class<?> transportClass; - - static +{ + public static final String QPID_TRANSPORT_PROPNAME = "qpid.transport"; + public static final String QPID_TRANSPORT_V0_8_PROPNAME = "qpid.transport.v0_8"; + public static final String QPID_TRANSPORT_V0_9_PROPNAME = "qpid.transport.v0_9"; + public static final String QPID_TRANSPORT_V0_9_1_PROPNAME = "qpid.transport.v0_9_1"; + public static final String QPID_TRANSPORT_V0_10_PROPNAME = "qpid.transport.v0_10"; + public static final String QPID_BROKER_TRANSPORT_PROPNAME = "qpid.broker.transport"; + + // Can't reference the class directly here, as this would preclude the ability to bundle transports separately. + private static final String IO_TRANSPORT_CLASSNAME = "org.apache.qpid.transport.network.io.IoNetworkTransport"; + + public static final String TCP = "tcp"; + + private final static Map<ProtocolVersion,String> OUTGOING_PROTOCOL_TO_IMPLDEFAULTS_MAP; + + static { - try + final Map<ProtocolVersion,String> map = new HashMap<ProtocolVersion, String>(); + map.put(ProtocolVersion.v8_0, IO_TRANSPORT_CLASSNAME); + map.put(ProtocolVersion.v0_9, IO_TRANSPORT_CLASSNAME); + map.put(ProtocolVersion.v0_91, IO_TRANSPORT_CLASSNAME); + map.put(ProtocolVersion.v0_10, IO_TRANSPORT_CLASSNAME); + + OUTGOING_PROTOCOL_TO_IMPLDEFAULTS_MAP = Collections.unmodifiableMap(map); + } + + public static IncomingNetworkTransport getIncomingTransportInstance() + { + return (IncomingNetworkTransport) loadTransportClass( + System.getProperty(QPID_BROKER_TRANSPORT_PROPNAME, IO_TRANSPORT_CLASSNAME)); + } + + public static OutgoingNetworkTransport getOutgoingTransportInstance( + final ProtocolVersion protocolVersion) + { + + final String overrride = getOverrideClassNameFromSystemProperty(protocolVersion); + final String networkTransportClassName; + if (overrride != null) { - transportClass = - Class.forName(System.getProperty("qpid.transport", - "org.apache.qpid.transport.network.io.IoNetworkTransport")); - + networkTransportClassName = overrride; } - catch(Exception e) + else { - throw new Error("Error occured while loading Qpid Transport",e); + networkTransportClassName = OUTGOING_PROTOCOL_TO_IMPLDEFAULTS_MAP.get(protocolVersion); } + + return (OutgoingNetworkTransport) loadTransportClass(networkTransportClassName); } - - public static NetworkTransport getTransport() throws TransportException + + private static NetworkTransport loadTransportClass(final String networkTransportClassName) { + if (networkTransportClassName == null) + { + throw new IllegalArgumentException("transport class name must not be null"); + } + try { - return (NetworkTransport)transportClass.newInstance(); + final Class<?> clazz = Class.forName(networkTransportClassName); + return (NetworkTransport) clazz.newInstance(); } - catch (Exception e) + catch (InstantiationException e) { - throw new TransportException("Error while creating a new transport instance",e); + throw new TransportException("Unable to instantiate transport class " + networkTransportClassName, e); } + catch (IllegalAccessException e) + { + throw new TransportException("Access exception " + networkTransportClassName, e); + } + catch (ClassNotFoundException e) + { + throw new TransportException("Unable to load transport class " + networkTransportClassName, e); + } + } + + private static String getOverrideClassNameFromSystemProperty(final ProtocolVersion protocolVersion) + { + final String protocolSpecificSystemProperty; + + if (ProtocolVersion.v0_10.equals(protocolVersion)) + { + protocolSpecificSystemProperty = QPID_TRANSPORT_V0_10_PROPNAME; + } + else if (ProtocolVersion.v0_91.equals(protocolVersion)) + { + protocolSpecificSystemProperty = QPID_TRANSPORT_V0_9_1_PROPNAME; + } + else if (ProtocolVersion.v0_9.equals(protocolVersion)) + { + protocolSpecificSystemProperty = QPID_TRANSPORT_V0_9_PROPNAME; + } + else if (ProtocolVersion.v8_0.equals(protocolVersion)) + { + protocolSpecificSystemProperty = QPID_TRANSPORT_V0_8_PROPNAME; + } + else + { + throw new IllegalArgumentException("Unknown ProtocolVersion " + protocolVersion); + } + + return System.getProperty(protocolSpecificSystemProperty, System.getProperty(QPID_TRANSPORT_PROPNAME)); } -}
\ No newline at end of file +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/io/InputHandler_0_9.java b/java/common/src/main/java/org/apache/qpid/transport/network/io/InputHandler_0_9.java deleted file mode 100644 index ecc5f6d07c..0000000000 --- a/java/common/src/main/java/org/apache/qpid/transport/network/io/InputHandler_0_9.java +++ /dev/null @@ -1,130 +0,0 @@ -package org.apache.qpid.transport.network.io; -/* - * - * 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.nio.ByteBuffer; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQFrame; -import org.apache.qpid.framing.AMQFrameDecodingException; -import org.apache.qpid.framing.AMQMethodBody; -import org.apache.qpid.framing.AMQMethodBodyFactory; -import org.apache.qpid.framing.BodyFactory; -import org.apache.qpid.framing.ContentBody; -import org.apache.qpid.framing.ContentBodyFactory; -import org.apache.qpid.framing.ContentHeaderBody; -import org.apache.qpid.framing.ContentHeaderBodyFactory; -import org.apache.qpid.framing.HeartbeatBody; -import org.apache.qpid.framing.HeartbeatBodyFactory; -import org.apache.qpid.framing.MethodRegistry; -import org.apache.qpid.protocol.AMQVersionAwareProtocolSession; -import org.apache.qpid.transport.Receiver; - -public class InputHandler_0_9 implements Receiver<ByteBuffer> -{ - - private AMQVersionAwareProtocolSession _session; - private MethodRegistry _registry; - private BodyFactory bodyFactory; - private static final BodyFactory[] _bodiesSupported = new BodyFactory[Byte.MAX_VALUE]; - - static - { - _bodiesSupported[ContentHeaderBody.TYPE] = ContentHeaderBodyFactory.getInstance(); - _bodiesSupported[ContentBody.TYPE] = ContentBodyFactory.getInstance(); - _bodiesSupported[HeartbeatBody.TYPE] = new HeartbeatBodyFactory(); - } - - public InputHandler_0_9(AMQVersionAwareProtocolSession session) - { - _session = session; - _registry = _session.getMethodRegistry(); - } - - public void closed() - { - // AS FIXME: implement - } - - public void exception(Throwable t) - { - // TODO: propogate exception to things - t.printStackTrace(); - } - - public void received(ByteBuffer buf) - { - org.apache.mina.common.ByteBuffer in = org.apache.mina.common.ByteBuffer.wrap(buf); - try - { - final byte type = in.get(); - if (type == AMQMethodBody.TYPE) - { - bodyFactory = new AMQMethodBodyFactory(_session); - } - else - { - bodyFactory = _bodiesSupported[type]; - } - - if (bodyFactory == null) - { - throw new AMQFrameDecodingException(null, "Unsupported frame type: " + type, null); - } - - final int channel = in.getUnsignedShort(); - final long bodySize = in.getUnsignedInt(); - - // bodySize can be zero - if ((channel < 0) || (bodySize < 0)) - { - throw new AMQFrameDecodingException(null, "Undecodable frame: type = " + type + " channel = " + channel - + " bodySize = " + bodySize, null); - } - - AMQFrame frame = new AMQFrame(in, channel, bodySize, bodyFactory); - - byte marker = in.get(); - if ((marker & 0xFF) != 0xCE) - { - throw new AMQFrameDecodingException(null, "End of frame marker not found. Read " + marker + " length=" + bodySize - + " type=" + type, null); - } - - try - { - frame.getBodyFrame().handle(frame.getChannel(), _session); - } - catch (AMQException e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - catch (AMQFrameDecodingException e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - -} diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkConnection.java b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkConnection.java new file mode 100644 index 0000000000..bfc77539ce --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkConnection.java @@ -0,0 +1,99 @@ +/* +* + * 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.io; + +import java.net.Socket; +import java.net.SocketAddress; +import java.nio.ByteBuffer; + +import org.apache.qpid.transport.Receiver; +import org.apache.qpid.transport.Sender; +import org.apache.qpid.transport.network.NetworkConnection; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class IoNetworkConnection implements NetworkConnection +{ + private static final Logger LOGGER = LoggerFactory.getLogger(IoNetworkConnection.class); + private final Socket _socket; + private final long _timeout; + private final IoSender _ioSender; + private final IoReceiver _ioReceiver; + + public IoNetworkConnection(Socket socket, Receiver<ByteBuffer> delegate, + int sendBufferSize, int receiveBufferSize, long timeout) + { + _socket = socket; + _timeout = timeout; + + _ioReceiver = new IoReceiver(_socket, delegate, receiveBufferSize,_timeout); + + _ioSender = new IoSender(_socket, 2 * sendBufferSize, _timeout); + + _ioSender.registerCloseListener(_ioReceiver); + + } + + public void start() + { + _ioSender.initiate(); + _ioReceiver.initiate(); + } + + public Sender<ByteBuffer> getSender() + { + return _ioSender; + } + + public void close() + { + try + { + _ioSender.close(); + } + finally + { + _ioReceiver.close(false); + } + } + + public SocketAddress getRemoteAddress() + { + return _socket.getRemoteSocketAddress(); + } + + public SocketAddress getLocalAddress() + { + return _socket.getLocalSocketAddress(); + } + + public void setMaxWriteIdle(int sec) + { + // TODO implement support for setting heartbeating config in this way + // Currently a socket timeout is used in IoSender + } + + public void setMaxReadIdle(int sec) + { + // TODO implement support for setting heartbeating config in this way + // Currently a socket timeout is used in IoSender + } +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java index dd6a37eca2..e1d1596ec5 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java +++ b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java @@ -21,57 +21,49 @@ package org.apache.qpid.transport.network.io; import java.io.IOException; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.net.SocketException; +import java.net.*; import java.nio.ByteBuffer; -import org.apache.qpid.transport.ConnectionSettings; -import org.apache.qpid.transport.Receiver; -import org.apache.qpid.transport.Sender; -import org.apache.qpid.transport.TransportException; -import org.apache.qpid.transport.network.NetworkTransport; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLServerSocketFactory; + +import org.apache.qpid.protocol.ProtocolEngine; +import org.apache.qpid.protocol.ProtocolEngineFactory; +import org.apache.qpid.transport.*; +import org.apache.qpid.transport.network.IncomingNetworkTransport; +import org.apache.qpid.transport.network.NetworkConnection; +import org.apache.qpid.transport.network.OutgoingNetworkTransport; import org.apache.qpid.transport.util.Logger; -public class IoNetworkTransport implements NetworkTransport, IoContext +public class IoNetworkTransport implements OutgoingNetworkTransport, IncomingNetworkTransport { - static - { - org.apache.mina.common.ByteBuffer.setAllocator - (new org.apache.mina.common.SimpleByteBufferAllocator()); - org.apache.mina.common.ByteBuffer.setUseDirectBuffers - (Boolean.getBoolean("amqj.enableDirectBuffers")); - } - private static final Logger log = Logger.get(IoNetworkTransport.class); + private static final Logger LOGGER = Logger.get(IoNetworkTransport.class); + + private Socket _socket; + private IoNetworkConnection _connection; + private long _timeout = 60000; + private AcceptingThread _acceptor; - private Socket socket; - private Sender<ByteBuffer> sender; - private IoReceiver receiver; - private long timeout = 60000; - private ConnectionSettings settings; - - public void init(ConnectionSettings settings) + public NetworkConnection connect(ConnectionSettings settings, Receiver<ByteBuffer> delegate, SSLContext sslContext) { + int sendBufferSize = settings.getWriteBufferSize(); + int receiveBufferSize = settings.getReadBufferSize(); + try { - this.settings = settings; - InetAddress address = InetAddress.getByName(settings.getHost()); - socket = new Socket(); - socket.setReuseAddress(true); - socket.setTcpNoDelay(settings.isTcpNodelay()); + _socket = new Socket(); + _socket.setReuseAddress(true); + _socket.setTcpNoDelay(settings.isTcpNodelay()); + _socket.setSendBufferSize(sendBufferSize); + _socket.setReceiveBufferSize(receiveBufferSize); - log.debug("default-SO_RCVBUF : %s", socket.getReceiveBufferSize()); - log.debug("default-SO_SNDBUF : %s", socket.getSendBufferSize()); + LOGGER.debug("SO_RCVBUF : %s", _socket.getReceiveBufferSize()); + LOGGER.debug("SO_SNDBUF : %s", _socket.getSendBufferSize()); - socket.setSendBufferSize(settings.getWriteBufferSize()); - socket.setReceiveBufferSize(settings.getReadBufferSize()); - - log.debug("new-SO_RCVBUF : %s", socket.getReceiveBufferSize()); - log.debug("new-SO_SNDBUF : %s", socket.getSendBufferSize()); + InetAddress address = InetAddress.getByName(settings.getHost()); - socket.connect(new InetSocketAddress(address, settings.getPort())); + _socket.connect(new InetSocketAddress(address, settings.getPort())); } catch (SocketException e) { @@ -81,36 +73,159 @@ public class IoNetworkTransport implements NetworkTransport, IoContext { throw new TransportException("Error connecting to broker", e); } - } - public void receiver(Receiver<ByteBuffer> delegate) - { - receiver = new IoReceiver(this, delegate, - 2*settings.getReadBufferSize() , timeout); - } + try + { + _connection = new IoNetworkConnection(_socket, delegate, sendBufferSize, receiveBufferSize, _timeout); + _connection.start(); + } + catch(Exception e) + { + try + { + _socket.close(); + } + catch(IOException ioe) + { + //ignored, throw based on original exception + } - public Sender<ByteBuffer> sender() - { - return new IoSender(this, 2*settings.getWriteBufferSize(), timeout); + throw new TransportException("Error creating network connection", e); + } + + return _connection; } public void close() { - + if(_connection != null) + { + _connection.close(); + } + if(_acceptor != null) + { + _acceptor.close(); + } } - public Sender<ByteBuffer> getSender() + public NetworkConnection getConnection() { - return sender; + return _connection; } - public IoReceiver getReceiver() + public void accept(NetworkTransportConfiguration config, ProtocolEngineFactory factory, SSLContext sslContext) { - return receiver; + + try + { + _acceptor = new AcceptingThread(config, factory, sslContext); + + _acceptor.start(); + } + catch (IOException e) + { + throw new TransportException("Unable to start server socket", e); + } + + } - public Socket getSocket() + private class AcceptingThread extends Thread { - return socket; + private NetworkTransportConfiguration _config; + private ProtocolEngineFactory _factory; + private SSLContext _sslContent; + private ServerSocket _serverSocket; + + private AcceptingThread(NetworkTransportConfiguration config, + ProtocolEngineFactory factory, + SSLContext sslContext) + throws IOException + { + _config = config; + _factory = factory; + _sslContent = sslContext; + + InetSocketAddress address = new InetSocketAddress(config.getHost(), config.getPort()); + + if(sslContext == null) + { + _serverSocket = new ServerSocket(); + } + else + { + SSLServerSocketFactory socketFactory = sslContext.getServerSocketFactory(); + _serverSocket = socketFactory.createServerSocket(); + } + + _serverSocket.bind(address); + _serverSocket.setReuseAddress(true); + + + } + + + /** + Close the underlying ServerSocket if it has not already been closed. + */ + public void close() + { + if (!_serverSocket.isClosed()) + { + try + { + _serverSocket.close(); + } + catch (IOException e) + { + throw new TransportException(e); + } + } + } + + @Override + public void run() + { + try + { + while (true) + { + try + { + Socket socket = _serverSocket.accept(); + socket.setTcpNoDelay(_config.getTcpNoDelay()); + + final Integer sendBufferSize = _config.getSendBufferSize(); + final Integer receiveBufferSize = _config.getReceiveBufferSize(); + + socket.setSendBufferSize(sendBufferSize); + socket.setReceiveBufferSize(receiveBufferSize); + + ProtocolEngine engine = _factory.newProtocolEngine(); + + NetworkConnection connection = new IoNetworkConnection(socket, engine, sendBufferSize, receiveBufferSize, _timeout); + + + engine.setNetworkConnection(connection, connection.getSender()); + + connection.start(); + + + } + catch(RuntimeException e) + { + LOGGER.error(e, "Error in Acceptor thread " + _config.getPort()); + } + } + } + catch (IOException e) + { + LOGGER.debug(e, "SocketException - no new connections will be accepted on port " + + _config.getPort()); + } + } + + } + } diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/io/IoReceiver.java b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoReceiver.java index 19a683d505..d4b5975e54 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/network/io/IoReceiver.java +++ b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoReceiver.java @@ -20,6 +20,7 @@ */ package org.apache.qpid.transport.network.io; +import org.apache.qpid.common.Closeable; import org.apache.qpid.thread.Threading; import org.apache.qpid.transport.Receiver; import org.apache.qpid.transport.TransportException; @@ -37,56 +38,77 @@ import java.util.concurrent.atomic.AtomicBoolean; * */ -final class IoReceiver implements Runnable +final class IoReceiver implements Runnable, Closeable { private static final Logger log = Logger.get(IoReceiver.class); - private final IoContext ioCtx; private final Receiver<ByteBuffer> receiver; private final int bufferSize; private final Socket socket; private final long timeout; private final AtomicBoolean closed = new AtomicBoolean(false); private final Thread receiverThread; - private final boolean shutdownBroken = - ((String) System.getProperties().get("os.name")).matches("(?i).*windows.*"); + private static final boolean shutdownBroken; + static + { + String osName = System.getProperty("os.name"); + shutdownBroken = osName == null ? false : osName.matches("(?i).*windows.*"); + } - public IoReceiver(IoContext ioCtx, Receiver<ByteBuffer> receiver, - int bufferSize, long timeout) + public IoReceiver(Socket socket, Receiver<ByteBuffer> receiver, int bufferSize, long timeout) { - this.ioCtx = ioCtx; this.receiver = receiver; this.bufferSize = bufferSize; - this.socket = ioCtx.getSocket(); + this.socket = socket; this.timeout = timeout; try { + //Create but deliberately don't start the thread. receiverThread = Threading.getThreadFactory().createThread(this); } catch(Exception e) { - throw new Error("Error creating IOReceiver thread",e); + throw new RuntimeException("Error creating IOReceiver thread",e); } receiverThread.setDaemon(true); receiverThread.setName(String.format("IoReceiver - %s", socket.getRemoteSocketAddress())); + } + + public void initiate() + { receiverThread.start(); } + public void close() + { + close(false); + } + void close(boolean block) { if (!closed.getAndSet(true)) { try { - if (shutdownBroken) + try { - socket.close(); + if (shutdownBroken) + { + socket.close(); + } + else + { + socket.shutdownInput(); + } } - else + catch(SocketException se) { - socket.shutdownInput(); + if(!socket.isClosed() && !socket.isInputShutdown()) + { + throw se; + } } if (block && Thread.currentThread() != receiverThread) { @@ -105,6 +127,7 @@ final class IoReceiver implements Runnable { throw new TransportException(e); } + } } diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/io/IoSender.java b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoSender.java index 66b97e8225..427487c879 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/network/io/IoSender.java +++ b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoSender.java @@ -24,10 +24,14 @@ import java.io.IOException; import java.io.OutputStream; import java.net.Socket; import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; +import org.apache.qpid.common.Closeable; import org.apache.qpid.thread.Threading; import org.apache.qpid.transport.Sender; +import org.apache.qpid.transport.SenderClosedException; import org.apache.qpid.transport.SenderException; import org.apache.qpid.transport.TransportException; import org.apache.qpid.transport.util.Logger; @@ -43,7 +47,6 @@ public final class IoSender implements Runnable, Sender<ByteBuffer> // we can test other cases as well private final static int START = Integer.MAX_VALUE - 10; - private final IoContext ioCtx; private final long timeout; private final Socket socket; private final OutputStream out; @@ -56,14 +59,13 @@ public final class IoSender implements Runnable, Sender<ByteBuffer> private final Object notEmpty = new Object(); private final AtomicBoolean closed = new AtomicBoolean(false); private final Thread senderThread; - - private volatile Throwable exception = null; + private final List<Closeable> _listeners = new ArrayList<Closeable>(); + private volatile Throwable exception = null; - public IoSender(IoContext ioCtx, int bufferSize, long timeout) + public IoSender(Socket socket, int bufferSize, long timeout) { - this.ioCtx = ioCtx; - this.socket = ioCtx.getSocket(); + this.socket = socket; this.buffer = new byte[pof2(bufferSize)]; // buffer size must be a power of 2 this.timeout = timeout; @@ -78,15 +80,20 @@ public final class IoSender implements Runnable, Sender<ByteBuffer> try { - senderThread = Threading.getThreadFactory().createThread(this); + //Create but deliberately don't start the thread. + senderThread = Threading.getThreadFactory().createThread(this); } catch(Exception e) { throw new Error("Error creating IOSender thread",e); } - + senderThread.setDaemon(true); senderThread.setName(String.format("IoSender - %s", socket.getRemoteSocketAddress())); + } + + public void initiate() + { senderThread.start(); } @@ -104,7 +111,11 @@ public final class IoSender implements Runnable, Sender<ByteBuffer> { if (closed.get()) { - throw new SenderException("sender is closed", exception); + throw new SenderClosedException("sender is closed", exception); + } + if(!senderThread.isAlive()) + { + throw new SenderException("sender thread not alive"); } final int size = buffer.length; @@ -137,7 +148,7 @@ public final class IoSender implements Runnable, Sender<ByteBuffer> if (closed.get()) { - throw new SenderException("sender is closed", exception); + throw new SenderClosedException("sender is closed", exception); } if (head - tail >= size) @@ -204,16 +215,20 @@ public final class IoSender implements Runnable, Sender<ByteBuffer> senderThread.join(timeout); if (senderThread.isAlive()) { + log.error("join timed out"); throw new SenderException("join timed out"); } } - ioCtx.getReceiver().close(false); } catch (InterruptedException e) { + log.error("interrupted whilst waiting for sender thread to stop"); throw new SenderException(e); } - + finally + { + closeListeners(); + } if (reportException && exception != null) { throw new SenderException(exception); @@ -221,9 +236,31 @@ public final class IoSender implements Runnable, Sender<ByteBuffer> } } + private void closeListeners() + { + Exception ex = null; + for(Closeable listener : _listeners) + { + try + { + listener.close(); + } + catch(Exception e) + { + log.error("Exception closing listener: " + e.getMessage()); + ex = e; + } + } + + if (ex != null) + { + throw new SenderException(ex.getMessage(), ex); + } + } + public void run() { - final int size = buffer.length; + final int size = buffer.length; while (true) { final int hd = head; @@ -304,4 +341,9 @@ public final class IoSender implements Runnable, Sender<ByteBuffer> throw new SenderException(e); } } + + public void registerCloseListener(Closeable listener) + { + _listeners.add(listener); + } } diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/io/IoTransport.java b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoTransport.java deleted file mode 100644 index bfdbb34978..0000000000 --- a/java/common/src/main/java/org/apache/qpid/transport/network/io/IoTransport.java +++ /dev/null @@ -1,231 +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.transport.network.io; - -import java.io.IOException; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.net.SocketException; -import java.nio.ByteBuffer; - -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLEngine; - -import org.apache.qpid.protocol.AMQVersionAwareProtocolSession; -import org.apache.qpid.ssl.SSLContextFactory; -import org.apache.qpid.transport.Binding; -import org.apache.qpid.transport.Connection; -import org.apache.qpid.transport.ConnectionDelegate; -import org.apache.qpid.transport.Receiver; -import org.apache.qpid.transport.Sender; -import org.apache.qpid.transport.TransportException; -import org.apache.qpid.transport.network.ConnectionBinding; -import org.apache.qpid.transport.network.security.ssl.SSLReceiver; -import org.apache.qpid.transport.network.security.ssl.SSLSender; -import org.apache.qpid.transport.util.Logger; - -/** - * This class provides a socket based transport using the java.io - * classes. - * - * The following params are configurable via JVM arguments - * TCP_NO_DELAY - amqj.tcpNoDelay - * SO_RCVBUF - amqj.receiveBufferSize - * SO_SNDBUF - amqj.sendBufferSize - */ -public final class IoTransport<E> implements IoContext -{ - - static - { - org.apache.mina.common.ByteBuffer.setAllocator - (new org.apache.mina.common.SimpleByteBufferAllocator()); - org.apache.mina.common.ByteBuffer.setUseDirectBuffers - (Boolean.getBoolean("amqj.enableDirectBuffers")); - } - - private static final Logger log = Logger.get(IoTransport.class); - - private static int DEFAULT_READ_WRITE_BUFFER_SIZE = 64 * 1024; - private static int readBufferSize = Integer.getInteger - ("amqj.receiveBufferSize", DEFAULT_READ_WRITE_BUFFER_SIZE); - private static int writeBufferSize = Integer.getInteger - ("amqj.sendBufferSize", DEFAULT_READ_WRITE_BUFFER_SIZE); - - private Socket socket; - private Sender<ByteBuffer> sender; - private E endpoint; - private IoReceiver receiver; - private long timeout = 60000; - - IoTransport(Socket socket, Binding<E,ByteBuffer> binding, boolean ssl) - { - this.socket = socket; - - if (ssl) - { - SSLEngine engine = null; - SSLContext sslCtx; - try - { - sslCtx = createSSLContext(); - } - catch (Exception e) - { - throw new TransportException("Error creating SSL Context", e); - } - - try - { - engine = sslCtx.createSSLEngine(); - engine.setUseClientMode(true); - } - catch(Exception e) - { - throw new TransportException("Error creating SSL Engine", e); - } - - this.sender = new SSLSender(engine,new IoSender(this, 2*writeBufferSize, timeout)); - this.endpoint = binding.endpoint(sender); - this.receiver = new IoReceiver(this, new SSLReceiver(engine,binding.receiver(endpoint),(SSLSender)sender), - 2*readBufferSize, timeout); - - log.info("SSL Sender and Receiver initiated"); - } - else - { - this.sender = new IoSender(this, 2*writeBufferSize, timeout); - this.endpoint = binding.endpoint(sender); - this.receiver = new IoReceiver(this, binding.receiver(endpoint), - 2*readBufferSize, timeout); - } - } - - public Sender<ByteBuffer> getSender() - { - return sender; - } - - public IoReceiver getReceiver() - { - return receiver; - } - - public Socket getSocket() - { - return socket; - } - - public static final <E> E connect(String host, int port, - Binding<E,ByteBuffer> binding, - boolean ssl) - { - Socket socket = createSocket(host, port); - IoTransport<E> transport = new IoTransport<E>(socket, binding,ssl); - return transport.endpoint; - } - - public static final Connection connect(String host, int port, - ConnectionDelegate delegate, - boolean ssl) - { - return connect(host, port, ConnectionBinding.get(delegate),ssl); - } - - public static void connect_0_9(AMQVersionAwareProtocolSession session, String host, int port, boolean ssl) - { - connect(host, port, new Binding_0_9(session),ssl); - } - - private static class Binding_0_9 - implements Binding<AMQVersionAwareProtocolSession,ByteBuffer> - { - - private AMQVersionAwareProtocolSession session; - - Binding_0_9(AMQVersionAwareProtocolSession session) - { - this.session = session; - } - - public AMQVersionAwareProtocolSession endpoint(Sender<ByteBuffer> sender) - { - session.setSender(sender); - return session; - } - - public Receiver<ByteBuffer> receiver(AMQVersionAwareProtocolSession ssn) - { - return new InputHandler_0_9(ssn); - } - - } - - private static Socket createSocket(String host, int port) - { - try - { - InetAddress address = InetAddress.getByName(host); - Socket socket = new Socket(); - socket.setReuseAddress(true); - socket.setTcpNoDelay(Boolean.getBoolean("amqj.tcpNoDelay")); - - log.debug("default-SO_RCVBUF : %s", socket.getReceiveBufferSize()); - log.debug("default-SO_SNDBUF : %s", socket.getSendBufferSize()); - - socket.setSendBufferSize(writeBufferSize); - socket.setReceiveBufferSize(readBufferSize); - - log.debug("new-SO_RCVBUF : %s", socket.getReceiveBufferSize()); - log.debug("new-SO_SNDBUF : %s", socket.getSendBufferSize()); - - socket.connect(new InetSocketAddress(address, port)); - return socket; - } - catch (SocketException e) - { - throw new TransportException("Error connecting to broker", e); - } - catch (IOException e) - { - throw new TransportException("Error connecting to broker", e); - } - } - - private SSLContext createSSLContext() throws Exception - { - String trustStorePath = System.getProperty("javax.net.ssl.trustStore"); - String trustStorePassword = System.getProperty("javax.net.ssl.trustStorePassword"); - String trustStoreCertType = System.getProperty("qpid.ssl.trustStoreCertType","SunX509"); - - String keyStorePath = System.getProperty("javax.net.ssl.keyStore",trustStorePath); - String keyStorePassword = System.getProperty("javax.net.ssl.keyStorePassword",trustStorePassword); - String keyStoreCertType = System.getProperty("qpid.ssl.keyStoreCertType","SunX509"); - - SSLContextFactory sslContextFactory = new SSLContextFactory(trustStorePath,trustStorePassword, - trustStoreCertType,keyStorePath, - keyStorePassword,keyStoreCertType); - - return sslContextFactory.buildServerContext(); - - } - -} diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java b/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java deleted file mode 100644 index 0f2c0d0226..0000000000 --- a/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java +++ /dev/null @@ -1,435 +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.transport.network.mina; - -import org.apache.mina.common.ConnectFuture; -import org.apache.mina.common.ExecutorThreadModel; -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; -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.slf4j.Logger; -import org.slf4j.LoggerFactory; - -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; - -import java.io.IOException; -import java.net.BindException; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.nio.ByteBuffer; - -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 IoConnector _socketConnector; - private IoAcceptor _acceptor; - private IoSession _ioSession; - private ProtocolEngineFactory _factory; - private boolean _protectIO; - private NetworkDriverConfiguration _config; - private Throwable _lastException; - private boolean _acceptingConnections = false; - - private WriteFuture _lastWriteFuture; - - private static final Logger _logger = LoggerFactory.getLogger(MINANetworkDriver.class); - - static - { - org.apache.mina.common.ByteBuffer.setUseDirectBuffers(Boolean.getBoolean("amqj.enableDirectBuffers")); - - //override the MINA defaults to prevent use of the PooledByteBufferAllocator - org.apache.mina.common.ByteBuffer.setAllocator(new SimpleByteBufferAllocator()); - } - - 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; - _ioSession.setAttachment(_protocolEngine); - } - - public MINANetworkDriver() - { - - } - - 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 - { - - _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(); - sconfig.setThreadModel(ExecutorThreadModel.getInstance("MINANetworkDriver(Acceptor)")); - SocketSessionConfig sc = (SocketSessionConfig) sconfig.getSessionConfig(); - - if (config != null) - { - sc.setReceiveBufferSize(config.getReceiveBufferSize()); - sc.setSendBufferSize(config.getSendBufferSize()); - sc.setTcpNoDelay(config.getTcpNoDelay()); - } - - 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 %1s:%2s", addr, port)); - } - } - } - else - { - try - { - _acceptor.bind(new InetSocketAddress(port), this, sconfig); - } - catch (IOException e) - { - throw new BindException(String.format("Could not bind to *:%1s", port)); - } - } - _acceptingConnections = true; - } - - public SocketAddress getRemoteAddress() - { - return _ioSession.getRemoteAddress(); - } - - public SocketAddress getLocalAddress() - { - return _ioSession.getLocalAddress(); - } - - - public void open(int port, InetAddress destination, ProtocolEngine engine, NetworkDriverConfiguration config, - SSLContextFactory sslFactory) throws OpenException - { - if (sslFactory != null) - { - _sslFactory = sslFactory; - } - - if (_useNIO) - { - _socketConnector = new MultiThreadSocketConnector(1, new QpidThreadExecutor()); - } - else - { - _socketConnector = new SocketConnector(1, new QpidThreadExecutor()); // non-blocking - // connector - } - - SocketConnectorConfig cfg = (SocketConnectorConfig) _socketConnector.getDefaultConfig(); - String s = ""; - StackTraceElement[] trace = Thread.currentThread().getStackTrace(); - for(StackTraceElement elt : trace) - { - if(elt.getClassName().contains("Test")) - { - s = elt.getClassName(); - break; - } - } - cfg.setThreadModel(ExecutorThreadModel.getInstance("MINANetworkDriver(Client)-"+s)); - - 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. - if (_socketConnector instanceof SocketConnector) - { - ((SocketConnector) _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(); - _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 (_lastWriteFuture != null) - { - _lastWriteFuture.join(); - } - if (_acceptor != null) - { - _acceptor.unbindAll(); - } - if (_ioSession != null) - { - _ioSession.close(); - } - } - - public void flush() - { - if (_lastWriteFuture != null) - { - _lastWriteFuture.join(); - } - } - - public void send(ByteBuffer msg) - { - org.apache.mina.common.ByteBuffer minaBuf = org.apache.mina.common.ByteBuffer.allocate(msg.capacity()); - minaBuf.put(msg); - minaBuf.flip(); - _lastWriteFuture = _ioSession.write(minaBuf); - } - - public void setIdleTimeout(int i) - { - // MINA doesn't support setting SO_TIMEOUT - } - - public void exceptionCaught(IoSession protocolSession, Throwable throwable) throws Exception - { - if (_protocolEngine != null) - { - _protocolEngine.exception(throwable); - } - else - { - _logger.error("Exception thrown and no ProtocolEngine to handle it", 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 - { - // 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"); - } - - 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); - } - } - - 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; - } - - public void setProtocolEngineFactory(ProtocolEngineFactory engineFactory, boolean acceptingConnections) - { - _factory = engineFactory; - _acceptingConnections = acceptingConnections; - } - - public void setProtocolEngine(ProtocolEngine protocolEngine) - { - _protocolEngine = protocolEngine; - if (_ioSession != null) - { - _ioSession.setAttachment(protocolEngine); - } - } - -} diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/mina/MinaHandler.java b/java/common/src/main/java/org/apache/qpid/transport/network/mina/MinaHandler.java deleted file mode 100644 index b89eed48b0..0000000000 --- a/java/common/src/main/java/org/apache/qpid/transport/network/mina/MinaHandler.java +++ /dev/null @@ -1,274 +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.transport.network.mina; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.SocketAddress; - -import org.apache.mina.common.*; - -import org.apache.mina.transport.socket.nio.SocketAcceptor; -import org.apache.mina.transport.socket.nio.SocketSessionConfig; -import org.apache.mina.transport.socket.nio.SocketConnector; -import org.apache.mina.filter.ReadThrottleFilterBuilder; -import org.apache.mina.filter.WriteBufferLimitFilterBuilder; -import org.apache.mina.filter.executor.ExecutorFilter; - -import org.apache.qpid.transport.Binding; -import org.apache.qpid.transport.Connection; -import org.apache.qpid.transport.ConnectionDelegate; -import org.apache.qpid.transport.Receiver; -import org.apache.qpid.transport.Sender; -import org.apache.qpid.transport.network.ConnectionBinding; - -import org.apache.qpid.transport.util.Logger; - -import org.apache.qpid.transport.network.Assembler; -import org.apache.qpid.transport.network.Disassembler; -import org.apache.qpid.transport.network.InputHandler; - -import static org.apache.qpid.transport.util.Functions.*; - -/** - * MinaHandler - * - * @author Rafael H. Schloming - */ -//RA making this public until we sort out the package issues -public class MinaHandler<E> implements IoHandler -{ - /** Default buffer size for pending messages reads */ - private static final String DEFAULT_READ_BUFFER_LIMIT = "262144"; - /** Default buffer size for pending messages writes */ - private static final String DEFAULT_WRITE_BUFFER_LIMIT = "262144"; - private static final int MAX_RCVBUF = 64*1024; - - private static final Logger log = Logger.get(MinaHandler.class); - - static - { - ByteBuffer.setAllocator(new SimpleByteBufferAllocator()); - ByteBuffer.setUseDirectBuffers(Boolean.getBoolean("amqj.enableDirectBuffers")); - } - - private final Binding<E,java.nio.ByteBuffer> binding; - - private MinaHandler(Binding<E,java.nio.ByteBuffer> binding) - { - this.binding = binding; - } - - public void messageReceived(IoSession ssn, Object obj) - { - Attachment<E> attachment = (Attachment<E>) ssn.getAttachment(); - ByteBuffer buf = (ByteBuffer) obj; - try - { - attachment.receiver.received(buf.buf()); - } - catch (Throwable t) - { - log.error(t, "exception handling buffer %s", str(buf.buf())); - throw new RuntimeException(t); - } - } - - public void messageSent(IoSession ssn, Object obj) - { - // do nothing - } - - public void exceptionCaught(IoSession ssn, Throwable e) - { - Attachment<E> attachment = (Attachment<E>) ssn.getAttachment(); - attachment.receiver.exception(e); - } - - /** - * 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 optional protectio - * - * @param session The MINA session. - * @throws Exception Any underlying exceptions are allowed to fall through to MINA. - */ - public void sessionCreated(IoSession session) throws Exception - { - log.debug("Protocol session created for session " + System.identityHashCode(session)); - - if (Boolean.getBoolean("protectio")) - { - 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("qpid.read.buffer.limit", DEFAULT_READ_BUFFER_LIMIT))); - readfilter.attach(chain); - - WriteBufferLimitFilterBuilder writefilter = new WriteBufferLimitFilterBuilder(); - writefilter.setMaximumConnectionBufferSize( - Integer.parseInt(System.getProperty("qpid.write.buffer.limit", DEFAULT_WRITE_BUFFER_LIMIT))); - writefilter.attach(chain); - session.getFilterChain().remove("tempExecutorFilterForFilterBuilder"); - - log.info("Using IO Read/Write Filter Protection"); - } - catch (Exception e) - { - log.error("Unable to attach IO Read/Write Filter Protection :" + e.getMessage()); - } - } - } - - public void sessionOpened(final IoSession ssn) - { - log.debug("opened: %s", this); - E endpoint = binding.endpoint(new MinaSender(ssn)); - Attachment<E> attachment = - new Attachment<E>(endpoint, binding.receiver(endpoint)); - - // We need to synchronize and notify here because the MINA - // connect future returns the session prior to the attachment - // being set. This is arguably a bug in MINA. - synchronized (ssn) - { - ssn.setAttachment(attachment); - ssn.notifyAll(); - } - } - - public void sessionClosed(IoSession ssn) - { - log.debug("closed: %s", ssn); - Attachment<E> attachment = (Attachment<E>) ssn.getAttachment(); - attachment.receiver.closed(); - ssn.setAttachment(null); - } - - public void sessionIdle(IoSession ssn, IdleStatus status) - { - // do nothing - } - - private static class Attachment<E> - { - - E endpoint; - Receiver<java.nio.ByteBuffer> receiver; - - Attachment(E endpoint, Receiver<java.nio.ByteBuffer> receiver) - { - this.endpoint = endpoint; - this.receiver = receiver; - } - } - - public static final void accept(String host, int port, - Binding<?,java.nio.ByteBuffer> binding) - throws IOException - { - accept(new InetSocketAddress(host, port), binding); - } - - public static final <E> void accept(SocketAddress address, - Binding<E,java.nio.ByteBuffer> binding) - throws IOException - { - IoAcceptor acceptor = new SocketAcceptor(); - acceptor.bind(address, new MinaHandler<E>(binding)); - } - - public static final <E> E connect(String host, int port, - Binding<E,java.nio.ByteBuffer> binding) - { - return connect(new InetSocketAddress(host, port), binding); - } - - public static final <E> E connect(SocketAddress address, - Binding<E,java.nio.ByteBuffer> binding) - { - MinaHandler<E> handler = new MinaHandler<E>(binding); - SocketConnector connector = new SocketConnector(); - IoServiceConfig acceptorConfig = connector.getDefaultConfig(); - acceptorConfig.setThreadModel(ThreadModel.MANUAL); - SocketSessionConfig scfg = (SocketSessionConfig) acceptorConfig.getSessionConfig(); - scfg.setTcpNoDelay(Boolean.getBoolean("amqj.tcpNoDelay")); - Integer sendBufferSize = Integer.getInteger("amqj.sendBufferSize"); - if (sendBufferSize != null && sendBufferSize > 0) - { - scfg.setSendBufferSize(sendBufferSize); - } - Integer receiveBufferSize = Integer.getInteger("amqj.receiveBufferSize"); - if (receiveBufferSize != null && receiveBufferSize > 0) - { - scfg.setReceiveBufferSize(receiveBufferSize); - } - else if (scfg.getReceiveBufferSize() > MAX_RCVBUF) - { - scfg.setReceiveBufferSize(MAX_RCVBUF); - } - connector.setWorkerTimeout(0); - ConnectFuture cf = connector.connect(address, handler); - cf.join(); - IoSession ssn = cf.getSession(); - - // We need to synchronize and wait here because the MINA - // connect future returns the session prior to the attachment - // being set. This is arguably a bug in MINA. - synchronized (ssn) - { - while (ssn.getAttachment() == null) - { - try - { - ssn.wait(); - } - catch (InterruptedException e) - { - throw new RuntimeException(e); - } - } - } - - Attachment<E> attachment = (Attachment<E>) ssn.getAttachment(); - return attachment.endpoint; - } - - public static final void accept(String host, int port, - ConnectionDelegate delegate) - throws IOException - { - accept(host, port, ConnectionBinding.get(delegate)); - } - - public static final Connection connect(String host, int port, - ConnectionDelegate delegate) - { - return connect(host, port, ConnectionBinding.get(delegate)); - } - -} diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/mina/MinaSender.java b/java/common/src/main/java/org/apache/qpid/transport/network/mina/MinaSender.java deleted file mode 100644 index 22b9c5e784..0000000000 --- a/java/common/src/main/java/org/apache/qpid/transport/network/mina/MinaSender.java +++ /dev/null @@ -1,90 +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.transport.network.mina; - -import org.apache.mina.common.ByteBuffer; -import org.apache.mina.common.CloseFuture; -import org.apache.mina.common.IoSession; -import org.apache.mina.common.WriteFuture; -import org.apache.qpid.transport.Sender; -import org.apache.qpid.transport.TransportException; - - -/** - * MinaSender - */ - -public class MinaSender implements Sender<java.nio.ByteBuffer> -{ - private static final int TIMEOUT = 2 * 60 * 1000; - - private final IoSession session; - private WriteFuture lastWrite = null; - - public MinaSender(IoSession session) - { - this.session = session; - } - - public void send(java.nio.ByteBuffer buf) - { - if (session.isClosing()) - { - throw new TransportException("attempted to write to a closed socket"); - } - - synchronized (this) - { - lastWrite = session.write(ByteBuffer.wrap(buf)); - } - } - - public void flush() - { - // pass - } - - public synchronized void close() - { - // MINA will sometimes throw away in-progress writes when you - // ask it to close - synchronized (this) - { - if (lastWrite != null) - { - lastWrite.join(); - } - } - CloseFuture closed = session.close(); - closed.join(); - } - - public void setIdleTimeout(int i) - { - //noop - } - - public long getIdleTimeout() - { - return 0; - } - -} diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/nio/NioHandler.java b/java/common/src/main/java/org/apache/qpid/transport/network/nio/NioHandler.java deleted file mode 100644 index 84e66c25bd..0000000000 --- a/java/common/src/main/java/org/apache/qpid/transport/network/nio/NioHandler.java +++ /dev/null @@ -1,135 +0,0 @@ -package org.apache.qpid.transport.network.nio; -/* - * - * 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.io.IOException; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.net.SocketException; -import java.nio.ByteBuffer; -import java.nio.channels.SocketChannel; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import org.apache.qpid.transport.Connection; -import org.apache.qpid.transport.ConnectionDelegate; -import org.apache.qpid.transport.Receiver; -import org.apache.qpid.transport.network.Assembler; -import org.apache.qpid.transport.network.Disassembler; -import org.apache.qpid.transport.network.InputHandler; - -public class NioHandler implements Runnable -{ - private Receiver<ByteBuffer> _receiver; - private SocketChannel _ch; - private ByteBuffer _readBuf; - private static Map<Long,NioSender> _handlers = new ConcurrentHashMap<Long,NioSender>(); - - private NioHandler(){} - - public static final Connection connect(String host, int port, - ConnectionDelegate delegate) - { - NioHandler handler = new NioHandler(); - return handler.connectInternal(host,port,delegate); - } - - private Connection connectInternal(String host, int port, - ConnectionDelegate delegate) - { - try - { - SocketAddress address = new InetSocketAddress(host,port); - _ch = SocketChannel.open(); - _ch.socket().setReuseAddress(true); - _ch.configureBlocking(true); - _ch.socket().setTcpNoDelay(true); - if (address != null) - { - _ch.socket().connect(address); - } - while (_ch.isConnectionPending()) - { - - } - - } - catch (SocketException e) - { - - e.printStackTrace(); - } - catch (IOException e) - { - e.printStackTrace(); - } - - NioSender sender = new NioSender(_ch); - Connection con = new Connection(); - con.setSender(new Disassembler(sender, 64*1024 - 1)); - con.setConnectionDelegate(delegate); - - _handlers.put(con.getConnectionId(),sender); - - _receiver = new InputHandler(new Assembler(con), InputHandler.State.FRAME_HDR); - - Thread t = new Thread(this); - t.start(); - - return con; - } - - public void run() - { - _readBuf = ByteBuffer.allocate(512); - long read = 0; - while(_ch.isConnected() && _ch.isOpen()) - { - try - { - read = _ch.read(_readBuf); - if (read > 0) - { - _readBuf.flip(); - ByteBuffer b = ByteBuffer.allocate(_readBuf.remaining()); - b.put(_readBuf); - b.flip(); - _readBuf.clear(); - _receiver.received(b); - } - } - catch(Exception e) - { - e.printStackTrace(); - } - } - - //throw new EOFException("The underlying socket/channel has closed"); - } - - public static void startBatchingFrames(int connectionId) - { - NioSender sender = _handlers.get(connectionId); - sender.setStartBatching(); - } - - -} diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/nio/NioSender.java b/java/common/src/main/java/org/apache/qpid/transport/network/nio/NioSender.java deleted file mode 100644 index 2fa875f279..0000000000 --- a/java/common/src/main/java/org/apache/qpid/transport/network/nio/NioSender.java +++ /dev/null @@ -1,126 +0,0 @@ -package org.apache.qpid.transport.network.nio; -/* - * - * 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.nio.ByteBuffer; -import java.nio.channels.SocketChannel; - -import org.apache.qpid.transport.Sender; - -public class NioSender implements Sender<java.nio.ByteBuffer> -{ - private final Object lock = new Object(); - private SocketChannel _ch; - private boolean _batch = false; - private ByteBuffer _batcher; - - public NioSender(SocketChannel ch) - { - this._ch = ch; - } - - public void send(java.nio.ByteBuffer buf) - { - if (_batch) - { - //System.out.println(_batcher.position() + " , " + buf.remaining() + " , " + buf.position() + ","+_batcher.capacity()); - if (_batcher.position() + buf.remaining() >= _batcher.capacity()) - { - _batcher.flip(); - write(_batcher); - _batcher.clear(); - if (buf.remaining() > _batcher.capacity()) - { - write(buf); - } - else - { - _batcher.put(buf); - } - } - else - { - _batcher.put(buf); - } - } - else - { - write(buf); - } - } - - public void flush() - { - // pass - } - - private void write(java.nio.ByteBuffer buf) - { - synchronized (lock) - { - if( _ch.isConnected() && _ch.isOpen()) - { - try - { - _ch.write(buf); - } - catch(Exception e) - { - e.fillInStackTrace(); - } - } - else - { - throw new RuntimeException("Trying to write on a closed socket"); - } - - } - } - - public void setStartBatching() - { - _batch = true; - _batcher = ByteBuffer.allocate(1024); - } - - public void close() - { - // MINA will sometimes throw away in-progress writes when you - // ask it to close - synchronized (lock) - { - try - { - _ch.close(); - } - catch(Exception e) - { - e.printStackTrace(); - } - } - } - - public void setIdleTimeout(int i) - { - //noop - } -} diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/security/SSLStatus.java b/java/common/src/main/java/org/apache/qpid/transport/network/security/SSLStatus.java new file mode 100644 index 0000000000..9db7dd557a --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/network/security/SSLStatus.java @@ -0,0 +1,49 @@ +/* + * 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.security; + +import java.util.concurrent.atomic.AtomicBoolean; + +public class SSLStatus +{ + private final Object _sslLock = new Object(); + private final AtomicBoolean _sslErrorFlag = new AtomicBoolean(false); + + /** + * Lock used to coordinate the SSL sender with the SSL receiver. + * + * @return lock + */ + public Object getSslLock() + { + return _sslLock; + } + + public boolean getSslErrorFlag() + { + return _sslErrorFlag.get(); + } + + public void setSslErrorFlag() + { + _sslErrorFlag.set(true); + } +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/security/SecurityLayer.java b/java/common/src/main/java/org/apache/qpid/transport/network/security/SecurityLayer.java index 3f0966903d..9fd65c6e51 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/network/security/SecurityLayer.java +++ b/java/common/src/main/java/org/apache/qpid/transport/network/security/SecurityLayer.java @@ -25,8 +25,8 @@ import java.nio.ByteBuffer; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; +import org.apache.qpid.ssl.SSLContextFactory; import org.apache.qpid.transport.Connection; -import org.apache.qpid.transport.ConnectionListener; import org.apache.qpid.transport.ConnectionSettings; import org.apache.qpid.transport.Receiver; import org.apache.qpid.transport.Sender; @@ -37,149 +37,12 @@ import org.apache.qpid.transport.network.security.ssl.SSLReceiver; import org.apache.qpid.transport.network.security.ssl.SSLSender; import org.apache.qpid.transport.network.security.ssl.SSLUtil; -public class SecurityLayer +public interface SecurityLayer { - ConnectionSettings settings; - Connection con; - SSLSecurityLayer sslLayer; - SASLSecurityLayer saslLayer; - - public void init(Connection con) throws TransportException - { - this.con = con; - this.settings = con.getConnectionSettings(); - if (settings.isUseSSL()) - { - sslLayer = new SSLSecurityLayer(); - } - if (settings.isUseSASLEncryption()) - { - saslLayer = new SASLSecurityLayer(); - } - - } - - public Sender<ByteBuffer> sender(Sender<ByteBuffer> delegate) - { - Sender<ByteBuffer> sender = delegate; - - if (settings.isUseSSL()) - { - sender = sslLayer.sender(sender); - } - - if (settings.isUseSASLEncryption()) - { - sender = saslLayer.sender(sender); - } - - return sender; - } - - public Receiver<ByteBuffer> receiver(Receiver<ByteBuffer> delegate) - { - Receiver<ByteBuffer> receiver = delegate; - - if (settings.isUseSSL()) - { - receiver = sslLayer.receiver(receiver); - } - - if (settings.isUseSASLEncryption()) - { - receiver = saslLayer.receiver(receiver); - } - - return receiver; - } - - public String getUserID() - { - if (settings.isUseSSL()) - { - return sslLayer.getUserID(); - } - else - { - return null; - } - } - - class SSLSecurityLayer - { - SSLEngine engine; - SSLSender sender; - - public SSLSecurityLayer() - { - SSLContext sslCtx; - try - { - sslCtx = SSLUtil.createSSLContext(settings); - } - catch (Exception e) - { - throw new TransportException("Error creating SSL Context", e); - } - - try - { - engine = sslCtx.createSSLEngine(); - engine.setUseClientMode(true); - } - catch(Exception e) - { - throw new TransportException("Error creating SSL Engine", e); - } - } - - public SSLSender sender(Sender<ByteBuffer> delegate) - { - sender = new SSLSender(engine,delegate); - sender.setConnectionSettings(settings); - return sender; - } - - public SSLReceiver receiver(Receiver<ByteBuffer> delegate) - { - if (sender == null) - { - throw new - IllegalStateException("SecurityLayer.sender method should be " + - "invoked before SecurityLayer.receiver"); - } - - SSLReceiver receiver = new SSLReceiver(engine,delegate,sender); - receiver.setConnectionSettings(settings); - return receiver; - } - - public String getUserID() - { - return SSLUtil.retriveIdentity(engine); - } - - } - - class SASLSecurityLayer - { - public SASLSecurityLayer() - { - } - - public SASLSender sender(Sender<ByteBuffer> delegate) - { - SASLSender sender = new SASLSender(delegate); - con.addConnectionListener((ConnectionListener)sender); - return sender; - } - - public SASLReceiver receiver(Receiver<ByteBuffer> delegate) - { - SASLReceiver receiver = new SASLReceiver(delegate); - con.addConnectionListener((ConnectionListener)receiver); - return receiver; - } - - } + + public Sender<ByteBuffer> sender(Sender<ByteBuffer> delegate); + public Receiver<ByteBuffer> receiver(Receiver<ByteBuffer> delegate); + public String getUserID(); + } + diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/security/SecurityLayerFactory.java b/java/common/src/main/java/org/apache/qpid/transport/network/security/SecurityLayerFactory.java new file mode 100644 index 0000000000..17f89c34ef --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/network/security/SecurityLayerFactory.java @@ -0,0 +1,161 @@ +package org.apache.qpid.transport.network.security; + +import org.apache.qpid.ssl.SSLContextFactory; +import org.apache.qpid.transport.*; +import org.apache.qpid.transport.network.security.sasl.SASLReceiver; +import org.apache.qpid.transport.network.security.sasl.SASLSender; +import org.apache.qpid.transport.network.security.ssl.SSLReceiver; +import org.apache.qpid.transport.network.security.ssl.SSLSender; +import org.apache.qpid.transport.network.security.ssl.SSLUtil; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLEngine; +import java.nio.ByteBuffer; + +public class SecurityLayerFactory +{ + public static SecurityLayer newInstance(ConnectionSettings settings) + { + + SecurityLayer layer = NullSecurityLayer.getInstance(); + + if (settings.isUseSSL()) + { + layer = new SSLSecurityLayer(settings, layer); + } + if (settings.isUseSASLEncryption()) + { + layer = new SASLSecurityLayer(layer); + } + + return layer; + + } + + static class SSLSecurityLayer implements SecurityLayer + { + + private final SSLEngine _engine; + private final SSLStatus _sslStatus = new SSLStatus(); + private String _hostname; + private SecurityLayer _layer; + + + public SSLSecurityLayer(ConnectionSettings settings, SecurityLayer layer) + { + + SSLContext sslCtx; + _layer = layer; + try + { + sslCtx = SSLContextFactory + .buildClientContext(settings.getTrustStorePath(), + settings.getTrustStorePassword(), + settings.getTrustStoreCertType(), + settings.getKeyStorePath(), + settings.getKeyStorePassword(), + settings.getKeyStoreCertType(), + settings.getCertAlias()); + } + catch (Exception e) + { + throw new TransportException("Error creating SSL Context", e); + } + + if(settings.isVerifyHostname()) + { + _hostname = settings.getHost(); + } + + try + { + _engine = sslCtx.createSSLEngine(); + _engine.setUseClientMode(true); + } + catch(Exception e) + { + throw new TransportException("Error creating SSL Engine", e); + } + + } + + public Sender<ByteBuffer> sender(Sender<ByteBuffer> delegate) + { + SSLSender sender = new SSLSender(_engine, _layer.sender(delegate), _sslStatus); + sender.setHostname(_hostname); + return sender; + } + + public Receiver<ByteBuffer> receiver(Receiver<ByteBuffer> delegate) + { + SSLReceiver receiver = new SSLReceiver(_engine, _layer.receiver(delegate), _sslStatus); + receiver.setHostname(_hostname); + return receiver; + } + + public String getUserID() + { + return SSLUtil.retriveIdentity(_engine); + } + } + + + static class SASLSecurityLayer implements SecurityLayer + { + + private SecurityLayer _layer; + + SASLSecurityLayer(SecurityLayer layer) + { + _layer = layer; + } + + public SASLSender sender(Sender<ByteBuffer> delegate) + { + SASLSender sender = new SASLSender(_layer.sender(delegate)); + return sender; + } + + public SASLReceiver receiver(Receiver<ByteBuffer> delegate) + { + SASLReceiver receiver = new SASLReceiver(_layer.receiver(delegate)); + return receiver; + } + + public String getUserID() + { + return _layer.getUserID(); + } + } + + + static class NullSecurityLayer implements SecurityLayer + { + + private static final NullSecurityLayer INSTANCE = new NullSecurityLayer(); + + private NullSecurityLayer() + { + } + + public Sender<ByteBuffer> sender(Sender<ByteBuffer> delegate) + { + return delegate; + } + + public Receiver<ByteBuffer> receiver(Receiver<ByteBuffer> delegate) + { + return delegate; + } + + public String getUserID() + { + return null; + } + + public static NullSecurityLayer getInstance() + { + return INSTANCE; + } + } +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/security/sasl/SASLSender.java b/java/common/src/main/java/org/apache/qpid/transport/network/security/sasl/SASLSender.java index 27255f79f6..2d9e4e9a7e 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/network/security/sasl/SASLSender.java +++ b/java/common/src/main/java/org/apache/qpid/transport/network/security/sasl/SASLSender.java @@ -43,8 +43,7 @@ public class SASLSender extends SASLEncryptor implements Sender<ByteBuffer> { this.delegate = delegate; log.debug("SASL Sender enabled"); } - - @Override + public void close() { @@ -65,13 +64,11 @@ public class SASLSender extends SASLEncryptor implements Sender<ByteBuffer> { } } - @Override public void flush() { delegate.flush(); } - @Override public void send(ByteBuffer buf) { if (closed.get()) @@ -108,7 +105,6 @@ public class SASLSender extends SASLEncryptor implements Sender<ByteBuffer> { } } - @Override public void setIdleTimeout(int i) { delegate.setIdleTimeout(i); diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/QpidClientX509KeyManager.java b/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/QpidClientX509KeyManager.java index 14f28f8828..4391e8adfc 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/QpidClientX509KeyManager.java +++ b/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/QpidClientX509KeyManager.java @@ -20,7 +20,9 @@ */ package org.apache.qpid.transport.network.security.ssl; +import java.io.IOException; import java.net.Socket; +import java.security.GeneralSecurityException; import java.security.KeyStore; import java.security.Principal; import java.security.PrivateKey; @@ -40,7 +42,7 @@ public class QpidClientX509KeyManager extends X509ExtendedKeyManager String alias; public QpidClientX509KeyManager(String alias, String keyStorePath, - String keyStorePassword,String keyStoreCertType) throws Exception + String keyStorePassword,String keyStoreCertType) throws GeneralSecurityException, IOException { this.alias = alias; KeyStore ks = SSLUtil.getInitializedKeyStore(keyStorePath,keyStorePassword); @@ -48,51 +50,45 @@ public class QpidClientX509KeyManager extends X509ExtendedKeyManager kmf.init(ks, keyStorePassword.toCharArray()); this.delegate = (X509ExtendedKeyManager)kmf.getKeyManagers()[0]; } - - @Override + public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) { log.debug("chooseClientAlias:Returning alias " + alias); return alias; } - @Override public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) { return delegate.chooseServerAlias(keyType, issuers, socket); } - @Override public X509Certificate[] getCertificateChain(String alias) { return delegate.getCertificateChain(alias); } - @Override public String[] getClientAliases(String keyType, Principal[] issuers) { log.debug("getClientAliases:Returning alias " + alias); return new String[]{alias}; } - @Override public PrivateKey getPrivateKey(String alias) { return delegate.getPrivateKey(alias); } - @Override public String[] getServerAliases(String keyType, Principal[] issuers) { return delegate.getServerAliases(keyType, issuers); } - + public String chooseEngineClientAlias(String[] keyType, Principal[] issuers, SSLEngine engine) { log.debug("chooseEngineClientAlias:Returning alias " + alias); return alias; } - + public String chooseEngineServerAlias(String keyType, Principal[] issuers, SSLEngine engine) { return delegate.chooseEngineServerAlias(keyType, issuers, engine); diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLReceiver.java b/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLReceiver.java index e227a51729..8ad40bbfd3 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLReceiver.java +++ b/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLReceiver.java @@ -24,43 +24,43 @@ import java.nio.ByteBuffer; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLEngineResult; -import javax.net.ssl.SSLException; import javax.net.ssl.SSLEngineResult.HandshakeStatus; import javax.net.ssl.SSLEngineResult.Status; +import javax.net.ssl.SSLException; import org.apache.qpid.transport.ConnectionSettings; import org.apache.qpid.transport.Receiver; import org.apache.qpid.transport.TransportException; +import org.apache.qpid.transport.network.security.SSLStatus; import org.apache.qpid.transport.util.Logger; public class SSLReceiver implements Receiver<ByteBuffer> { - private Receiver<ByteBuffer> delegate; - private SSLEngine engine; - private SSLSender sender; - private int sslBufSize; + private static final Logger log = Logger.get(SSLReceiver.class); + + private final Receiver<ByteBuffer> delegate; + private final SSLEngine engine; + private final int sslBufSize; + private final ByteBuffer localBuffer; + private final SSLStatus _sslStatus; private ByteBuffer appData; - private ByteBuffer localBuffer; private boolean dataCached = false; - private final Object notificationToken; - private ConnectionSettings settings; - - private static final Logger log = Logger.get(SSLReceiver.class); - public SSLReceiver(SSLEngine engine, Receiver<ByteBuffer> delegate,SSLSender sender) + private String _hostname; + + public SSLReceiver(final SSLEngine engine, final Receiver<ByteBuffer> delegate, final SSLStatus sslStatus) { this.engine = engine; this.delegate = delegate; - this.sender = sender; this.sslBufSize = engine.getSession().getApplicationBufferSize(); appData = ByteBuffer.allocate(sslBufSize); localBuffer = ByteBuffer.allocate(sslBufSize); - notificationToken = sender.getNotificationToken(); + _sslStatus = sslStatus; } - public void setConnectionSettings(ConnectionSettings settings) + public void setHostname(String hostname) { - this.settings = settings; + _hostname = hostname; } public void closed() @@ -102,9 +102,9 @@ public class SSLReceiver implements Receiver<ByteBuffer> try { SSLEngineResult result = engine.unwrap(netData, appData); - synchronized (notificationToken) + synchronized (_sslStatus.getSslLock()) { - notificationToken.notifyAll(); + _sslStatus.getSslLock().notifyAll(); } int read = result.bytesProduced(); @@ -129,9 +129,9 @@ public class SSLReceiver implements Receiver<ByteBuffer> switch(status) { case CLOSED: - synchronized(notificationToken) + synchronized(_sslStatus.getSslLock()) { - notificationToken.notifyAll(); + _sslStatus.getSslLock().notifyAll(); } return; @@ -163,20 +163,20 @@ public class SSLReceiver implements Receiver<ByteBuffer> break; case NEED_TASK: - sender.doTasks(); + doTasks(); handshakeStatus = engine.getHandshakeStatus(); case FINISHED: - if (this.settings != null && this.settings.isVerifyHostname() ) + if (_hostname != null) { - SSLUtil.verifyHostname(engine, this.settings.getHost()); + SSLUtil.verifyHostname(engine, _hostname); } case NEED_WRAP: case NOT_HANDSHAKING: - synchronized(notificationToken) + synchronized(_sslStatus.getSslLock()) { - notificationToken.notifyAll(); + _sslStatus.getSslLock().notifyAll(); } break; @@ -189,14 +189,23 @@ public class SSLReceiver implements Receiver<ByteBuffer> catch(SSLException e) { log.error(e, "Error caught in SSLReceiver"); - sender.setErrorFlag(); - synchronized(notificationToken) + _sslStatus.setSslErrorFlag(); + synchronized(_sslStatus.getSslLock()) { - notificationToken.notifyAll(); + _sslStatus.getSslLock().notifyAll(); } exception(new TransportException("Error in SSLReceiver",e)); } } } + + private void doTasks() + { + Runnable runnable; + while ((runnable = engine.getDelegatedTask()) != null) { + runnable.run(); + } + } + } diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLSender.java b/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLSender.java index cd47a11825..6f5aa6d86e 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLSender.java +++ b/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLSender.java @@ -31,35 +31,38 @@ import javax.net.ssl.SSLEngineResult.Status; import org.apache.qpid.transport.ConnectionSettings; import org.apache.qpid.transport.Sender; import org.apache.qpid.transport.SenderException; +import org.apache.qpid.transport.network.security.SSLStatus; import org.apache.qpid.transport.util.Logger; public class SSLSender implements Sender<ByteBuffer> { - private Sender<ByteBuffer> delegate; - private SSLEngine engine; - private int sslBufSize; - private ByteBuffer netData; - private long timeout = 30000; - private ConnectionSettings settings; - - private final Object engineState = new Object(); + private static final Logger log = Logger.get(SSLSender.class); + + private final Sender<ByteBuffer> delegate; + private final SSLEngine engine; + private final int sslBufSize; + private final ByteBuffer netData; + private final long timeout; + private final SSLStatus _sslStatus; + + private String _hostname; + private final AtomicBoolean closed = new AtomicBoolean(false); - private final AtomicBoolean error = new AtomicBoolean(false); - private static final Logger log = Logger.get(SSLSender.class); - public SSLSender(SSLEngine engine, Sender<ByteBuffer> delegate) + public SSLSender(SSLEngine engine, Sender<ByteBuffer> delegate, SSLStatus sslStatus) { this.engine = engine; this.delegate = delegate; sslBufSize = engine.getSession().getPacketBufferSize(); netData = ByteBuffer.allocate(sslBufSize); timeout = Long.getLong("qpid.ssl_timeout", 60000); + _sslStatus = sslStatus; } - public void setConnectionSettings(ConnectionSettings settings) + public void setHostname(String hostname) { - this.settings = settings; + _hostname = hostname; } public void close() @@ -83,13 +86,13 @@ public class SSLSender implements Sender<ByteBuffer> } - synchronized(engineState) + synchronized(_sslStatus.getSslLock()) { while (!engine.isOutboundDone()) { try { - engineState.wait(); + _sslStatus.getSslLock().wait(); } catch(InterruptedException e) { @@ -148,7 +151,7 @@ public class SSLSender implements Sender<ByteBuffer> HandshakeStatus handshakeStatus; Status status; - while(appData.hasRemaining() && !error.get()) + while(appData.hasRemaining() && !_sslStatus.getSslErrorFlag()) { int read = 0; try @@ -160,6 +163,7 @@ public class SSLSender implements Sender<ByteBuffer> } catch(SSLException e) { + // Should this set _sslError?? throw new SenderException("SSL, Error occurred while encrypting data",e); } @@ -207,7 +211,7 @@ public class SSLSender implements Sender<ByteBuffer> case NEED_UNWRAP: flush(); - synchronized(engineState) + synchronized(_sslStatus.getSslLock()) { switch (engine.getHandshakeStatus()) { @@ -215,7 +219,7 @@ public class SSLSender implements Sender<ByteBuffer> long start = System.currentTimeMillis(); try { - engineState.wait(timeout); + _sslStatus.getSslLock().wait(timeout); } catch(InterruptedException e) { @@ -234,9 +238,9 @@ public class SSLSender implements Sender<ByteBuffer> break; case FINISHED: - if (this.settings != null && this.settings.isVerifyHostname() ) + if (_hostname != null) { - SSLUtil.verifyHostname(engine, this.settings.getHost()); + SSLUtil.verifyHostname(engine, _hostname); } case NOT_HANDSHAKING: @@ -249,7 +253,7 @@ public class SSLSender implements Sender<ByteBuffer> } } - public void doTasks() + private void doTasks() { Runnable runnable; while ((runnable = engine.getDelegatedTask()) != null) { @@ -257,16 +261,6 @@ public class SSLSender implements Sender<ByteBuffer> } } - public Object getNotificationToken() - { - return engineState; - } - - public void setErrorFlag() - { - error.set(true); - } - public void setIdleTimeout(int i) { delegate.setIdleTimeout(i); diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLUtil.java b/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLUtil.java index fd73915b65..6bb038a581 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLUtil.java +++ b/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLUtil.java @@ -125,38 +125,6 @@ public class SSLUtil return id.toString(); } - public static SSLContext createSSLContext(ConnectionSettings settings) throws Exception - { - SSLContextFactory sslContextFactory; - - if (settings.getCertAlias() == null) - { - sslContextFactory = - new SSLContextFactory(settings.getTrustStorePath(), - settings.getTrustStorePassword(), - settings.getTrustStoreCertType(), - settings.getKeyStorePath(), - settings.getKeyStorePassword(), - settings.getKeyStoreCertType()); - - } else - { - sslContextFactory = - new SSLContextFactory(settings.getTrustStorePath(), - settings.getTrustStorePassword(), - settings.getTrustStoreCertType(), - new QpidClientX509KeyManager(settings.getCertAlias(), - settings.getKeyStorePath(), - settings.getKeyStorePassword(), - settings.getKeyStoreCertType())); - - log.debug("Using custom key manager"); - } - - return sslContextFactory.buildServerContext(); - - } - public static KeyStore getInitializedKeyStore(String storePath, String storePassword) throws GeneralSecurityException, IOException { KeyStore ks = KeyStore.getInstance("JKS"); @@ -176,7 +144,10 @@ public class SSLUtil { throw new IOException("Unable to load keystore resource: " + storePath); } - ks.load(in, storePassword.toCharArray()); + + char[] storeCharPassword = storePassword == null ? null : storePassword.toCharArray(); + + ks.load(in, storeCharPassword); } finally { diff --git a/java/common/src/main/java/org/apache/qpid/url/URLHelper.java b/java/common/src/main/java/org/apache/qpid/url/URLHelper.java index 6f21c327e7..e261860bf3 100644 --- a/java/common/src/main/java/org/apache/qpid/url/URLHelper.java +++ b/java/common/src/main/java/org/apache/qpid/url/URLHelper.java @@ -31,9 +31,6 @@ public class URLHelper public static void parseOptions(Map<String, String> optionMap, String options) throws URLSyntaxException { - // options looks like this - // brokerlist='tcp://host:port?option='value',option='value';vm://:3/virtualpath?option='value'',failover='method?option='value',option='value'' - if ((options == null) || (options.indexOf('=') == -1)) { return; diff --git a/java/common/src/main/java/org/apache/qpid/util/FileUtils.java b/java/common/src/main/java/org/apache/qpid/util/FileUtils.java index 516204fbd3..ac8e3da3c2 100644 --- a/java/common/src/main/java/org/apache/qpid/util/FileUtils.java +++ b/java/common/src/main/java/org/apache/qpid/util/FileUtils.java @@ -143,8 +143,9 @@ public class FileUtils } /** - * Either opens the specified filename as an input stream, or uses the default resource loaded using the - * specified class loader, if opening the file fails or no file name is specified. + * Either opens the specified filename as an input stream or either the filesystem or classpath, + * or uses the default resource loaded using the specified class loader, if opening the file fails + * or no file name is specified. * * @param filename The name of the file to open. * @param defaultResource The name of the default resource on the classpath if the file cannot be opened. @@ -156,28 +157,28 @@ public class FileUtils { InputStream is = null; - // Flag to indicate whether the default resource should be used. By default this is true, so that the default - // is used when opening the file fails. - boolean useDefault = true; - // Try to open the file if one was specified. if (filename != null) { + // try on filesystem try { is = new BufferedInputStream(new FileInputStream(new File(filename))); - - // Clear the default flag because the file was succesfully opened. - useDefault = false; } catch (FileNotFoundException e) { - // Ignore this exception, the default will be used instead. + is = null; + } + + if (is == null) + { + // failed on filesystem, so try on classpath + is = cl.getResourceAsStream(filename); } } // Load the default resource if a file was not specified, or if opening the file failed. - if (useDefault) + if (is == null) { is = cl.getResourceAsStream(defaultResource); } @@ -339,7 +340,7 @@ public class FileUtils } //else we have a source directory - if (!dst.isDirectory() && !dst.mkdir()) + if (!dst.isDirectory() && !dst.mkdirs()) { throw new UnableToCopyException("Unable to create destination directory"); } diff --git a/java/common/src/test/java/org/apache/mina/SocketIOTest/IOWriterClient.java b/java/common/src/test/java/org/apache/mina/SocketIOTest/IOWriterClient.java deleted file mode 100644 index b93dc46741..0000000000 --- a/java/common/src/test/java/org/apache/mina/SocketIOTest/IOWriterClient.java +++ /dev/null @@ -1,396 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed 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.mina.SocketIOTest; - -import org.apache.mina.common.ByteBuffer; -import org.apache.mina.common.CloseFuture; -import org.apache.mina.common.ConnectFuture; -import org.apache.mina.common.IoConnector; -import org.apache.mina.common.IoFilterChain; -import org.apache.mina.common.IoHandlerAdapter; -import org.apache.mina.common.IoSession; -import org.apache.mina.common.SimpleByteBufferAllocator; -import org.apache.mina.filter.ReadThrottleFilterBuilder; -import org.apache.mina.filter.WriteBufferLimitFilterBuilder; -import org.apache.mina.transport.socket.nio.SocketSessionConfig; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.util.concurrent.CountDownLatch; - -public class IOWriterClient implements Runnable -{ - private static final Logger _logger = LoggerFactory.getLogger(IOWriterClient.class); - - public static int DEFAULT_TEST_SIZE = 2; - - private IoSession _session; - - private long _startTime; - - private long[] _chunkTimes; - - public int _chunkCount = 200000; - - private int _chunkSize = 1024; - - private CountDownLatch _notifier; - - private int _maximumWriteQueueLength; - - static public int _PORT = IOWriterServer._PORT; - - public void run() - { - _logger.info("Starting to send " + _chunkCount + " buffers of " + _chunkSize + "B"); - _startTime = System.currentTimeMillis(); - _notifier = new CountDownLatch(1); - - for (int i = 0; i < _chunkCount; i++) - { - ByteBuffer buf = ByteBuffer.allocate(_chunkSize, false); - byte check = (byte) (i % 128); - buf.put(check); - buf.fill((byte) 88, buf.remaining()); - buf.flip(); - - _session.write(buf); - } - - long _sentall = System.currentTimeMillis(); - long _receivedall = _sentall; - try - { - _logger.info("All buffers sent; waiting for receipt from server"); - _notifier.await(); - _receivedall = System.currentTimeMillis(); - } - catch (InterruptedException e) - { - //Ignore - } - _logger.info("Completed"); - _logger.info("Total time waiting for server after last write: " + (_receivedall - _sentall)); - - long totalTime = System.currentTimeMillis() - _startTime; - - _logger.info("Total time: " + totalTime); - _logger.info("MB per second: " + (int) ((1.0 * _chunkSize * _chunkCount) / totalTime)); - long lastChunkTime = _startTime; - double average = 0; - for (int i = 0; i < _chunkTimes.length; i++) - { - if (i == 0) - { - average = _chunkTimes[i] - _startTime; - } - else - { - long delta = _chunkTimes[i] - lastChunkTime; - if (delta != 0) - { - average = (average + delta) / 2; - } - } - lastChunkTime = _chunkTimes[i]; - } - _logger.info("Average chunk time: " + average + "ms"); - _logger.info("Maximum WriteRequestQueue size: " + _maximumWriteQueueLength); - - CloseFuture cf = _session.close(); - _logger.info("Closing session"); - cf.join(); - } - - private class WriterHandler extends IoHandlerAdapter - { - private int _chunksReceived = 0; - - private int _partialBytesRead = 0; - - private byte _partialCheckNumber; - - private int _totalBytesReceived = 0; - - private int _receivedCount = 0; - private int _sentCount = 0; - private static final String DEFAULT_READ_BUFFER = "262144"; - private static final String DEFAULT_WRITE_BUFFER = "262144"; - - public void sessionCreated(IoSession session) throws Exception - { - IoFilterChain chain = session.getFilterChain(); - - ReadThrottleFilterBuilder readfilter = new ReadThrottleFilterBuilder(); - readfilter.setMaximumConnectionBufferSize(Integer.parseInt(System.getProperty("qpid.read.buffer.limit", DEFAULT_READ_BUFFER))); - readfilter.attach(chain); - - WriteBufferLimitFilterBuilder writefilter = new WriteBufferLimitFilterBuilder(); - - writefilter.setMaximumConnectionBufferSize(Integer.parseInt(System.getProperty("qpid.write.buffer.limit", DEFAULT_WRITE_BUFFER))); - - writefilter.attach(chain); - } - - public void messageSent(IoSession session, Object message) throws Exception - { - _maximumWriteQueueLength = Math.max(session.getScheduledWriteRequests(), _maximumWriteQueueLength); - - if (_logger.isDebugEnabled()) - { - ++_sentCount; - if (_sentCount % 1000 == 0) - { - _logger.debug("Sent count " + _sentCount + ":WQueue" + session.getScheduledWriteRequests()); - - } - } - } - - public void messageReceived(IoSession session, Object message) throws Exception - { - if (_logger.isDebugEnabled()) - { - ++_receivedCount; - - if (_receivedCount % 1000 == 0) - { - _logger.debug("Receieved count " + _receivedCount); - } - } - - ByteBuffer result = (ByteBuffer) message; - _totalBytesReceived += result.remaining(); - int size = result.remaining(); - long now = System.currentTimeMillis(); - if (_partialBytesRead > 0) - { - int offset = _chunkSize - _partialBytesRead; - if (size >= offset) - { - _chunkTimes[_chunksReceived++] = now; - result.position(offset); - } - else - { - // have not read even one chunk, including the previous partial bytes - _partialBytesRead += size; - return; - } - } - - - int chunkCount = result.remaining() / _chunkSize; - - for (int i = 0; i < chunkCount; i++) - { - _chunkTimes[_chunksReceived++] = now; - byte check = result.get(); - _logger.debug("Check number " + check + " read"); - if (check != (byte) ((_chunksReceived - 1) % 128)) - { - _logger.error("Check number " + check + " read when expected " + (_chunksReceived % 128)); - } - _logger.debug("Chunk times recorded"); - - try - { - result.skip(_chunkSize - 1); - } - catch (IllegalArgumentException e) - { - _logger.error("Position was: " + result.position()); - _logger.error("Tried to skip to: " + (_chunkSize * i)); - _logger.error("limit was; " + result.limit()); - } - } - _logger.debug("Chunks received now " + _chunksReceived); - _logger.debug("Bytes received: " + _totalBytesReceived); - _partialBytesRead = result.remaining(); - - if (_partialBytesRead > 0) - { - _partialCheckNumber = result.get(); - } - - - if (_chunksReceived >= _chunkCount) - { - _notifier.countDown(); - } - - } - - public void exceptionCaught(IoSession session, Throwable cause) throws Exception - { - _logger.error("Error: " + cause, cause); - } - } - - public void startWriter() throws IOException, InterruptedException - { - - _maximumWriteQueueLength = 0; - - IoConnector ioConnector = null; - - if (Boolean.getBoolean("multinio")) - { - _logger.warn("Using MultiThread NIO"); - ioConnector = new org.apache.mina.transport.socket.nio.MultiThreadSocketConnector(); - } - else - { - _logger.warn("Using MINA NIO"); - ioConnector = new org.apache.mina.transport.socket.nio.SocketConnector(); - } - - SocketSessionConfig scfg = (SocketSessionConfig) ioConnector.getDefaultConfig().getSessionConfig(); - scfg.setTcpNoDelay(true); - scfg.setSendBufferSize(32768); - scfg.setReceiveBufferSize(32768); - - ByteBuffer.setAllocator(new SimpleByteBufferAllocator()); - - - final InetSocketAddress address = new InetSocketAddress("localhost", _PORT); - _logger.info("Attempting connection to " + address); - - //Old mina style -// ioConnector.setHandler(new WriterHandler()); -// ConnectFuture future = ioConnector.connect(address); - ConnectFuture future = ioConnector.connect(address, new WriterHandler()); - // wait for connection to complete - future.join(); - _logger.info("Connection completed"); - // we call getSession which throws an IOException if there has been an error connecting - _session = future.getSession(); - - _chunkTimes = new long[_chunkCount]; - Thread t = new Thread(this); - t.start(); - t.join(); - _logger.info("Test Complete"); - } - - - public void test1k() throws IOException, InterruptedException - { - _logger.info("Starting 1k test"); - _chunkSize = 1024; - startWriter(); - } - - - public void test2k() throws IOException, InterruptedException - { - _logger.info("Starting 2k test"); - _chunkSize = 2048; - startWriter(); - } - - - public void test4k() throws IOException, InterruptedException - { - _logger.info("Starting 4k test"); - _chunkSize = 4096; - startWriter(); - } - - - public void test8k() throws IOException, InterruptedException - { - _logger.info("Starting 8k test"); - _chunkSize = 8192; - startWriter(); - } - - - public void test16k() throws IOException, InterruptedException - { - _logger.info("Starting 16k test"); - _chunkSize = 16384; - startWriter(); - } - - - public void test32k() throws IOException, InterruptedException - { - _logger.info("Starting 32k test"); - _chunkSize = 32768; - startWriter(); - } - - - public static int getIntArg(String[] args, int index, int defaultValue) - { - if (args.length > index) - { - try - { - return Integer.parseInt(args[index]); - } - catch (NumberFormatException e) - { - //Do nothing - } - } - return defaultValue; - } - - public static void main(String[] args) throws IOException, InterruptedException - { - _PORT = getIntArg(args, 0, _PORT); - - int test = getIntArg(args, 1, DEFAULT_TEST_SIZE); - - IOWriterClient w = new IOWriterClient(); - w._chunkCount = getIntArg(args, 2, w._chunkCount); - switch (test) - { - case 0: - w.test1k(); - w.test2k(); - w.test4k(); - w.test8k(); - w.test16k(); - w.test32k(); - break; - case 1: - w.test1k(); - break; - case 2: - w.test2k(); - break; - case 4: - w.test4k(); - break; - case 8: - w.test8k(); - break; - case 16: - w.test16k(); - break; - case 32: - w.test32k(); - break; - } - } -} diff --git a/java/common/src/test/java/org/apache/mina/SocketIOTest/IOWriterServer.java b/java/common/src/test/java/org/apache/mina/SocketIOTest/IOWriterServer.java deleted file mode 100644 index 423e98c67b..0000000000 --- a/java/common/src/test/java/org/apache/mina/SocketIOTest/IOWriterServer.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed 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.mina.SocketIOTest; - -import org.apache.mina.common.ByteBuffer; -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.SimpleByteBufferAllocator; -import org.apache.mina.filter.ReadThrottleFilterBuilder; -import org.apache.mina.filter.WriteBufferLimitFilterBuilder; -import org.apache.mina.transport.socket.nio.SocketSessionConfig; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.net.InetSocketAddress; - -/** Tests MINA socket performance. This acceptor simply reads data from the network and writes it back again. */ -public class IOWriterServer -{ - private static final Logger _logger = LoggerFactory.getLogger(IOWriterServer.class); - - static public int _PORT = 9999; - - private static final String DEFAULT_READ_BUFFER = "262144"; - private static final String DEFAULT_WRITE_BUFFER = "262144"; - - - private static class TestHandler extends IoHandlerAdapter - { - private int _sentCount = 0; - - private int _bytesSent = 0; - - private int _receivedCount = 0; - - public void sessionCreated(IoSession ioSession) throws java.lang.Exception - { - IoFilterChain chain = ioSession.getFilterChain(); - - ReadThrottleFilterBuilder readfilter = new ReadThrottleFilterBuilder(); - readfilter.setMaximumConnectionBufferSize(Integer.parseInt(System.getProperty("qpid.read.buffer.limit", DEFAULT_READ_BUFFER))); - readfilter.attach(chain); - - WriteBufferLimitFilterBuilder writefilter = new WriteBufferLimitFilterBuilder(); - - writefilter.setMaximumConnectionBufferSize(Integer.parseInt(System.getProperty("qpid.write.buffer.limit", DEFAULT_WRITE_BUFFER))); - - writefilter.attach(chain); - - } - - public void messageReceived(IoSession session, Object message) throws Exception - { - ((ByteBuffer) message).acquire(); - session.write(message); - - if (_logger.isDebugEnabled()) - { - _bytesSent += ((ByteBuffer) message).remaining(); - - _sentCount++; - - if (_sentCount % 1000 == 0) - { - _logger.debug("Bytes sent: " + _bytesSent); - } - } - } - - public void messageSent(IoSession session, Object message) throws Exception - { - if (_logger.isDebugEnabled()) - { - ++_receivedCount; - - if (_receivedCount % 1000 == 0) - { - _logger.debug("Receieved count " + _receivedCount); - } - } - } - - public void exceptionCaught(IoSession session, Throwable cause) throws Exception - { - _logger.error("Error: " + cause, cause); - } - } - - public void startAcceptor() throws IOException - { - IoAcceptor acceptor; - if (Boolean.getBoolean("multinio")) - { - _logger.warn("Using MultiThread NIO"); - acceptor = new org.apache.mina.transport.socket.nio.MultiThreadSocketAcceptor(); - } - else - { - _logger.warn("Using MINA NIO"); - acceptor = new org.apache.mina.transport.socket.nio.SocketAcceptor(); - } - - - SocketSessionConfig sc = (SocketSessionConfig) acceptor.getDefaultConfig().getSessionConfig(); - sc.setTcpNoDelay(true); - sc.setSendBufferSize(32768); - sc.setReceiveBufferSize(32768); - - ByteBuffer.setAllocator(new SimpleByteBufferAllocator()); - - //The old mina style -// acceptor.setLocalAddress(new InetSocketAddress(_PORT)); -// acceptor.setHandler(new TestHandler()); -// acceptor.bind(); - acceptor.bind(new InetSocketAddress(_PORT), new TestHandler()); - - _logger.info("Bound on port " + _PORT + ":" + _logger.isDebugEnabled()); - _logger.debug("debug on"); - } - - public static void main(String[] args) throws IOException - { - - if (args.length > 0) - { - try - { - _PORT = Integer.parseInt(args[0]); - } - catch (NumberFormatException e) - { - //IGNORE so use default port 9999; - } - } - - IOWriterServer a = new IOWriterServer(); - a.startAcceptor(); - } -} diff --git a/java/common/src/test/java/org/apache/qpid/AMQExceptionTest.java b/java/common/src/test/java/org/apache/qpid/AMQExceptionTest.java index ef6cd41492..f65427e583 100644 --- a/java/common/src/test/java/org/apache/qpid/AMQExceptionTest.java +++ b/java/common/src/test/java/org/apache/qpid/AMQExceptionTest.java @@ -23,6 +23,7 @@ package org.apache.qpid; import junit.framework.TestCase; import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.framing.AMQFrameDecodingException; +import org.apache.qpid.framing.AMQShortString; /** * This test is to ensure that when an AMQException is rethrown that the specified exception is correctly wrapped up. @@ -91,6 +92,18 @@ public class AMQExceptionTest extends TestCase return amqe; } + public void testGetMessageAsString() + { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < 25; i++) + { + sb.append("message [" + i + "]"); + } + AMQException e = new AMQException(AMQConstant.INTERNAL_ERROR, sb.toString(), null); + AMQShortString message = e.getMessageAsShortString(); + assertEquals(sb.substring(0, AMQShortString.MAX_LENGTH - 3) + "...", message.toString()); + } + /** * Private class that extends AMQException but does not have a default exception. */ diff --git a/java/common/src/test/java/org/apache/qpid/codec/AMQDecoderTest.java b/java/common/src/test/java/org/apache/qpid/codec/AMQDecoderTest.java index 62e25e7d79..272eb75800 100644 --- a/java/common/src/test/java/org/apache/qpid/codec/AMQDecoderTest.java +++ b/java/common/src/test/java/org/apache/qpid/codec/AMQDecoderTest.java @@ -21,6 +21,9 @@ package org.apache.qpid.codec; */ +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; import java.nio.ByteBuffer; import java.util.ArrayList; @@ -46,9 +49,16 @@ public class AMQDecoderTest extends TestCase } - public void testSingleFrameDecode() throws AMQProtocolVersionException, AMQFrameDecodingException + private ByteBuffer getHeartbeatBodyBuffer() throws IOException { - ByteBuffer msg = HeartbeatBody.FRAME.toNioByteBuffer(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + HeartbeatBody.FRAME.writePayload(new DataOutputStream(baos)); + return ByteBuffer.wrap(baos.toByteArray()); + } + + public void testSingleFrameDecode() throws AMQProtocolVersionException, AMQFrameDecodingException, IOException + { + ByteBuffer msg = getHeartbeatBodyBuffer(); ArrayList<AMQDataBlock> frames = _decoder.decodeBuffer(msg); if (frames.get(0) instanceof AMQFrame) { @@ -60,9 +70,9 @@ public class AMQDecoderTest extends TestCase } } - public void testPartialFrameDecode() throws AMQProtocolVersionException, AMQFrameDecodingException + public void testPartialFrameDecode() throws AMQProtocolVersionException, AMQFrameDecodingException, IOException { - ByteBuffer msg = HeartbeatBody.FRAME.toNioByteBuffer(); + ByteBuffer msg = getHeartbeatBodyBuffer(); ByteBuffer msgA = msg.slice(); int msgbPos = msg.remaining() / 2; int msgaLimit = msg.remaining() - msgbPos; @@ -83,10 +93,10 @@ public class AMQDecoderTest extends TestCase } } - public void testMultipleFrameDecode() throws AMQProtocolVersionException, AMQFrameDecodingException + public void testMultipleFrameDecode() throws AMQProtocolVersionException, AMQFrameDecodingException, IOException { - ByteBuffer msgA = HeartbeatBody.FRAME.toNioByteBuffer(); - ByteBuffer msgB = HeartbeatBody.FRAME.toNioByteBuffer(); + ByteBuffer msgA = getHeartbeatBodyBuffer(); + ByteBuffer msgB = getHeartbeatBodyBuffer(); ByteBuffer msg = ByteBuffer.allocate(msgA.remaining() + msgB.remaining()); msg.put(msgA); msg.put(msgB); @@ -106,11 +116,11 @@ public class AMQDecoderTest extends TestCase } } - public void testMultiplePartialFrameDecode() throws AMQProtocolVersionException, AMQFrameDecodingException + public void testMultiplePartialFrameDecode() throws AMQProtocolVersionException, AMQFrameDecodingException, IOException { - ByteBuffer msgA = HeartbeatBody.FRAME.toNioByteBuffer(); - ByteBuffer msgB = HeartbeatBody.FRAME.toNioByteBuffer(); - ByteBuffer msgC = HeartbeatBody.FRAME.toNioByteBuffer(); + ByteBuffer msgA = getHeartbeatBodyBuffer(); + ByteBuffer msgB = getHeartbeatBodyBuffer(); + ByteBuffer msgC = getHeartbeatBodyBuffer(); ByteBuffer sliceA = ByteBuffer.allocate(msgA.remaining() + msgB.remaining() / 2); sliceA.put(msgA); diff --git a/java/common/src/test/java/org/apache/qpid/framing/AMQShortStringTest.java b/java/common/src/test/java/org/apache/qpid/framing/AMQShortStringTest.java index 92e7ce0a80..9a805d87b3 100644 --- a/java/common/src/test/java/org/apache/qpid/framing/AMQShortStringTest.java +++ b/java/common/src/test/java/org/apache/qpid/framing/AMQShortStringTest.java @@ -20,6 +20,10 @@ package org.apache.qpid.framing; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.List; + import junit.framework.TestCase; public class AMQShortStringTest extends TestCase { @@ -105,5 +109,215 @@ public class AMQShortStringTest extends TestCase assertFalse(new AMQShortString("A").equals(new AMQShortString("a"))); } + /** + * Test method for + * {@link org.apache.qpid.framing.AMQShortString#AMQShortString(byte[])}. + */ + public void testCreateAMQShortStringByteArray() + { + byte[] bytes = null; + try + { + bytes = "test".getBytes("UTF-8"); + } + catch (UnsupportedEncodingException e) + { + fail("UTF-8 encoding is not supported anymore by JVM:" + e.getMessage()); + } + AMQShortString string = new AMQShortString(bytes); + assertEquals("constructed amq short string length differs from expected", 4, string.length()); + assertTrue("constructed amq short string differs from expected", string.equals("test")); + } + + /** + * Test method for + * {@link org.apache.qpid.framing.AMQShortString#AMQShortString(java.lang.String)} + * <p> + * Tests short string construction from string with length less than 255. + */ + public void testCreateAMQShortStringString() + { + AMQShortString string = new AMQShortString("test"); + assertEquals("constructed amq short string length differs from expected", 4, string.length()); + assertTrue("constructed amq short string differs from expected", string.equals("test")); + } + + /** + * Test method for + * {@link org.apache.qpid.framing.AMQShortString#AMQShortString(char[])}. + * <p> + * Tests short string construction from char array with length less than 255. + */ + public void testCreateAMQShortStringCharArray() + { + char[] chars = "test".toCharArray(); + AMQShortString string = new AMQShortString(chars); + assertEquals("constructed amq short string length differs from expected", 4, string.length()); + assertTrue("constructed amq short string differs from expected", string.equals("test")); + } + + /** + * Test method for + * {@link org.apache.qpid.framing.AMQShortString#AMQShortString(java.lang.CharSequence)} + * <p> + * Tests short string construction from char sequence with length less than 255. + */ + public void testCreateAMQShortStringCharSequence() + { + AMQShortString string = new AMQShortString((CharSequence) "test"); + assertEquals("constructed amq short string length differs from expected", 4, string.length()); + assertTrue("constructed amq short string differs from expected", string.equals("test")); + } + + /** + * Test method for + * {@link org.apache.qpid.framing.AMQShortString#AMQShortString(byte[])}. + * <p> + * Tests an attempt to create an AMQP short string from byte array with length over 255. + */ + public void testCreateAMQShortStringByteArrayOver255() + { + String test = buildString('a', 256); + byte[] bytes = null; + try + { + bytes = test.getBytes("UTF-8"); + } + catch (UnsupportedEncodingException e) + { + fail("UTF-8 encoding is not supported anymore by JVM:" + e.getMessage()); + } + try + { + new AMQShortString(bytes); + fail("It should not be possible to create AMQShortString with length over 255"); + } + catch (IllegalArgumentException e) + { + assertEquals("Exception message differs from expected", + "Cannot create AMQShortString with number of octets over 255!", e.getMessage()); + } + } + + /** + * Test method for + * {@link org.apache.qpid.framing.AMQShortString#AMQShortString(java.lang.String)} + * <p> + * Tests an attempt to create an AMQP short string from string with length over 255 + */ + public void testCreateAMQShortStringStringOver255() + { + String test = buildString('a', 256); + try + { + new AMQShortString(test); + fail("It should not be possible to create AMQShortString with length over 255"); + } + catch (IllegalArgumentException e) + { + assertEquals("Exception message differs from expected", + "Cannot create AMQShortString with number of octets over 255!", e.getMessage()); + } + } + + /** + * Test method for + * {@link org.apache.qpid.framing.AMQShortString#AMQShortString(char[])}. + * <p> + * Tests an attempt to create an AMQP short string from char array with length over 255. + */ + public void testCreateAMQShortStringCharArrayOver255() + { + String test = buildString('a', 256); + char[] chars = test.toCharArray(); + try + { + new AMQShortString(chars); + fail("It should not be possible to create AMQShortString with length over 255"); + } + catch (IllegalArgumentException e) + { + assertEquals("Exception message differs from expected", + "Cannot create AMQShortString with number of octets over 255!", e.getMessage()); + } + } + + /** + * Test method for + * {@link org.apache.qpid.framing.AMQShortString#AMQShortString(java.lang.CharSequence)} + * <p> + * Tests an attempt to create an AMQP short string from char sequence with length over 255. + */ + public void testCreateAMQShortStringCharSequenceOver255() + { + String test = buildString('a', 256); + try + { + new AMQShortString((CharSequence) test); + fail("It should not be possible to create AMQShortString with length over 255"); + } + catch (IllegalArgumentException e) + { + assertEquals("Exception message differs from expected", + "Cannot create AMQShortString with number of octets over 255!", e.getMessage()); + } + } + + /** + * Tests joining of short strings into a short string with length over 255. + */ + public void testJoinOverflow() + { + List<AMQShortString> data = new ArrayList<AMQShortString>(); + for (int i = 0; i < 25; i++) + { + data.add(new AMQShortString("test data!")); + } + try + { + AMQShortString.join(data, new AMQShortString(" ")); + fail("It should not be possible to create AMQShortString with length over 255"); + } + catch (IllegalArgumentException e) + { + assertEquals("Exception message differs from expected", + "Cannot create AMQShortString with number of octets over 255!", e.getMessage()); + } + } + + /** + * Tests joining of short strings into a short string with length less than 255. + */ + public void testJoin() + { + StringBuilder expected = new StringBuilder(); + List<AMQShortString> data = new ArrayList<AMQShortString>(); + data.add(new AMQShortString("test data 1")); + expected.append("test data 1"); + data.add(new AMQShortString("test data 2")); + expected.append(" test data 2"); + AMQShortString result = AMQShortString.join(data, new AMQShortString(" ")); + assertEquals("join result differs from expected", expected.toString(), result.asString()); + } + + /** + * A helper method to generate a string with given length containing given + * character + * + * @param ch + * char to build string with + * @param length + * target string length + * @return string + */ + private String buildString(char ch, int length) + { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < length; i++) + { + sb.append(ch); + } + return sb.toString(); + } } diff --git a/java/common/src/test/java/org/apache/qpid/framing/BasicContentHeaderPropertiesTest.java b/java/common/src/test/java/org/apache/qpid/framing/BasicContentHeaderPropertiesTest.java index 4fd1f60d69..5e7783f492 100644 --- a/java/common/src/test/java/org/apache/qpid/framing/BasicContentHeaderPropertiesTest.java +++ b/java/common/src/test/java/org/apache/qpid/framing/BasicContentHeaderPropertiesTest.java @@ -20,10 +20,10 @@ */ package org.apache.qpid.framing; -import org.apache.mina.common.ByteBuffer; - import junit.framework.TestCase; +import java.io.*; + public class BasicContentHeaderPropertiesTest extends TestCase { @@ -76,15 +76,14 @@ public class BasicContentHeaderPropertiesTest extends TestCase assertEquals(99, _testProperties.getPropertyFlags()); } - public void testWritePropertyListPayload() + public void testWritePropertyListPayload() throws IOException { - ByteBuffer buf = ByteBuffer.allocate(300); - _testProperties.writePropertyListPayload(buf); + _testProperties.writePropertyListPayload(new DataOutputStream(new ByteArrayOutputStream(300))); } public void testPopulatePropertiesFromBuffer() throws Exception { - ByteBuffer buf = ByteBuffer.allocate(300); + DataInputStream buf = new DataInputStream(new ByteArrayInputStream(new byte[300])); _testProperties.populatePropertiesFromBuffer(buf, 99, 99); } diff --git a/java/common/src/test/java/org/apache/qpid/framing/PropertyFieldTableTest.java b/java/common/src/test/java/org/apache/qpid/framing/PropertyFieldTableTest.java index d4691ba097..bb4c9c3884 100644 --- a/java/common/src/test/java/org/apache/qpid/framing/PropertyFieldTableTest.java +++ b/java/common/src/test/java/org/apache/qpid/framing/PropertyFieldTableTest.java @@ -23,14 +23,14 @@ package org.apache.qpid.framing; import junit.framework.Assert; import junit.framework.TestCase; -import org.apache.mina.common.ByteBuffer; - import org.apache.qpid.AMQInvalidArgumentException; import org.apache.qpid.AMQPInvalidClassException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.*; + public class PropertyFieldTableTest extends TestCase { private static final Logger _logger = LoggerFactory.getLogger(PropertyFieldTableTest.class); @@ -441,7 +441,7 @@ public class PropertyFieldTableTest extends TestCase } /** Check that a nested field table parameter correctly encodes and decodes to a byte buffer. */ - public void testNestedFieldTable() + public void testNestedFieldTable() throws IOException { byte[] testBytes = new byte[] { 0, 1, 2, 3, 4, 5 }; @@ -465,14 +465,16 @@ public class PropertyFieldTableTest extends TestCase outerTable.setFieldTable("innerTable", innerTable); // Write the outer table into the buffer. - final ByteBuffer buffer = ByteBuffer.allocate((int) outerTable.getEncodedSize() + 4); - outerTable.writeToBuffer(buffer); - buffer.flip(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + outerTable.writeToBuffer(new DataOutputStream(baos)); + + byte[] data = baos.toByteArray(); // Extract the table back from the buffer again. try { - FieldTable extractedOuterTable = EncodingUtils.readFieldTable(buffer); + FieldTable extractedOuterTable = EncodingUtils.readFieldTable(new DataInputStream(new ByteArrayInputStream(data))); FieldTable extractedTable = extractedOuterTable.getFieldTable("innerTable"); @@ -567,7 +569,7 @@ public class PropertyFieldTableTest extends TestCase Assert.assertEquals("Hello", table.getObject("object-string")); } - public void testwriteBuffer() + public void testwriteBuffer() throws IOException { byte[] bytes = { 99, 98, 97, 96, 95 }; @@ -585,15 +587,17 @@ public class PropertyFieldTableTest extends TestCase table.setString("string", "hello"); table.setString("null-string", null); - final ByteBuffer buffer = ByteBuffer.allocate((int) table.getEncodedSize() + 4); // FIXME XXX: Is cast a problem? - table.writeToBuffer(buffer); + ByteArrayOutputStream baos = new ByteArrayOutputStream((int) table.getEncodedSize() + 4); + table.writeToBuffer(new DataOutputStream(baos)); + + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + DataInputStream dis = new DataInputStream(bais); - buffer.flip(); - long length = buffer.getUnsignedInt(); + long length = dis.readInt() & 0xFFFFFFFFL; - FieldTable table2 = new FieldTable(buffer, length); + FieldTable table2 = new FieldTable(dis, length); Assert.assertEquals((Boolean) true, table2.getBoolean("bool")); Assert.assertEquals((Byte) Byte.MAX_VALUE, table2.getByte("byte")); diff --git a/java/common/src/test/java/org/apache/qpid/session/TestSession.java b/java/common/src/test/java/org/apache/qpid/session/TestSession.java deleted file mode 100644 index aafc91b03b..0000000000 --- a/java/common/src/test/java/org/apache/qpid/session/TestSession.java +++ /dev/null @@ -1,277 +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.session; - -import org.apache.mina.common.*; - -import java.net.SocketAddress; -import java.util.Set; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.ConcurrentHashMap; - -public class TestSession implements IoSession -{ - private final ConcurrentMap attributes = new ConcurrentHashMap(); - - public TestSession() - { - } - - public IoService getService() - { - return null; //TODO - } - - public IoServiceConfig getServiceConfig() - { - return null; //TODO - } - - public IoHandler getHandler() - { - return null; //TODO - } - - public IoSessionConfig getConfig() - { - return null; //TODO - } - - public IoFilterChain getFilterChain() - { - return null; //TODO - } - - public WriteFuture write(Object message) - { - return null; //TODO - } - - public CloseFuture close() - { - return null; //TODO - } - - 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; //TODO - } - - public boolean isConnected() - { - return false; //TODO - } - - public boolean isClosing() - { - return false; //TODO - } - - public CloseFuture getCloseFuture() - { - return null; //TODO - } - - public SocketAddress getRemoteAddress() - { - return null; //TODO - } - - public SocketAddress getLocalAddress() - { - return null; //TODO - } - - public SocketAddress getServiceAddress() - { - return null; //TODO - } - - public int getIdleTime(IdleStatus status) - { - return 0; //TODO - } - - public long getIdleTimeInMillis(IdleStatus status) - { - return 0; //TODO - } - - public void setIdleTime(IdleStatus status, int idleTime) - { - //TODO - } - - public int getWriteTimeout() - { - return 0; //TODO - } - - public long getWriteTimeoutInMillis() - { - return 0; //TODO - } - - public void setWriteTimeout(int writeTimeout) - { - //TODO - } - - public TrafficMask getTrafficMask() - { - return null; //TODO - } - - public void setTrafficMask(TrafficMask trafficMask) - { - //TODO - } - - public void suspendRead() - { - //TODO - } - - public void suspendWrite() - { - //TODO - } - - public void resumeRead() - { - //TODO - } - - public void resumeWrite() - { - //TODO - } - - public long getReadBytes() - { - return 0; //TODO - } - - public long getWrittenBytes() - { - return 0; //TODO - } - - public long getReadMessages() - { - return 0; - } - - public long getWrittenMessages() - { - return 0; - } - - public long getWrittenWriteRequests() - { - return 0; //TODO - } - - public int getScheduledWriteRequests() - { - return 0; //TODO - } - - public int getScheduledWriteBytes() - { - return 0; //TODO - } - - public long getCreationTime() - { - return 0; //TODO - } - - public long getLastIoTime() - { - return 0; //TODO - } - - public long getLastReadTime() - { - return 0; //TODO - } - - public long getLastWriteTime() - { - return 0; //TODO - } - - public boolean isIdle(IdleStatus status) - { - return false; //TODO - } - - public int getIdleCount(IdleStatus status) - { - return 0; //TODO - } - - public long getLastIdleTime(IdleStatus status) - { - return 0; //TODO - } -} diff --git a/java/common/src/test/java/org/apache/qpid/ssl/SSLContextFactoryTest.java b/java/common/src/test/java/org/apache/qpid/ssl/SSLContextFactoryTest.java new file mode 100644 index 0000000000..288946e064 --- /dev/null +++ b/java/common/src/test/java/org/apache/qpid/ssl/SSLContextFactoryTest.java @@ -0,0 +1,84 @@ +/* Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.ssl; + +import java.io.IOException; + +import javax.net.ssl.SSLContext; + +import org.apache.qpid.test.utils.QpidTestCase; + +public class SSLContextFactoryTest extends QpidTestCase +{ + private static final String BROKER_KEYSTORE_PATH = TEST_RESOURCES_DIR + "/ssl/java_broker_keystore.jks"; + private static final String CLIENT_KEYSTORE_PATH = TEST_RESOURCES_DIR + "/ssl/java_client_keystore.jks"; + private static final String CLIENT_TRUSTSTORE_PATH = TEST_RESOURCES_DIR + "/ssl/java_client_truststore.jks"; + private static final String STORE_PASSWORD = "password"; + private static final String CERT_TYPE = "SunX509"; + private static final String CERT_ALIAS_APP1 = "app1"; + + public void testBuildServerContext() throws Exception + { + SSLContext context = SSLContextFactory.buildServerContext(BROKER_KEYSTORE_PATH, STORE_PASSWORD, CERT_TYPE); + assertNotNull("SSLContext should not be null", context); + } + + public void testBuildServerContextWithIncorrectPassword() throws Exception + { + try + { + SSLContextFactory.buildServerContext(BROKER_KEYSTORE_PATH, "sajdklsad", CERT_TYPE); + fail("Exception was not thrown due to incorrect password"); + } + catch (IOException e) + { + //expected + } + } + + public void testTrustStoreDoesNotExist() throws Exception + { + try + { + SSLContextFactory.buildClientContext("/path/to/nothing", STORE_PASSWORD, CERT_TYPE, CLIENT_KEYSTORE_PATH, STORE_PASSWORD, CERT_TYPE, null); + fail("Exception was not thrown due to incorrect path"); + } + catch (IOException e) + { + //expected + } + } + + public void testBuildClientContextForSSLEncryptionOnly() throws Exception + { + SSLContext context = SSLContextFactory.buildClientContext(CLIENT_TRUSTSTORE_PATH, STORE_PASSWORD, CERT_TYPE, null, null, null, null); + assertNotNull("SSLContext should not be null", context); + } + + public void testBuildClientContextWithForClientAuth() throws Exception + { + SSLContext context = SSLContextFactory.buildClientContext(CLIENT_TRUSTSTORE_PATH, STORE_PASSWORD, CERT_TYPE, CLIENT_KEYSTORE_PATH, STORE_PASSWORD, CERT_TYPE, null); + assertNotNull("SSLContext should not be null", context); + } + + public void testBuildClientContextWithForClientAuthWithCertAlias() throws Exception + { + SSLContext context = SSLContextFactory.buildClientContext(CLIENT_TRUSTSTORE_PATH, STORE_PASSWORD, CERT_TYPE, CLIENT_KEYSTORE_PATH, STORE_PASSWORD, CERT_TYPE, CERT_ALIAS_APP1); + assertNotNull("SSLContext should not be null", context); + } +} diff --git a/java/common/src/test/java/org/apache/qpid/test/utils/QpidTestCase.java b/java/common/src/test/java/org/apache/qpid/test/utils/QpidTestCase.java index 8b470d555e..e69f95f916 100644 --- a/java/common/src/test/java/org/apache/qpid/test/utils/QpidTestCase.java +++ b/java/common/src/test/java/org/apache/qpid/test/utils/QpidTestCase.java @@ -24,17 +24,28 @@ import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; -import java.util.ArrayList; -import java.util.List; +import java.net.DatagramSocket; +import java.net.ServerSocket; +import java.util.*; import junit.framework.TestCase; import junit.framework.TestResult; +import org.apache.log4j.Level; import org.apache.log4j.Logger; + public class QpidTestCase extends TestCase { - protected static final Logger _logger = Logger.getLogger(QpidTestCase.class); + public static final String QPID_HOME = System.getProperty("QPID_HOME"); + public static final String TEST_RESOURCES_DIR = QPID_HOME + "/../test-profiles/test_resources/"; + + private static final Logger _logger = Logger.getLogger(QpidTestCase.class); + + private final Map<Logger, Level> _loggerLevelSetForTest = new HashMap<Logger, Level>(); + private final Map<String, String> _propertiesSetForTest = new HashMap<String, String>(); + + private String _testName; /** * Some tests are excluded when the property test.excludes is set to true. @@ -54,7 +65,7 @@ public class QpidTestCase extends TestCase String exclusionListString = System.getProperties().getProperty("test.excludelist", ""); List<String> exclusionList = new ArrayList<String>(); - for (String uri : exclusionListURIs.split("\\s+")) + for (String uri : exclusionListURIs.split(";\\s*")) { File file = new File(uri); if (file.exists()) @@ -76,6 +87,10 @@ public class QpidTestCase extends TestCase _logger.warn("Exception when reading exclusion list", e); } } + else + { + _logger.info("Specified exclude file does not exist: " + uri); + } } if (!exclusionListString.equals("")) @@ -127,4 +142,187 @@ public class QpidTestCase extends TestCase return storeClass != null ? storeClass : MEMORY_STORE_CLASS_NAME ; } + + + public static final int MIN_PORT_NUMBER = 1; + public static final int MAX_PORT_NUMBER = 49151; + + + /** + * Gets the next available port starting at a port. + * + * @param fromPort the port to scan for availability + * @throws NoSuchElementException if there are no ports available + */ + protected int getNextAvailable(int fromPort) + { + if ((fromPort < MIN_PORT_NUMBER) || (fromPort > MAX_PORT_NUMBER)) + { + throw new IllegalArgumentException("Invalid start port: " + fromPort); + } + + for (int i = fromPort; i <= MAX_PORT_NUMBER; i++) + { + if (available(i)) { + return i; + } + } + + throw new NoSuchElementException("Could not find an available port above " + fromPort); + } + + /** + * Checks to see if a specific port is available. + * + * @param port the port to check for availability + */ + private boolean available(int port) + { + if ((port < MIN_PORT_NUMBER) || (port > MAX_PORT_NUMBER)) + { + throw new IllegalArgumentException("Invalid start port: " + port); + } + + ServerSocket ss = null; + DatagramSocket ds = null; + try + { + ss = new ServerSocket(port); + ss.setReuseAddress(true); + ds = new DatagramSocket(port); + ds.setReuseAddress(true); + return true; + } + catch (IOException e) + { + } + finally + { + if (ds != null) + { + ds.close(); + } + + if (ss != null) + { + try + { + ss.close(); + } + catch (IOException e) + { + /* should not be thrown */ + } + } + } + + return false; + } + + public int findFreePort() + { + return getNextAvailable(10000); + } + + /** + * Set a System property for duration of this test only. The tearDown will + * guarantee to reset the property to its previous value after the test + * completes. + * + * @param property The property to set + * @param value the value to set it to, if null, the property will be cleared + */ + protected void setTestSystemProperty(final String property, final String value) + { + if (!_propertiesSetForTest.containsKey(property)) + { + // Record the current value so we can revert it later. + _propertiesSetForTest.put(property, System.getProperty(property)); + } + + if (value == null) + { + System.clearProperty(property); + } + else + { + System.setProperty(property, value); + } + } + + /** + * Restore the System property values that were set by this test run. + */ + protected void revertTestSystemProperties() + { + if(!_propertiesSetForTest.isEmpty()) + { + _logger.debug("reverting " + _propertiesSetForTest.size() + " test properties"); + for (String key : _propertiesSetForTest.keySet()) + { + String value = _propertiesSetForTest.get(key); + if (value != null) + { + System.setProperty(key, value); + } + else + { + System.clearProperty(key); + } + } + + _propertiesSetForTest.clear(); + } + } + + /** + * 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(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 (Logger logger : _loggerLevelSetForTest.keySet()) + { + logger.setLevel(_loggerLevelSetForTest.get(logger)); + } + + _loggerLevelSetForTest.clear(); + } + + protected void tearDown() throws java.lang.Exception + { + _logger.info("========== tearDown " + _testName + " =========="); + revertTestSystemProperties(); + revertLoggingLevels(); + } + + protected void setUp() throws Exception + { + _testName = getClass().getSimpleName() + "." + getName(); + _logger.info("========== start " + _testName + " =========="); + } + + protected String getTestName() + { + return _testName; + } } diff --git a/java/common/src/test/java/org/apache/qpid/transport/ConnectionTest.java b/java/common/src/test/java/org/apache/qpid/transport/ConnectionTest.java index 375a326654..49f6a08007 100644 --- a/java/common/src/test/java/org/apache/qpid/transport/ConnectionTest.java +++ b/java/common/src/test/java/org/apache/qpid/transport/ConnectionTest.java @@ -20,32 +20,27 @@ */ package org.apache.qpid.transport; -import org.apache.mina.util.AvailablePortFinder; - -import org.apache.qpid.test.utils.QpidTestCase; -import org.apache.qpid.transport.network.ConnectionBinding; -import org.apache.qpid.transport.network.io.IoAcceptor; -import org.apache.qpid.transport.util.Logger; -import org.apache.qpid.transport.util.Waiter; +import static org.apache.qpid.transport.Option.EXPECTED; +import static org.apache.qpid.transport.Option.NONE; +import static org.apache.qpid.transport.Option.SYNC; +import java.io.IOException; import java.util.ArrayList; -import java.util.List; import java.util.Collections; +import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import java.io.IOException; -import static org.apache.qpid.transport.Option.*; +import org.apache.qpid.test.utils.QpidTestCase; +import org.apache.qpid.transport.network.ConnectionBinding; +import org.apache.qpid.transport.network.io.IoAcceptor; +import org.apache.qpid.transport.util.Waiter; /** * ConnectionTest */ - public class ConnectionTest extends QpidTestCase implements SessionListener { - - private static final Logger log = Logger.get(ConnectionTest.class); - private int port; private volatile boolean queue = false; private List<MessageTransfer> messages = new ArrayList<MessageTransfer>(); @@ -58,7 +53,7 @@ public class ConnectionTest extends QpidTestCase implements SessionListener { super.setUp(); - port = AvailablePortFinder.getNextAvailable(12000); + port = findFreePort(); } protected void tearDown() throws Exception @@ -158,7 +153,8 @@ public class ConnectionTest extends QpidTestCase implements SessionListener private Connection connect(final CountDownLatch closed) { - Connection conn = new Connection(); + final Connection conn = new Connection(); + conn.setConnectionDelegate(new ClientDelegate(new ConnectionSettings())); conn.addConnectionListener(new ConnectionListener() { public void opened(Connection conn) {} @@ -182,9 +178,9 @@ public class ConnectionTest extends QpidTestCase implements SessionListener { // Force os.name to be windows to exercise code in IoReceiver // that looks for the value of os.name - System.setProperty("os.name","windows"); + setTestSystemProperty("os.name","windows"); - // Start server as 0-9 to froce a ProtocolVersionException + // Start server as 0-9 to force a ProtocolVersionException startServer(new ProtocolHeader(1, 0, 9)); CountDownLatch closed = new CountDownLatch(1); @@ -219,7 +215,7 @@ public class ConnectionTest extends QpidTestCase implements SessionListener conn.send(protocolHeader); List<Object> utf8 = new ArrayList<Object>(); utf8.add("utf8"); - conn.connectionStart(null, Collections.EMPTY_LIST, utf8); + conn.connectionStart(null, Collections.emptyList(), utf8); } @Override @@ -270,40 +266,7 @@ public class ConnectionTest extends QpidTestCase implements SessionListener } } - class FailoverConnectionListener implements ConnectionListener - { - public void opened(Connection conn) {} - - public void exception(Connection conn, ConnectionException e) - { - throw e; - } - - public void closed(Connection conn) - { - queue = true; - conn.connect("localhost", port, null, "guest", "guest"); - conn.resume(); - } - } - - class TestSessionListener implements SessionListener - { - public void opened(Session s) {} - public void resumed(Session s) {} - public void exception(Session s, SessionException e) {} - public void message(Session s, MessageTransfer xfr) - { - synchronized (incoming) - { - incoming.add(xfr); - incoming.notifyAll(); - } - s.processed(xfr); - } - public void closed(Session s) {} - } public void testResumeNonemptyReplayBuffer() throws Exception { @@ -311,6 +274,7 @@ public class ConnectionTest extends QpidTestCase implements SessionListener Connection conn = new Connection(); conn.addConnectionListener(new FailoverConnectionListener()); + conn.setConnectionDelegate(new ClientDelegate(new ConnectionSettings())); conn.connect("localhost", port, null, "guest", "guest"); Session ssn = conn.createSession(1); ssn.setSessionListener(new TestSessionListener()); @@ -365,6 +329,7 @@ public class ConnectionTest extends QpidTestCase implements SessionListener startServer(); Connection conn = new Connection(); + conn.setConnectionDelegate(new ClientDelegate(new ConnectionSettings())); conn.addConnectionListener(new FailoverConnectionListener()); conn.connect("localhost", port, null, "guest", "guest"); Session ssn = conn.createSession(1); @@ -387,6 +352,7 @@ public class ConnectionTest extends QpidTestCase implements SessionListener startServer(); Connection conn = new Connection(); + conn.setConnectionDelegate(new ClientDelegate(new ConnectionSettings())); conn.connect("localhost", port, null, "guest", "guest"); Session ssn = conn.createSession(); ssn.sessionFlush(EXPECTED); @@ -400,6 +366,7 @@ public class ConnectionTest extends QpidTestCase implements SessionListener { startServer(); Connection conn = new Connection(); + conn.setConnectionDelegate(new ClientDelegate(new ConnectionSettings())); conn.connect("localhost", port, null, "guest", "guest"); conn.connectionHeartbeat(); conn.close(); @@ -410,6 +377,7 @@ public class ConnectionTest extends QpidTestCase implements SessionListener startServer(); Connection conn = new Connection(); + conn.setConnectionDelegate(new ClientDelegate(new ConnectionSettings())); conn.connect("localhost", port, null, "guest", "guest"); Session ssn = conn.createSession(); send(ssn, "EXCP 0"); @@ -429,6 +397,7 @@ public class ConnectionTest extends QpidTestCase implements SessionListener startServer(); Connection conn = new Connection(); + conn.setConnectionDelegate(new ClientDelegate(new ConnectionSettings())); conn.connect("localhost", port, null, "guest", "guest"); Session ssn = conn.createSession(); send(ssn, "EXCP 0", true); @@ -443,4 +412,38 @@ public class ConnectionTest extends QpidTestCase implements SessionListener } } + class FailoverConnectionListener implements ConnectionListener + { + public void opened(Connection conn) {} + + public void exception(Connection conn, ConnectionException e) + { + throw e; + } + + public void closed(Connection conn) + { + queue = true; + conn.connect("localhost", port, null, "guest", "guest"); + conn.resume(); + } + } + + class TestSessionListener implements SessionListener + { + public void opened(Session s) {} + public void resumed(Session s) {} + public void exception(Session s, SessionException e) {} + public void message(Session s, MessageTransfer xfr) + { + synchronized (incoming) + { + incoming.add(xfr); + incoming.notifyAll(); + } + + s.processed(xfr); + } + public void closed(Session s) {} + } } diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/io/IoContext.java b/java/common/src/test/java/org/apache/qpid/transport/MockSender.java index 69b3a0ce45..4b38b7318a 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/network/io/IoContext.java +++ b/java/common/src/test/java/org/apache/qpid/transport/MockSender.java @@ -1,5 +1,5 @@ /* - * + * * 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 @@ -7,29 +7,41 @@ * 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.io; +package org.apache.qpid.transport; -import java.net.Socket; import java.nio.ByteBuffer; -import org.apache.qpid.transport.Sender; - -public interface IoContext +public class MockSender implements Sender<ByteBuffer> { - Sender<ByteBuffer> getSender(); - - IoReceiver getReceiver(); - Socket getSocket(); + public void setIdleTimeout(int i) + { + + } + + public void send(ByteBuffer msg) + { + + } + + public void flush() + { + + } + + public void close() + { + + } } diff --git a/java/common/src/test/java/org/apache/qpid/transport/SessionTimeoutTest.java b/java/common/src/test/java/org/apache/qpid/transport/SessionTimeoutTest.java new file mode 100644 index 0000000000..5f1c1254a2 --- /dev/null +++ b/java/common/src/test/java/org/apache/qpid/transport/SessionTimeoutTest.java @@ -0,0 +1,81 @@ +/* + * 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 org.apache.qpid.configuration.ClientProperties; +import org.apache.qpid.test.utils.QpidTestCase; + + +public class SessionTimeoutTest extends QpidTestCase +{ + public void testSessionTimeout() + { + try + { + long timeout = 1; + setTestSystemProperty("qpid.sync_op_timeout", Long.toString(timeout)); + assertSessionTimeout(timeout); + } + finally + { + revertTestSystemProperties(); + } + } + + public void testSessionTimeoutSetWith_amqj_default_syncwrite_timeout() + { + try + { + long timeout = 1; + setTestSystemProperty("amqj.default_syncwrite_timeout", Long.toString(timeout)); + setTestSystemProperty("qpid.sync_op_timeout", null); + assertSessionTimeout(timeout); + } + finally + { + revertTestSystemProperties(); + } + } + + private void assertSessionTimeout(long timeout) + { + Session session = new TestSession(null, null, 0); + long startTime = System.currentTimeMillis(); + try + { + session.awaitOpen(); + fail("SessionTimeoutException is expected!"); + } + catch (SessionException e) + { + long elapsedTime = System.currentTimeMillis() - startTime; + assertTrue("Expected timeout should happened in " + timeout + " ms but timeout occured in " + + elapsedTime + " ms!", elapsedTime >= timeout && elapsedTime < ClientProperties.DEFAULT_SYNC_OPERATION_TIMEOUT); + } + } + + class TestSession extends Session + { + public TestSession(Connection connection, Binary name, long expiry) + { + super(connection, name, expiry); + } + } + +} diff --git a/java/common/src/test/java/org/apache/qpid/transport/TestNetworkDriver.java b/java/common/src/test/java/org/apache/qpid/transport/TestNetworkConnection.java index 957a7190ee..8533c64fab 100644 --- a/java/common/src/test/java/org/apache/qpid/transport/TestNetworkDriver.java +++ b/java/common/src/test/java/org/apache/qpid/transport/TestNetworkConnection.java @@ -25,34 +25,36 @@ 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; +import org.apache.qpid.transport.network.NetworkConnection; /** * 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 +public class TestNetworkConnection implements NetworkConnection { - private final ConcurrentMap attributes = new ConcurrentHashMap(); private String _remoteHost = "127.0.0.1"; private String _localHost = "127.0.0.1"; private int _port = 1; private SocketAddress _localAddress = null; private SocketAddress _remoteAddress = null; + private final MockSender _sender; - public TestNetworkDriver() + public TestNetworkConnection() { + _sender = new MockSender(); } + + public void bind(int port, InetAddress[] addresses, ProtocolEngineFactory protocolFactory, - NetworkDriverConfiguration config, SSLContextFactory sslFactory) throws BindException + NetworkTransportConfiguration config, SSLContextFactory sslFactory) throws BindException { - + } public SocketAddress getLocalAddress() @@ -65,40 +67,40 @@ public class TestNetworkDriver implements NetworkDriver return (_remoteAddress != null) ? _remoteAddress : new InetSocketAddress(_remoteHost, _port); } - public void open(int port, InetAddress destination, ProtocolEngine engine, NetworkDriverConfiguration config, + public void open(int port, InetAddress destination, ProtocolEngine engine, NetworkTransportConfiguration 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(int i) { - + } public void setPort(int port) @@ -130,4 +132,13 @@ public class TestNetworkDriver implements NetworkDriver { _remoteAddress = address; } + + public Sender<ByteBuffer> getSender() + { + return _sender; + } + + public void start() + { + } } diff --git a/java/common/src/test/java/org/apache/qpid/transport/network/TransportTest.java b/java/common/src/test/java/org/apache/qpid/transport/network/TransportTest.java new file mode 100644 index 0000000000..7039b904e3 --- /dev/null +++ b/java/common/src/test/java/org/apache/qpid/transport/network/TransportTest.java @@ -0,0 +1,157 @@ +/* + * + * 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; + + +import java.nio.ByteBuffer; + +import javax.net.ssl.SSLContext; + +import org.apache.qpid.framing.ProtocolVersion; +import org.apache.qpid.protocol.ProtocolEngineFactory; +import org.apache.qpid.test.utils.QpidTestCase; +import org.apache.qpid.transport.ConnectionSettings; +import org.apache.qpid.transport.NetworkTransportConfiguration; +import org.apache.qpid.transport.Receiver; +import org.apache.qpid.transport.TransportException; +import org.apache.qpid.transport.network.io.IoNetworkTransport; + +public class TransportTest extends QpidTestCase +{ + + + + public void testDefaultGetOutgoingTransportForv0_8() throws Exception + { + final OutgoingNetworkTransport networkTransport = Transport.getOutgoingTransportInstance(ProtocolVersion.v8_0); + assertNotNull(networkTransport); + assertTrue(networkTransport instanceof IoNetworkTransport); + } + + public void testGloballyOverriddenOutgoingTransportForv0_8() throws Exception + { + setTestSystemProperty(Transport.QPID_TRANSPORT_PROPNAME, TestOutgoingNetworkTransport.class.getName()); + + final OutgoingNetworkTransport networkTransport = Transport.getOutgoingTransportInstance(ProtocolVersion.v8_0); + assertNotNull(networkTransport); + assertTrue(networkTransport instanceof TestOutgoingNetworkTransport); + } + + public void testProtocolSpecificOverriddenOutgoingTransportForv0_8() throws Exception + { + setTestSystemProperty(Transport.QPID_TRANSPORT_V0_8_PROPNAME, TestOutgoingNetworkTransport.class.getName()); + + final OutgoingNetworkTransport networkTransport = Transport.getOutgoingTransportInstance(ProtocolVersion.v8_0); + assertNotNull(networkTransport); + assertTrue(networkTransport instanceof TestOutgoingNetworkTransport); + } + + public void testDefaultGetOutgoingTransportForv0_10() throws Exception + { + final OutgoingNetworkTransport networkTransport = Transport.getOutgoingTransportInstance(ProtocolVersion.v0_10); + assertNotNull(networkTransport); + assertTrue(networkTransport instanceof IoNetworkTransport); + } + + public void testDefaultGetIncomingTransport() throws Exception + { + final IncomingNetworkTransport networkTransport = Transport.getIncomingTransportInstance(); + assertNotNull(networkTransport); + assertTrue(networkTransport instanceof IoNetworkTransport); + } + + public void testOverriddenGetIncomingTransport() throws Exception + { + setTestSystemProperty(Transport.QPID_BROKER_TRANSPORT_PROPNAME, TestIncomingNetworkTransport.class.getName()); + + final IncomingNetworkTransport networkTransport = Transport.getIncomingTransportInstance(); + assertNotNull(networkTransport); + assertTrue(networkTransport instanceof TestIncomingNetworkTransport); + } + + public void testInvalidOutgoingTransportClassName() throws Exception + { + setTestSystemProperty(Transport.QPID_TRANSPORT_PROPNAME, "invalid"); + + try + { + Transport.getOutgoingTransportInstance(ProtocolVersion.v0_10); + fail("Should have failed to load the invalid class"); + } + catch(TransportException te) + { + //expected, ignore + } + } + + public void testInvalidOutgoingTransportProtocolVersion() throws Exception + { + try + { + Transport.getOutgoingTransportInstance(new ProtocolVersion((byte)0, (byte)0)); + fail("Should have failed to load the transport for invalid protocol version"); + } + catch(IllegalArgumentException iae) + { + //expected, ignore + } + } + + public static class TestOutgoingNetworkTransport implements OutgoingNetworkTransport + { + + public void close() + { + throw new UnsupportedOperationException(); + } + + public NetworkConnection getConnection() + { + throw new UnsupportedOperationException(); + } + + public NetworkConnection connect(ConnectionSettings settings, + Receiver<ByteBuffer> delegate, SSLContext sslContext) + { + throw new UnsupportedOperationException(); + } + } + + public static class TestIncomingNetworkTransport implements IncomingNetworkTransport + { + + public void close() + { + throw new UnsupportedOperationException(); + } + + public NetworkConnection getConnection() + { + throw new UnsupportedOperationException(); + } + + public void accept(NetworkTransportConfiguration config, + ProtocolEngineFactory factory, SSLContext sslContext) + { + throw new UnsupportedOperationException(); + } + } +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/io/IoAcceptor.java b/java/common/src/test/java/org/apache/qpid/transport/network/io/IoAcceptor.java index 8530240dcc..e075681acb 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/network/io/IoAcceptor.java +++ b/java/common/src/test/java/org/apache/qpid/transport/network/io/IoAcceptor.java @@ -80,7 +80,7 @@ public class IoAcceptor<E> extends Thread try { Socket sock = socket.accept(); - IoTransport<E> transport = new IoTransport<E>(sock, binding,false); + IoTransport<E> transport = new IoTransport<E>(sock, binding); } catch (IOException e) { diff --git a/java/common/src/test/java/org/apache/qpid/transport/network/io/IoTransport.java b/java/common/src/test/java/org/apache/qpid/transport/network/io/IoTransport.java new file mode 100644 index 0000000000..215c6d9931 --- /dev/null +++ b/java/common/src/test/java/org/apache/qpid/transport/network/io/IoTransport.java @@ -0,0 +1,91 @@ +/* + * 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.io; + +import java.net.Socket; +import java.nio.ByteBuffer; + +import org.apache.qpid.transport.Binding; +import org.apache.qpid.transport.Sender; +import org.apache.qpid.transport.util.Logger; + +/** + * This class provides a socket based transport using the java.io + * classes. + * + * The following params are configurable via JVM arguments + * TCP_NO_DELAY - amqj.tcpNoDelay + * SO_RCVBUF - amqj.receiveBufferSize + * SO_SNDBUF - amqj.sendBufferSize + */ +public final class IoTransport<E> +{ + + + private static final Logger log = Logger.get(IoTransport.class); + + private static int DEFAULT_READ_WRITE_BUFFER_SIZE = 64 * 1024; + private static int readBufferSize = Integer.getInteger + ("amqj.receiveBufferSize", DEFAULT_READ_WRITE_BUFFER_SIZE); + private static int writeBufferSize = Integer.getInteger + ("amqj.sendBufferSize", DEFAULT_READ_WRITE_BUFFER_SIZE); + + private Socket socket; + private Sender<ByteBuffer> sender; + private E endpoint; + private IoReceiver receiver; + private long timeout = 60000; + + IoTransport(Socket socket, Binding<E,ByteBuffer> binding) + { + this.socket = socket; + setupTransport(socket, binding); + } + + private void setupTransport(Socket socket, Binding<E, ByteBuffer> binding) + { + IoSender ios = new IoSender(socket, 2*writeBufferSize, timeout); + ios.initiate(); + + this.sender = ios; + this.endpoint = binding.endpoint(sender); + this.receiver = new IoReceiver(socket, binding.receiver(endpoint), + 2*readBufferSize, timeout); + this.receiver.initiate(); + + ios.registerCloseListener(this.receiver); + } + + public Sender<ByteBuffer> getSender() + { + return sender; + } + + public IoReceiver getReceiver() + { + return receiver; + } + + public Socket getSocket() + { + return socket; + } + +} diff --git a/java/common/src/test/java/org/apache/qpid/transport/network/mina/MINANetworkDriverTest.java b/java/common/src/test/java/org/apache/qpid/transport/network/mina/MINANetworkDriverTest.java deleted file mode 100644 index fc8e689ca4..0000000000 --- a/java/common/src/test/java/org/apache/qpid/transport/network/mina/MINANetworkDriverTest.java +++ /dev/null @@ -1,494 +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.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 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(); - // increment the port to prevent tests clashing with each other when - // the port is in TIMED_WAIT state. - TEST_PORT++; - } - - @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); - sleepForAtLeast(1500); - 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); - sleepForAtLeast(1500); - 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 have 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(NetworkDriver driver) - { - if (_engine == null) - { - _engine = new EchoProtocolEngine(); - _engine.setNetworkDriver(driver); - } - return getEngine(); - } - - public EchoProtocolEngine getEngine() - { - return _engine; - } - } - - public class CountingProtocolEngine implements ProtocolEngine - { - - protected NetworkDriver _driver; - public ArrayList<ByteBuffer> _receivedBytes = new ArrayList<ByteBuffer>(); - 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 SocketAddress getLocalAddress() - { - if (_driver != null) - { - return _driver.getLocalAddress(); - } - 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); - } - } - - 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 diff --git a/java/common/src/test/java/org/apache/qpid/util/FileUtilsTest.java b/java/common/src/test/java/org/apache/qpid/util/FileUtilsTest.java index 7eba5f092e..d6767eb9c0 100644 --- a/java/common/src/test/java/org/apache/qpid/util/FileUtilsTest.java +++ b/java/common/src/test/java/org/apache/qpid/util/FileUtilsTest.java @@ -27,7 +27,9 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; +import java.io.InputStream; import java.util.List; +import java.util.Properties; public class FileUtilsTest extends TestCase { @@ -182,6 +184,20 @@ public class FileUtilsTest extends TestCase } } + + /** + * Helper method to create a temporary file with test content. + * + * @param test_data The data to store in the file + * + * @return The File reference + */ + private File createTestFileInTmpDir(final String testData) throws Exception + { + final File tmpFile = File.createTempFile("test", "tmp"); + + return createTestFile(tmpFile.getCanonicalPath(), testData); + } /** * Helper method to create a test file with a string content * @@ -302,8 +318,74 @@ public class FileUtilsTest extends TestCase // expected path } } + + /** + * Tests that openFileOrDefaultResource can open a file on the filesystem. + * + */ + public void testOpenFileOrDefaultResourceOpensFileOnFileSystem() throws Exception + { + final File testFile = createTestFileInTmpDir("src=tmpfile"); + final String filenameOnFilesystem = testFile.getCanonicalPath(); + final String defaultResource = "org/apache/qpid/util/default.properties"; + + + final InputStream is = FileUtils.openFileOrDefaultResource(filenameOnFilesystem, defaultResource, this.getClass().getClassLoader()); + assertNotNull("Stream must not be null", is); + final Properties p = new Properties(); + p.load(is); + assertEquals("tmpfile", p.getProperty("src")); + } /** + * Tests that openFileOrDefaultResource can open a file on the classpath. + * + */ + public void testOpenFileOrDefaultResourceOpensFileOnClasspath() throws Exception + { + final String mydefaultsResource = "org/apache/qpid/util/mydefaults.properties"; + final String defaultResource = "org/apache/qpid/util/default.properties"; + + + final InputStream is = FileUtils.openFileOrDefaultResource(mydefaultsResource, defaultResource, this.getClass().getClassLoader()); + assertNotNull("Stream must not be null", is); + final Properties p = new Properties(); + p.load(is); + assertEquals("mydefaults", p.getProperty("src")); + } + + /** + * Tests that openFileOrDefaultResource returns the default resource when file cannot be found. + */ + public void testOpenFileOrDefaultResourceOpensDefaultResource() throws Exception + { + final File fileThatDoesNotExist = new File("/does/not/exist.properties"); + assertFalse("Test must not exist", fileThatDoesNotExist.exists()); + + final String defaultResource = "org/apache/qpid/util/default.properties"; + + final InputStream is = FileUtils.openFileOrDefaultResource(fileThatDoesNotExist.getCanonicalPath(), defaultResource, this.getClass().getClassLoader()); + assertNotNull("Stream must not be null", is); + Properties p = new Properties(); + p.load(is); + assertEquals("default.properties", p.getProperty("src")); + } + + /** + * Tests that openFileOrDefaultResource returns null if neither the file nor + * the default resource can be found.. + */ + public void testOpenFileOrDefaultResourceReturnsNullWhenNeitherCanBeFound() throws Exception + { + + final String mydefaultsResource = "org/apache/qpid/util/doesnotexisteiether.properties"; + final String defaultResource = "org/apache/qpid/util/doesnotexisteiether.properties"; + + final InputStream is = FileUtils.openFileOrDefaultResource(mydefaultsResource, defaultResource, this.getClass().getClassLoader()); + assertNull("Stream must be null", is); + } + + /** * Given two lists of File arrays ensure they are the same length and all entries in Before are in After * * @param filesBefore File[] diff --git a/java/common/src/test/java/org/apache/qpid/util/default.properties b/java/common/src/test/java/org/apache/qpid/util/default.properties new file mode 100644 index 0000000000..cb522ea9a7 --- /dev/null +++ b/java/common/src/test/java/org/apache/qpid/util/default.properties @@ -0,0 +1,2 @@ +# Used by FileUtilsTests +src=default.properties
\ No newline at end of file diff --git a/java/common/src/test/java/org/apache/qpid/util/mydefaults.properties b/java/common/src/test/java/org/apache/qpid/util/mydefaults.properties new file mode 100644 index 0000000000..6a49d927d0 --- /dev/null +++ b/java/common/src/test/java/org/apache/qpid/util/mydefaults.properties @@ -0,0 +1,2 @@ +# Used by FileUtilsTests +src=mydefaults
\ No newline at end of file diff --git a/java/common/templates/method/version/MethodBodyClass.vm b/java/common/templates/method/version/MethodBodyClass.vm index a739110d70..ce8a453eeb 100644 --- a/java/common/templates/method/version/MethodBodyClass.vm +++ b/java/common/templates/method/version/MethodBodyClass.vm @@ -46,9 +46,11 @@ package org.apache.qpid.framing.amqp_$version.getMajor()_$version.getMinor(); +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; import java.util.HashMap; -import org.apache.mina.common.ByteBuffer; import org.apache.qpid.framing.*; import org.apache.qpid.AMQException; @@ -56,7 +58,7 @@ public class ${javaClassName} extends AMQMethodBody_$version.getMajor()_$version { private static final AMQMethodBodyInstanceFactory FACTORY_INSTANCE = new AMQMethodBodyInstanceFactory() { - public AMQMethodBody newInstance(ByteBuffer in, long size) throws AMQFrameDecodingException + public AMQMethodBody newInstance(DataInputStream in, long size) throws AMQFrameDecodingException, IOException { return new ${javaClassName}(in); } @@ -84,7 +86,7 @@ public class ${javaClassName} extends AMQMethodBody_$version.getMajor()_$version // Constructor - public ${javaClassName}(ByteBuffer buffer) throws AMQFrameDecodingException + public ${javaClassName}(DataInputStream buffer) throws AMQFrameDecodingException, IOException { #foreach( $field in $method.ConsolidatedFields ) _$field.Name = read$field.getEncodingType()( buffer ); @@ -169,7 +171,7 @@ public class ${javaClassName} extends AMQMethodBody_$version.getMajor()_$version return size; } - public void writeMethodPayload(ByteBuffer buffer) + public void writeMethodPayload(DataOutputStream buffer) throws IOException { #foreach( $field in $method.ConsolidatedFields ) write$field.getEncodingType()( buffer, _$field.Name ); diff --git a/java/common/templates/model/MethodRegistryClass.vm b/java/common/templates/model/MethodRegistryClass.vm index 759e5e4a42..8258175ce7 100644 --- a/java/common/templates/model/MethodRegistryClass.vm +++ b/java/common/templates/model/MethodRegistryClass.vm @@ -30,7 +30,8 @@ package org.apache.qpid.framing; -import org.apache.mina.common.ByteBuffer; +import java.io.DataInputStream; +import java.io.IOException; import org.apache.qpid.framing.abstraction.ProtocolVersionMethodConverter; @@ -53,8 +54,8 @@ public abstract class MethodRegistry #end - public abstract AMQMethodBody convertToBody(ByteBuffer in, long size) - throws AMQFrameDecodingException; + public abstract AMQMethodBody convertToBody(DataInputStream in, long size) + throws AMQFrameDecodingException, IOException; public abstract int getMaxClassId(); @@ -101,4 +102,4 @@ public abstract class MethodRegistry public abstract ProtocolVersionMethodConverter getProtocolVersionMethodConverter(); -}
\ No newline at end of file +} diff --git a/java/common/templates/model/version/MethodRegistryClass.vm b/java/common/templates/model/version/MethodRegistryClass.vm index 277605e34b..79553f7748 100644 --- a/java/common/templates/model/version/MethodRegistryClass.vm +++ b/java/common/templates/model/version/MethodRegistryClass.vm @@ -35,32 +35,33 @@ import org.apache.qpid.protocol.AMQConstant; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.apache.mina.common.ByteBuffer; +import java.io.DataInputStream; +import java.io.IOException; import org.apache.qpid.framing.abstraction.ProtocolVersionMethodConverter; public class MethodRegistry_$version.getMajor()_$version.getMinor() extends MethodRegistry { - + private static final Logger _log = LoggerFactory.getLogger(MethodRegistry.class); - private ProtocolVersionMethodConverter _protocolVersionConverter = new MethodConverter_$version.getMajor()_$version.getMinor()(); - -#set( $specificModel = $model.asSingleVersionModel() ) - - -#set( $maxClassId = $specificModel.getMaximumClassId()+1 ) - private final AMQMethodBodyInstanceFactory[][] _factories = new AMQMethodBodyInstanceFactory[$maxClassId][]; - - public MethodRegistry_$version.getMajor()_$version.getMinor()() - { - this(new ProtocolVersion((byte)$version.getMajor(),(byte)$version.getMinor())); + private ProtocolVersionMethodConverter _protocolVersionConverter = new MethodConverter_$version.getMajor()_$version.getMinor()(); + +#set( $specificModel = $model.asSingleVersionModel() ) + + +#set( $maxClassId = $specificModel.getMaximumClassId()+1 ) + private final AMQMethodBodyInstanceFactory[][] _factories = new AMQMethodBodyInstanceFactory[$maxClassId][]; + + public MethodRegistry_$version.getMajor()_$version.getMinor()() + { + this(new ProtocolVersion((byte)$version.getMajor(),(byte)$version.getMinor())); } - - public MethodRegistry_$version.getMajor()_$version.getMinor()(ProtocolVersion pv) - { - super(pv); + + public MethodRegistry_$version.getMajor()_$version.getMinor()(ProtocolVersion pv) + { + super(pv); #foreach( $amqpClass in $specificModel.getClassList() ) #set( $amqpClassNameFirstChar = $amqpClass.getName().substring(0,1) ) #set( $amqpClassNameFirstCharU = $amqpClassNameFirstChar.toUpperCase() ) @@ -68,30 +69,30 @@ public class MethodRegistry_$version.getMajor()_$version.getMinor() extends Meth - // Register method body instance factories for the $amqpClassNameUpperCamel class. + // Register method body instance factories for the $amqpClassNameUpperCamel class. -#set( $maxMethodId = $amqpClass.getMaximumMethodId()+1 ) +#set( $maxMethodId = $amqpClass.getMaximumMethodId()+1 ) _factories[$amqpClass.getClassId()] = new AMQMethodBodyInstanceFactory[$maxMethodId]; - + #foreach( $amqpMethod in $amqpClass.getMethodList() ) #set( $amqpMethodNameFirstChar = $amqpMethod.getName().substring(0,1) ) #set( $amqpMethodNameFirstCharU = $amqpMethodNameFirstChar.toUpperCase() ) #set( $amqpMethodNameUpperCamel = "$amqpMethodNameFirstCharU$amqpMethod.getName().substring(1)" ) _factories[$amqpClass.getClassId()][$amqpMethod.getMethodId()] = ${amqpClassNameUpperCamel}${amqpMethodNameUpperCamel}BodyImpl.getFactory(); -#end - +#end + #end - - - } + + + } - public AMQMethodBody convertToBody(ByteBuffer in, long size) - throws AMQFrameDecodingException + public AMQMethodBody convertToBody(DataInputStream in, long size) + throws AMQFrameDecodingException, IOException { - int classId = in.getUnsignedShort(); - int methodId = in.getUnsignedShort(); - + int classId = in.readUnsignedShort(); + int methodId = in.readUnsignedShort(); + AMQMethodBodyInstanceFactory bodyFactory; try { @@ -137,15 +138,15 @@ public class MethodRegistry_$version.getMajor()_$version.getMinor() extends Meth public int getMaxClassId() - { - return $specificModel.getMaximumClassId(); - } + { + return $specificModel.getMaximumClassId(); + } public int getMaxMethodId(int classId) - { - return _factories[classId].length - 1; - } - + { + return _factories[classId].length - 1; + } + #foreach( $amqpClass in $specificModel.getClassList() ) @@ -153,12 +154,12 @@ public class MethodRegistry_$version.getMajor()_$version.getMinor() extends Meth #set( $amqpClassNameFirstCharU = $amqpClassNameFirstChar.toUpperCase() ) #set( $amqpClassNameUpperCamel = "$amqpClassNameFirstCharU$amqpClass.getName().substring(1)" ) - + #foreach( $amqpMethod in $amqpClass.getMethodList() ) #set( $amqpMethodNameFirstChar = $amqpMethod.getName().substring(0,1) ) #set( $amqpMethodNameFirstCharU = $amqpMethodNameFirstChar.toUpperCase() ) #set( $amqpMethodNameUpperCamel = "$amqpMethodNameFirstCharU$amqpMethod.getName().substring(1)" ) - public ${amqpClassNameUpperCamel}${amqpMethodNameUpperCamel}Body create${amqpClassNameUpperCamel}${amqpMethodNameUpperCamel}Body( + public ${amqpClassNameUpperCamel}${amqpMethodNameUpperCamel}Body create${amqpClassNameUpperCamel}${amqpMethodNameUpperCamel}Body( #foreach( $field in $amqpMethod.FieldList ) #if( $velocityCount == $amqpMethod.getFieldList().size() ) final $field.NativeType $field.Name @@ -166,9 +167,9 @@ public class MethodRegistry_$version.getMajor()_$version.getMinor() extends Meth final $field.NativeType $field.Name, #end #end - ) + ) { - return new ${amqpClassNameUpperCamel}${amqpMethodNameUpperCamel}BodyImpl( + return new ${amqpClassNameUpperCamel}${amqpMethodNameUpperCamel}BodyImpl( #foreach( $field in $amqpMethod.FieldList ) #if( $velocityCount == $amqpMethod.getFieldList().size() ) $field.Name @@ -176,18 +177,18 @@ public class MethodRegistry_$version.getMajor()_$version.getMinor() extends Meth $field.Name, #end #end - ); + ); } -#end - +#end + #end - - + + public ProtocolVersionMethodConverter getProtocolVersionMethodConverter() { return _protocolVersionConverter; - } + } } |