Clover coverage report - ActiveIO - 1.0
Coverage timestamp: Fri Apr 22 2005 14:27:22 PDT
file stats: LOC: 228   Methods: 15
NCLOC: 141   Classes: 1
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover
 
 Source file Conditionals Statements Methods TOTAL
SynchToAsynchChannelAdapter.java 56.2% 66.2% 80% 65.2%
coverage coverage
 1   
 /** 
 2   
  * 
 3   
  * Copyright 2004 Protique Ltd
 4   
  * 
 5   
  * Licensed under the Apache License, Version 2.0 (the "License"); 
 6   
  * you may not use this file except in compliance with the License. 
 7   
  * You may obtain a copy of the License at 
 8   
  * 
 9   
  * http://www.apache.org/licenses/LICENSE-2.0
 10   
  * 
 11   
  * Unless required by applicable law or agreed to in writing, software
 12   
  * distributed under the License is distributed on an "AS IS" BASIS, 
 13   
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 14   
  * See the License for the specific language governing permissions and 
 15   
  * limitations under the License. 
 16   
  * 
 17   
  **/
 18   
 package org.activeio.adapter;
 19   
 
 20   
 import java.io.IOException;
 21   
 import java.io.InterruptedIOException;
 22   
 
 23   
 import org.activeio.AsynchChannel;
 24   
 import org.activeio.AsynchChannelListener;
 25   
 import org.activeio.Channel;
 26   
 import org.activeio.ChannelFactory;
 27   
 import org.activeio.Packet;
 28   
 import org.activeio.Service;
 29   
 import org.activeio.SynchChannel;
 30   
 import org.activeio.packet.EOSPacket;
 31   
 
 32   
 import EDU.oswego.cs.dl.util.concurrent.Executor;
 33   
 import EDU.oswego.cs.dl.util.concurrent.Latch;
 34   
 import EDU.oswego.cs.dl.util.concurrent.SynchronizedBoolean;
 35   
 
 36   
 /**
 37   
  * Adapts a {@see org.activeio.SynchChannel} so that it provides an 
 38   
  * {@see org.activeio.AsynchChannel} interface.  When this channel
 39   
  * is started, a background thread is used to poll the {@see org.activeio.SynchChannel}
 40   
  *  for packets comming up the channel which are then delivered to the 
 41   
  * {@see org.activeio.ChannelConsumer}.
 42   
  * 
 43   
  * @version $Revision$
 44   
  */
 45   
 final public class SynchToAsynchChannelAdapter implements AsynchChannel, Runnable {
 46   
 
 47   
     private final SynchronizedBoolean running = new SynchronizedBoolean(false);
 48   
     private final SynchChannel synchChannel;
 49   
     private final Executor executor;
 50   
     private AsynchChannelListener channelListener;
 51   
     private Latch doneLatch;
 52   
     
 53   
     
 54  44
     static public AsynchChannel adapt(Channel channel) {
 55  44
         return adapt(channel, ChannelFactory.DEFAULT_EXECUTOR);
 56   
     }
 57   
 
 58  46
     static public AsynchChannel adapt(Channel channel, Executor executor) {
 59   
         
 60   
         // It might not need adapting
 61  46
         if( channel instanceof AsynchChannel ) {
 62  4
             return (AsynchChannel) channel;
 63   
         }
 64   
         
 65   
         // Can we just just undo the adaptor
 66  41
         if( channel.getClass() == SynchToAsynchChannelAdapter.class ) {
 67  0
             return ((AsynchToSynchChannelAdapter)channel).getAsynchChannel();
 68   
         }
 69   
         
 70  41
         return new SynchToAsynchChannelAdapter((SynchChannel) channel, executor);
 71   
         
 72   
     }
 73   
 
 74   
     
 75   
     /**
 76   
      * @deprecated {@see #adapt(SynchChannel)}
 77   
      */
 78  0
     public SynchToAsynchChannelAdapter(SynchChannel synchChannel) {
 79  0
         this(synchChannel, ChannelFactory.DEFAULT_EXECUTOR);
 80   
     }
 81   
 
 82   
     /**
 83   
      * @deprecated {@see #adapt(SynchChannel, Executor)}
 84   
      */
 85  42
     public SynchToAsynchChannelAdapter(SynchChannel synchChannel, Executor executor) {
 86  42
         this.synchChannel = synchChannel;
 87  42
         this.executor = executor;
 88   
     }
 89   
 
 90  26
     synchronized public void start() throws IOException {
 91  26
         if (running.commit(false, true)) {
 92   
             
 93  26
             if (channelListener == null)
 94  0
                 throw new IllegalStateException("UpPacketListener must be set before object can be started.");
 95   
             
 96  26
             synchChannel.start();
 97   
 
 98  26
             try {
 99  26
                 doneLatch = new Latch();
 100  26
                 executor.execute(this);
 101   
             } catch (InterruptedException e) {
 102  0
                 throw new InterruptedIOException(e.getMessage());
 103   
             }
 104   
 
 105   
         }
 106   
     }
 107   
 
 108  22
     synchronized public void stop(long timeout) throws IOException {
 109  22
         if (running.commit(true, false)) {
 110  12
             try {
 111  12
                 if( timeout == NO_WAIT_TIMEOUT ) {
 112  12
                     synchChannel.stop(NO_WAIT_TIMEOUT);
 113  0
                 } else if( timeout == WAIT_FOREVER_TIMEOUT ) {
 114  0
                     doneLatch.acquire();
 115  0
                     synchChannel.stop(WAIT_FOREVER_TIMEOUT);
 116   
                 } else {
 117   
                     
 118  0
                     long start = System.currentTimeMillis();
 119  0
                     if( doneLatch.attempt(timeout) ) {
 120  0
                         timeout -= (System.currentTimeMillis() - start);
 121   
                     } else {
 122  0
                         timeout=0;
 123   
                     }
 124   
                     
 125  0
                     if( timeout <= 0 ) {
 126  0
                         synchChannel.stop(NO_WAIT_TIMEOUT);
 127   
                     } else {
 128  0
                         synchChannel.stop(timeout);
 129   
                     }
 130   
                 }
 131   
             } catch (IOException e) {
 132  0
                 throw e;
 133   
             } catch (Throwable e) {
 134  0
                 throw (IOException)new IOException("stop failed: " + e.getMessage()).initCause(e);
 135   
             }
 136   
         }
 137   
     }
 138   
 
 139   
     /**
 140   
      * reads packets from a Socket
 141   
      */
 142  26
     public void run() {
 143   
         
 144   
         // Change the thread name.
 145  26
         String oldName = Thread.currentThread().getName();        
 146  26
         Thread.currentThread().setName( synchChannel.toString() );        
 147  26
         try {
 148  26
             while (running.get()) {
 149  101
                 try {
 150  101
                     Packet packet = synchChannel.read(500);
 151  101
                     if( packet==null )
 152  54
                         continue;    
 153   
                     
 154  47
                     if( packet == EOSPacket.EOS_PACKET ) {
 155  14
                         channelListener.onPacket(packet);
 156  14
                         return;
 157   
                     }
 158   
                     
 159  33
                     if( packet.hasRemaining() ) {
 160  33
                         channelListener.onPacket(packet);
 161   
                     }
 162   
                     
 163   
                 } catch (IOException e) {
 164  0
                     channelListener.onPacketError(e);
 165   
                 } catch (Throwable e) {
 166  0
                     channelListener.onPacketError((IOException)new IOException("Unexpected Error: "+e).initCause(e));
 167   
                 }
 168   
             }
 169   
         } finally {
 170  26
             if( doneLatch!=null )
 171  26
                 doneLatch.release();
 172  26
             Thread.currentThread().setName(oldName);
 173   
         }
 174   
     }
 175   
 
 176   
     /**
 177   
      * @see org.activeio.AsynchChannel#setAsynchChannelListener(org.activeio.UpPacketListener)
 178   
      */
 179  38
     public void setAsynchChannelListener(AsynchChannelListener channelListener) {
 180  38
         if (running.get())
 181  0
             throw new IllegalStateException("Cannot change the UpPacketListener while the object is running.");
 182  38
         this.channelListener = channelListener;
 183   
     }
 184   
 
 185   
     /**
 186   
      * @see org.activeio.Channel#write(org.activeio.channel.Packet)
 187   
      */
 188  24
     public void write(org.activeio.Packet packet) throws IOException {
 189  24
         synchChannel.write(packet);
 190   
     }
 191   
 
 192   
     /**
 193   
      * @see org.activeio.Channel#flush()
 194   
      */
 195  10
     public void flush() throws IOException {
 196  10
         synchChannel.flush();
 197   
     }
 198   
 
 199   
     /**
 200   
      * @see org.activeio.Disposable#dispose()
 201   
      */
 202  10
     public void dispose() {
 203  10
         try {
 204  10
             stop(Service.NO_WAIT_TIMEOUT);
 205   
         } catch ( IOException ignore) {
 206   
         }
 207  10
         synchChannel.dispose();        
 208   
     }
 209   
 
 210  0
     public AsynchChannelListener getAsynchChannelListener() {
 211  0
         return channelListener;
 212   
     }
 213   
     
 214  8
     public Object narrow(Class target) {
 215  8
         if( target.isAssignableFrom(getClass()) ) {
 216  0
             return this;
 217   
         }
 218  8
         return synchChannel.narrow(target);
 219   
     }    
 220   
     
 221  16
     public SynchChannel getSynchChannel() {
 222  16
         return synchChannel;
 223   
     }
 224   
 
 225  0
     public String toString() {
 226  0
         return synchChannel.toString();
 227   
     }
 228   
 }