View Javadoc

    1   //========================================================================
    2   //$Id: ChannelEndPoint.java,v 1.1 2005/10/05 14:09:38 janb Exp $
    3   //Copyright 2004-2005 Mort Bay Consulting Pty. 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   //http://www.apache.org/licenses/LICENSE-2.0
    9   //Unless required by applicable law or agreed to in writing, software
    10  //distributed under the License is distributed on an "AS IS" BASIS,
    11  //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  //See the License for the specific language governing permissions and
    13  //limitations under the License.
    14  //========================================================================
    15
    16  package org.mortbay.io.nio;
    17
    18  import java.io.IOException;
    19  import java.net.InetSocketAddress;
    20  import java.net.Socket;
    21  import java.nio.ByteBuffer;
    22  import java.nio.channels.ByteChannel;
    23  import java.nio.channels.GatheringByteChannel;
    24  import java.nio.channels.SelectableChannel;
    25  import java.nio.channels.SocketChannel;
    26
    27  import org.mortbay.io.Buffer;
    28  import org.mortbay.io.EndPoint;
    29  import org.mortbay.io.Portable;
    30  import org.mortbay.log.Log;
    31
    32
    33  /**
    34   * @author gregw
    35   *
    36   * To change the template for this generated type comment go to
    37   * Window - Preferences - Java - Code Generation - Code and Comments
    38   */
    39  public class ChannelEndPoint implements EndPoint
    40  {
    41      protected final ByteChannel _channel;
    42      protected final ByteBuffer[] _gather2=new ByteBuffer[2];
    43      protected final Socket _socket;
    44      protected final InetSocketAddress _local;
    45      protected final InetSocketAddress _remote;
    46
    47      /**
    48       *
    49       */
    50      public ChannelEndPoint(ByteChannel channel)
    51      {
    52          super();
    53          this._channel = channel;
    54          if (channel instanceof SocketChannel)
    55          {
    56              _socket=((SocketChannel)channel).socket();
    57              _local=(InetSocketAddress)_socket.getLocalSocketAddress();
    58              _remote=(InetSocketAddress)_socket.getRemoteSocketAddress();
    59          }
    60          else
    61          {
    62              _socket=null;
    63              _local=null;
    64              _remote=null;
    65          }
    66      }
    67
    68      public boolean isBlocking()
    69      {
    70          if (_channel instanceof SelectableChannel)
    71              return ((SelectableChannel)_channel).isBlocking();
    72          return true;
    73      }
    74
    75      public boolean blockReadable(long millisecs) throws IOException
    76      {
    77          return true;
    78      }
    79
    80      public boolean blockWritable(long millisecs) throws IOException
    81      {
    82          return true;
    83      }
    84
    85      /*
    86       * @see org.mortbay.io.EndPoint#isOpen()
    87       */
    88      public boolean isOpen()
    89      {
    90          return _channel.isOpen();
    91      }
    92
    93      /* (non-Javadoc)
    94       * @see org.eclipse.io.EndPoint#close()
    95       */
    96      public void shutdownOutput() throws IOException
    97      {
    98          if (_channel.isOpen() && _channel instanceof SocketChannel)
    99          {
    100             Socket socket= ((SocketChannel)_channel).socket();
    101             if (!socket.isClosed()&&!socket.isOutputShutdown())
    102                 socket.shutdownOutput();
    103         }
    104     }
    105
    106     /* (non-Javadoc)
    107      * @see org.eclipse.io.EndPoint#close()
    108      */
    109     public void close() throws IOException
    110     {
    111         if (_socket!=null && !_socket.isOutputShutdown())
    112             _socket.shutdownOutput();
    113         _channel.close();
    114     }
    115
    116     /* (non-Javadoc)
    117      * @see org.mortbay.io.EndPoint#fill(org.mortbay.io.Buffer)
    118      */
    119     public int fill(Buffer buffer) throws IOException
    120     {
    121         Buffer buf = buffer.buffer();
    122         int len=0;
    123         if (buf instanceof NIOBuffer)
    124         {
    125             NIOBuffer nbuf = (NIOBuffer)buf;
    126             ByteBuffer bbuf=nbuf.getByteBuffer();
    127             synchronized(nbuf)
    128             {
    129                 try
    130                 {
    131                     bbuf.position(buffer.putIndex());
    132                     len=_channel.read(bbuf);
    133                     if (len<0)
    134                         _channel.close();
    135                 }
    136                 finally
    137                 {
    138                     buffer.setPutIndex(bbuf.position());
    139                     bbuf.position(0);
    140                 }
    141             }
    142         }
    143         else
    144         {
    145             throw new IOException("Not Implemented");
    146         }
    147
    148         return len;
    149     }
    150
    151     /* (non-Javadoc)
    152      * @see org.mortbay.io.EndPoint#flush(org.mortbay.io.Buffer)
    153      */
    154     public int flush(Buffer buffer) throws IOException
    155     {
    156         Buffer buf = buffer.buffer();
    157         int len=0;
    158         if (buf instanceof NIOBuffer)
    159         {
    160             NIOBuffer nbuf = (NIOBuffer)buf;
    161             ByteBuffer bbuf=nbuf.getByteBuffer();
    162
    163             // TODO synchronize
    164             synchronized(bbuf)
    165             {
    166                 try
    167                 {
    168                     bbuf.position(buffer.getIndex());
    169                     bbuf.limit(buffer.putIndex());
    170                     len=_channel.write(bbuf);
    171                 }
    172                 finally
    173                 {
    174                     if (len>0)
    175                         buffer.skip(len);
    176                     bbuf.position(0);
    177                     bbuf.limit(bbuf.capacity());
    178                 }
    179             }
    180         }
    181         else if (buffer.array()!=null)
    182         {
    183             ByteBuffer b = ByteBuffer.wrap(buffer.array(), buffer.getIndex(), buffer.length());
    184             len=_channel.write(b);
    185             if (len>0)
    186                 buffer.skip(len);
    187         }
    188         else
    189         {
    190             throw new IOException("Not Implemented");
    191         }
    192         return len;
    193     }
    194
    195     /* (non-Javadoc)
    196      * @see org.mortbay.io.EndPoint#flush(org.mortbay.io.Buffer, org.mortbay.io.Buffer, org.mortbay.io.Buffer)
    197      */
    198     public int flush(Buffer header, Buffer buffer, Buffer trailer) throws IOException
    199     {
    200         int length=0;
    201
    202         Buffer buf0 = header==null?null:header.buffer();
    203         Buffer buf1 = buffer==null?null:buffer.buffer();
    204
    205         if (_channel instanceof GatheringByteChannel &&
    206             header!=null && header.length()!=0 && header instanceof NIOBuffer &&
    207             buffer!=null && buffer.length()!=0 && buffer instanceof NIOBuffer)
    208         {
    209             NIOBuffer nbuf0 = (NIOBuffer)buf0;
    210             ByteBuffer bbuf0=nbuf0.getByteBuffer();
    211             NIOBuffer nbuf1 = (NIOBuffer)buf1;
    212             ByteBuffer bbuf1=nbuf1.getByteBuffer();
    213
    214             synchronized(this)
    215             {
    216                 // We must sync because buffers may be shared (eg nbuf1 is likely to be cached content).
    217                 synchronized(bbuf0)
    218                 {
    219                     synchronized(bbuf1)
    220                     {
    221                         try
    222                         {
    223                             // Adjust position indexs of buf0 and buf1
    224                             bbuf0.position(header.getIndex());
    225                             bbuf0.limit(header.putIndex());
    226                             bbuf1.position(buffer.getIndex());
    227                             bbuf1.limit(buffer.putIndex());
    228
    229                             _gather2[0]=bbuf0;
    230                             _gather2[1]=bbuf1;
    231
    232                             // do the gathering write.
    233                             length=(int)((GatheringByteChannel)_channel).write(_gather2);
    234
    235                             int hl=header.length();
    236                             if (length>hl)
    237                             {
    238                                 header.clear();
    239                                 buffer.skip(length-hl);
    240                             }
    241                             else if (length>0)
    242                             {
    243                                 header.skip(length);
    244                             }
    245
    246                         }
    247                         finally
    248                         {
    249                             // adjust buffer 0 and 1
    250                             if (!header.isImmutable())
    251                                 header.setGetIndex(bbuf0.position());
    252                             if (!buffer.isImmutable())
    253                                 buffer.setGetIndex(bbuf1.position());
    254
    255                             bbuf0.position(0);
    256                             bbuf1.position(0);
    257                             bbuf0.limit(bbuf0.capacity());
    258                             bbuf1.limit(bbuf1.capacity());
    259                         }
    260                     }
    261                 }
    262             }
    263         }
    264         else
    265         {
    266             if (header!=null)
    267             {
    268                 if (buffer!=null && buffer.length()>0 && header.space()>buffer.length())
    269                 {
    270                     header.put(buffer);
    271                     buffer.clear();
    272                 }
    273                 if (trailer!=null && trailer.length()>0 && header.space()>trailer.length())
    274                 {
    275                     header.put(trailer);
    276                     trailer.clear();
    277                 }
    278             }
    279
    280             // flush header
    281             if (header!=null && header.length()>0)
    282                 length=flush(header);
    283
    284             // flush buffer
    285             if ((header==null || header.length()==0) &&
    286                  buffer!=null && buffer.length()>0)
    287                 length+=flush(buffer);
    288
    289             // flush trailer
    290             if ((header==null || header.length()==0) &&
    291                 (buffer==null || buffer.length()==0) &&
    292                  trailer!=null && trailer.length()>0)
    293                 length+=flush(trailer);
    294         }
    295
    296         return length;
    297     }
    298
    299     /**
    300      * @return Returns the channel.
    301      */
    302     public ByteChannel getChannel()
    303     {
    304         return _channel;
    305     }
    306
    307
    308     /* ------------------------------------------------------------ */
    309     /*
    310      * @see org.mortbay.io.EndPoint#getLocalAddr()
    311      */
    312     public String getLocalAddr()
    313     {
    314         if (_socket==null)
    315             return null;
    316
    317        if (_local==null || _local.getAddress()==null || _local.getAddress().isAnyLocalAddress())
    318            return Portable.ALL_INTERFACES;
    319
    320         return _local.getAddress().getHostAddress();
    321     }
    322
    323     /* ------------------------------------------------------------ */
    324     /*
    325      * @see org.mortbay.io.EndPoint#getLocalHost()
    326      */
    327     public String getLocalHost()
    328     {
    329         if (_socket==null)
    330             return null;
    331
    332        if (_local==null || _local.getAddress()==null || _local.getAddress().isAnyLocalAddress())
    333            return Portable.ALL_INTERFACES;
    334
    335         return _local.getAddress().getCanonicalHostName();
    336     }
    337
    338     /* ------------------------------------------------------------ */
    339     /*
    340      * @see org.mortbay.io.EndPoint#getLocalPort()
    341      */
    342     public int getLocalPort()
    343     {
    344         if (_socket==null)
    345             return 0;
    346         if (_local==null)
    347             return -1;
    348         return _local.getPort();
    349     }
    350
    351     /* ------------------------------------------------------------ */
    352     /*
    353      * @see org.mortbay.io.EndPoint#getRemoteAddr()
    354      */
    355     public String getRemoteAddr()
    356     {
    357         if (_socket==null)
    358             return null;
    359
    360         if (_remote==null)
    361             return null;
    362         return _remote.getAddress().getHostAddress();
    363     }
    364
    365     /* ------------------------------------------------------------ */
    366     /*
    367      * @see org.mortbay.io.EndPoint#getRemoteHost()
    368      */
    369     public String getRemoteHost()
    370     {
    371         if (_socket==null)
    372             return null;
    373
    374         if (_remote==null)
    375             return null;
    376         return _remote.getAddress().getCanonicalHostName();
    377     }
    378
    379     /* ------------------------------------------------------------ */
    380     /*
    381      * @see org.mortbay.io.EndPoint#getRemotePort()
    382      */
    383     public int getRemotePort()
    384     {
    385         if (_socket==null)
    386             return 0;
    387
    388         if (_remote==null)
    389             return -1;
    390         return _remote==null?-1:_remote.getPort();
    391     }
    392
    393     /* ------------------------------------------------------------ */
    394     /*
    395      * @see org.mortbay.io.EndPoint#getConnection()
    396      */
    397     public Object getTransport()
    398     {
    399         return _channel;
    400     }
    401
    402     /* ------------------------------------------------------------ */
    403     public void flush()
    404         throws IOException
    405     {
    406     }
    407
    408     /* ------------------------------------------------------------ */
    409     public boolean isBufferingInput()
    410     {
    411         return false;
    412     }
    413
    414     /* ------------------------------------------------------------ */
    415     public boolean isBufferingOutput()
    416     {
    417         return false;
    418     }
    419
    420     /* ------------------------------------------------------------ */
    421     public boolean isBufferred()
    422     {
    423         return false;
    424     }
    425 }