Clover coverage report - ActiveIO - 1.0
Coverage timestamp: Fri Apr 22 2005 14:27:22 PDT
file stats: LOC: 225   Methods: 18
NCLOC: 134   Classes: 4
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
OnePortAsynchChannelServer.java 62.5% 73.6% 66.7% 70.1%
coverage coverage
 1   
 /** 
 2   
  * 
 3   
  * Copyright 2004 Hiram Chirino
 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.oneport;
 19   
 
 20   
 import java.io.IOException;
 21   
 import java.net.URI;
 22   
 import java.util.Iterator;
 23   
 
 24   
 import org.activeio.AcceptListener;
 25   
 import org.activeio.AsynchChannel;
 26   
 import org.activeio.AsynchChannelListener;
 27   
 import org.activeio.AsynchChannelServer;
 28   
 import org.activeio.Channel;
 29   
 import org.activeio.FilterAsynchChannel;
 30   
 import org.activeio.FilterAsynchChannelServer;
 31   
 import org.activeio.Packet;
 32   
 import org.activeio.SynchChannel;
 33   
 import org.activeio.adapter.AsynchToSynchChannelAdapter;
 34   
 import org.activeio.adapter.SynchToAsynchChannelAdapter;
 35   
 import org.activeio.filter.PushbackSynchChannel;
 36   
 import org.activeio.packet.AppendedPacket;
 37   
 
 38   
 import EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap;
 39   
 
 40   
 /**
 41   
  * Allows multiple protocols share a single ChannelServer.  All protocols sharing the server 
 42   
  * must have a distinct magic number at the beging of the client's request.
 43   
  * 
 44   
  * TODO: handle the case where a client opens a connection but sends no data down the stream.  We need
 45   
  * to timeout that client.
 46   
  * 
 47   
  * @version $Revision$
 48   
  */
 49   
 final public class OnePortAsynchChannelServer extends FilterAsynchChannelServer {
 50   
     
 51   
     /**
 52   
      * The OnePortAsynchChannelServer listens for incoming connection
 53   
      * from a normal AsynchChannelServer.  This s the listner used 
 54   
      * to receive the accepted channels.
 55   
      */
 56   
     final private class OnePortAcceptListener implements AcceptListener {
 57   
         
 58  24
         public void onAccept(Channel channel) {
 59  24
             try {
 60  24
                 AsynchChannel asynchChannel = SynchToAsynchChannelAdapter.adapt(channel);
 61  24
                 ProtocolInspectingAsynchChannel inspector = new ProtocolInspectingAsynchChannel(asynchChannel);
 62  24
                 inspector.start();                
 63   
             } catch (IOException e) {
 64  0
                 onAcceptError(e);
 65   
             }                
 66   
         }
 67   
         
 68  0
         public void onAcceptError(IOException error) {
 69  0
             dispose();
 70   
         }
 71   
     }
 72   
 
 73   
     /**
 74   
      * This channel filter sniffs the first few bytes of the byte stream 
 75   
      * to see if a ProtocolRecognizer recognizes the protocol.  If it does not
 76   
      * it just closes the channel, otherwise the associated SubPortAsynchChannelServer
 77   
      * is notified that it accepted a channel.
 78   
      *
 79   
      */
 80   
     final private class ProtocolInspectingAsynchChannel extends FilterAsynchChannel {
 81   
         private Packet buffer;
 82   
 
 83  24
         public ProtocolInspectingAsynchChannel(AsynchChannel next) throws IOException {
 84  24
             super(next);
 85  24
             setAsynchChannelListener(new AsynchChannelListener() {
 86  30
                 public void onPacket(Packet packet) {
 87  30
                     if (buffer == null) {
 88  24
                         buffer = packet;
 89   
                     } else {
 90  6
                         buffer = AppendedPacket.join(buffer, packet);
 91   
                     }
 92  30
                     findMagicNumber();
 93   
                 }
 94   
 
 95  0
                 public void onPacketError(IOException error) {
 96  0
                     dispose();
 97   
                 }
 98   
             });
 99   
         }
 100   
 
 101  30
         private void findMagicNumber() {
 102  30
             for (Iterator iter = recognizerMap.keySet().iterator(); iter.hasNext();) {
 103  32
                 ProtocolRecognizer recognizer = (ProtocolRecognizer) iter.next();
 104  32
                 if (recognizer.recognizes(buffer.duplicate())) {
 105   
 
 106  12
                     if( UnknownRecognizer.UNKNOWN_RECOGNIZER == recognizer ) {
 107   
                         // Dispose the channel.. don't know what to do with it.
 108  0
                         dispose();
 109   
                     }
 110   
                     
 111  12
                     SubPortAsynchChannelServer onePort = (SubPortAsynchChannelServer) recognizerMap.get(recognizer);
 112  12
                     if( onePort == null ) {
 113   
                         // Dispose the channel.. don't know what to do with it.
 114  0
                         dispose();
 115   
                     }
 116   
 
 117   
                     // Once the magic number is found:
 118   
                     // Stop the channel so that a decision can be taken on what to
 119   
                     // do with the
 120   
                     // channel. When the channel is restarted, the buffered up
 121   
                     // packets wiil get
 122   
                     // delivered.
 123  12
                     try {
 124  12
                         stop(NO_WAIT_TIMEOUT);
 125  12
                         setAsynchChannelListener(null);
 126   
                     } catch (IOException e) {                        
 127  0
                         getAsynchChannelListener().onPacketError(e);
 128   
                     }
 129   
                     
 130  12
                     Channel channel = getNext();
 131  12
                     channel = AsynchToSynchChannelAdapter.adapt(channel);
 132  12
                     channel = new PushbackSynchChannel((SynchChannel) channel, buffer);
 133  12
                     channel = SynchToAsynchChannelAdapter.adapt(channel);
 134   
                     
 135  12
                     onePort.onAccept(channel);
 136  12
                     break;
 137   
                 }
 138   
             }
 139   
         }
 140   
     }    
 141   
 
 142   
     /**
 143   
      * Clients bind against the OnePortAsynchChannelServer and get 
 144   
      * SubPortAsynchChannelServer which can be used to accept connections.
 145   
      */
 146   
     final private class SubPortAsynchChannelServer implements AsynchChannelServer {
 147   
         
 148   
         private final ProtocolRecognizer recognizer;
 149   
         private AcceptListener acceptListener;
 150   
         private boolean started;
 151   
         
 152   
         /**
 153   
          * @param recognizer
 154   
          */
 155  36
         public SubPortAsynchChannelServer(ProtocolRecognizer recognizer) {
 156  36
             this.recognizer = recognizer;
 157   
         }
 158   
 
 159  36
         public void setAcceptListener(AcceptListener acceptListener) {
 160  36
             this.acceptListener = acceptListener;
 161   
         }
 162   
         
 163  0
         public URI getBindURI() {
 164  0
             return next.getBindURI();
 165   
         }
 166   
         
 167  12
         public URI getConnectURI() {
 168  12
             return next.getConnectURI();
 169   
         }
 170   
         
 171  36
         public void dispose() {
 172  36
             started = false;
 173  36
             recognizerMap.remove(recognizer);
 174   
         }
 175   
         
 176  36
         public void start() throws IOException {
 177  36
             started = true;
 178   
         }
 179  0
         public void stop(long timeout) throws IOException {
 180  0
             started = false;
 181   
         }
 182   
         
 183  12
         void onAccept(Channel channel) {
 184  12
             if( started && acceptListener!=null ) {
 185  12
                 acceptListener.onAccept(channel);
 186   
             } else {
 187   
                 // Dispose the channel.. don't know what to do with it.
 188  0
                 channel.dispose();
 189   
             }
 190   
         }
 191   
         
 192  0
         public Object narrow(Class target) {
 193  0
             if( target.isAssignableFrom(getClass()) ) {
 194  0
                 return this;
 195   
             }
 196  0
             return OnePortAsynchChannelServer.this.narrow(target);
 197   
         }    
 198   
         
 199   
     }
 200   
     
 201   
     
 202   
     private final ConcurrentHashMap recognizerMap = new ConcurrentHashMap();
 203   
 
 204  18
     public OnePortAsynchChannelServer(AsynchChannelServer server) throws IOException {
 205  18
         super(server);
 206  18
         super.setAcceptListener(new OnePortAcceptListener());
 207   
     }
 208   
     
 209  0
     public void setAcceptListener(AcceptListener acceptListener) {
 210  0
         throw new IllegalAccessError("Not supported");
 211   
     }    
 212   
     
 213  36
     public AsynchChannelServer bindAsynchChannel(ProtocolRecognizer recognizer) throws IOException {
 214   
         
 215  36
         if( recognizerMap.contains(recognizer) ) 
 216  0
             throw new IOException("That recognizer is allredy bound.");
 217   
         
 218  36
         SubPortAsynchChannelServer server = new SubPortAsynchChannelServer(recognizer);
 219  36
         Object old = recognizerMap.put(recognizer, server);
 220  36
         return server;
 221   
     }
 222   
     
 223   
     
 224   
 }
 225