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 ByteChannel _channel;
    42      protected ByteBuffer[] _gather2=new ByteBuffer[2];
    43      protected Socket _socket;
    44      protected InetSocketAddress _local;
    45      protected InetSocketAddress _remote;
    46
    47      /**
    48       *
    49       */
    50      public ChannelEndPoint(ByteChannel channel)
    51      {
    52          super();
    53          this._channel = channel;
    54          if (channel instanceof SocketChannel)
    55              _socket=((SocketChannel)channel).socket();
    56      }
    57
    58      public boolean isBlocking()
    59      {
    60          if (_channel instanceof SelectableChannel)
    61              return ((SelectableChannel)_channel).isBlocking();
    62          return true;
    63      }
    64
    65      public boolean blockReadable(long millisecs) throws IOException
    66      {
    67          return true;
    68      }
    69
    70      public boolean blockWritable(long millisecs) throws IOException
    71      {
    72          return true;
    73      }
    74
    75      /*
    76       * @see org.mortbay.io.EndPoint#isOpen()
    77       */
    78      public boolean isOpen()
    79      {
    80          return _channel.isOpen();
    81      }
    82
    83      /* (non-Javadoc)
    84       * @see org.mortbay.io.EndPoint#close()
    85       */
    86      public void close() throws IOException
    87      {
    88          if (_channel.isOpen())
    89          {
    90              try
    91              {
    92                  if (_channel instanceof SocketChannel)
    93                  {
    94                      // TODO - is this really required?
    95                      Socket socket= ((SocketChannel)_channel).socket();
    96                      if (!socket.isClosed() && !socket.isOutputShutdown())
    97                          socket.shutdownOutput();
    98                  }
    99              }
    100             catch(IOException e)
    101             {
    102                 Log.ignore(e);
    103             }
    104             catch(UnsupportedOperationException e)
    105             {
    106                 Log.ignore(e);
    107             }
    108             finally
    109             {
    110                 _channel.close();
    111             }
    112         }
    113     }
    114
    115     /* (non-Javadoc)
    116      * @see org.mortbay.io.EndPoint#fill(org.mortbay.io.Buffer)
    117      */
    118     public int fill(Buffer buffer) throws IOException
    119     {
    120         Buffer buf = buffer.buffer();
    121         int len=0;
    122         if (buf instanceof NIOBuffer)
    123         {
    124             NIOBuffer nbuf = (NIOBuffer)buf;
    125             ByteBuffer bbuf=nbuf.getByteBuffer();
    126             synchronized(nbuf)
    127             {
    128                 try
    129                 {
    130                     bbuf.position(buffer.putIndex());
    131                     len=_channel.read(bbuf);
    132                     if (len<0)
    133                         _channel.close();
    134                 }
    135                 finally
    136                 {
    137                     buffer.setPutIndex(bbuf.position());
    138                     bbuf.position(0);
    139                 }
    140             }
    141         }
    142         else
    143         {
    144             throw new IOException("Not Implemented");
    145         }
    146
    147         return len;
    148     }
    149
    150     /* (non-Javadoc)
    151      * @see org.mortbay.io.EndPoint#flush(org.mortbay.io.Buffer)
    152      */
    153     public int flush(Buffer buffer) throws IOException
    154     {
    155         Buffer buf = buffer.buffer();
    156         int len=0;
    157         if (buf instanceof NIOBuffer)
    158         {
    159             NIOBuffer nbuf = (NIOBuffer)buf;
    160             ByteBuffer bbuf=nbuf.getByteBuffer();
    161
    162             // TODO synchronize
    163             synchronized(bbuf)
    164             {
    165                 try
    166                 {
    167                     bbuf.position(buffer.getIndex());
    168                     bbuf.limit(buffer.putIndex());
    169                     len=_channel.write(bbuf);
    170                 }
    171                 finally
    172                 {
    173                     if (len>0)
    174                         buffer.skip(len);
    175                     bbuf.position(0);
    176                     bbuf.limit(bbuf.capacity());
    177                 }
    178             }
    179         }
    180         else if (buffer.array()!=null)
    181         {
    182             ByteBuffer b = ByteBuffer.wrap(buffer.array(), buffer.getIndex(), buffer.length());
    183             len=_channel.write(b);
    184             if (len>0)
    185                 buffer.skip(len);
    186         }
    187         else
    188         {
    189             throw new IOException("Not Implemented");
    190         }
    191         return len;
    192     }
    193
    194     /* (non-Javadoc)
    195      * @see org.mortbay.io.EndPoint#flush(org.mortbay.io.Buffer, org.mortbay.io.Buffer, org.mortbay.io.Buffer)
    196      */
    197     public int flush(Buffer header, Buffer buffer, Buffer trailer) throws IOException
    198     {
    199         int length=0;
    200
    201         Buffer buf0 = header==null?null:header.buffer();
    202         Buffer buf1 = buffer==null?null:buffer.buffer();
    203
    204         if (_channel instanceof GatheringByteChannel &&
    205             header!=null && header.length()!=0 && header instanceof NIOBuffer &&
    206             buffer!=null && buffer.length()!=0 && buffer instanceof NIOBuffer)
    207         {
    208             NIOBuffer nbuf0 = (NIOBuffer)buf0;
    209             ByteBuffer bbuf0=nbuf0.getByteBuffer();
    210             NIOBuffer nbuf1 = (NIOBuffer)buf1;
    211             ByteBuffer bbuf1=nbuf1.getByteBuffer();
    212
    213             synchronized(this)
    214             {
    215                 // We must sync because buffers may be shared (eg nbuf1 is likely to be cached content).
    216                 synchronized(bbuf0)
    217                 {
    218                     synchronized(bbuf1)
    219                     {
    220                         try
    221                         {
    222                             // Adjust position indexs of buf0 and buf1
    223                             bbuf0.position(header.getIndex());
    224                             bbuf0.limit(header.putIndex());
    225                             bbuf1.position(buffer.getIndex());
    226                             bbuf1.limit(buffer.putIndex());
    227
    228                             _gather2[0]=bbuf0;
    229                             _gather2[1]=bbuf1;
    230
    231                             // do the gathering write.
    232                             length=(int)((GatheringByteChannel)_channel).write(_gather2);
    233
    234                             int hl=header.length();
    235                             if (length>hl)
    236                             {
    237                                 header.clear();
    238                                 buffer.skip(length-hl);
    239                             }
    240                             else if (length>0)
    241                             {
    242                                 header.skip(length);
    243                             }
    244
    245                         }
    246                         finally
    247                         {
    248                             // adjust buffer 0 and 1
    249                             if (!header.isImmutable())
    250                                 header.setGetIndex(bbuf0.position());
    251                             if (!buffer.isImmutable())
    252                                 buffer.setGetIndex(bbuf1.position());
    253
    254                             bbuf0.position(0);
    255                             bbuf1.position(0);
    256                             bbuf0.limit(bbuf0.capacity());
    257                             bbuf1.limit(bbuf1.capacity());
    258                         }
    259                     }
    260                 }
    261             }
    262         }
    263         else
    264         {
    265             // TODO - consider copying buffers buffer and trailer into header if there is space!
    266
    267             // flush header
    268             if (header!=null && header.length()>0)
    269                 length=flush(header);
    270
    271             // flush buffer
    272             if ((header==null || header.length()==0) &&
    273                  buffer!=null && buffer.length()>0)
    274                 length+=flush(buffer);
    275
    276             // flush trailer
    277             if ((header==null || header.length()==0) &&
    278                 (buffer==null || buffer.length()==0) &&
    279                  trailer!=null && trailer.length()>0)
    280                 length+=flush(trailer);
    281         }
    282
    283         return length;
    284     }
    285
    286     /**
    287      * @return Returns the channel.
    288      */
    289     public ByteChannel getChannel()
    290     {
    291         return _channel;
    292     }
    293
    294
    295     /* ------------------------------------------------------------ */
    296     /*
    297      * @see org.mortbay.io.EndPoint#getLocalAddr()
    298      */
    299     public String getLocalAddr()
    300     {
    301         if (_socket==null)
    302             return null;
    303
    304         if (_local==null)
    305             _local=(InetSocketAddress)_socket.getLocalSocketAddress();
    306
    307        if (_local==null || _local.getAddress()==null || _local.getAddress().isAnyLocalAddress())
    308            return Portable.ALL_INTERFACES;
    309
    310         return _local.getAddress().getHostAddress();
    311     }
    312
    313     /* ------------------------------------------------------------ */
    314     /*
    315      * @see org.mortbay.io.EndPoint#getLocalHost()
    316      */
    317     public String getLocalHost()
    318     {
    319         if (_socket==null)
    320             return null;
    321
    322         if (_local==null)
    323             _local=(InetSocketAddress)_socket.getLocalSocketAddress();
    324
    325        if (_local==null || _local.getAddress()==null || _local.getAddress().isAnyLocalAddress())
    326            return Portable.ALL_INTERFACES;
    327
    328         return _local.getAddress().getCanonicalHostName();
    329     }
    330
    331     /* ------------------------------------------------------------ */
    332     /*
    333      * @see org.mortbay.io.EndPoint#getLocalPort()
    334      */
    335     public int getLocalPort()
    336     {
    337         if (_socket==null)
    338             return 0;
    339
    340         if (_local==null)
    341             _local=(InetSocketAddress)_socket.getLocalSocketAddress();
    342         if (_local==null)
    343             return -1;
    344         return _local.getPort();
    345     }
    346
    347     /* ------------------------------------------------------------ */
    348     /*
    349      * @see org.mortbay.io.EndPoint#getRemoteAddr()
    350      */
    351     public String getRemoteAddr()
    352     {
    353         if (_socket==null)
    354             return null;
    355
    356         if (_remote==null)
    357             _remote=(InetSocketAddress)_socket.getRemoteSocketAddress();
    358
    359         if (_remote==null)
    360             return null;
    361         return _remote.getAddress().getHostAddress();
    362     }
    363
    364     /* ------------------------------------------------------------ */
    365     /*
    366      * @see org.mortbay.io.EndPoint#getRemoteHost()
    367      */
    368     public String getRemoteHost()
    369     {
    370         if (_socket==null)
    371             return null;
    372
    373         if (_remote==null)
    374             _remote=(InetSocketAddress)_socket.getRemoteSocketAddress();
    375
    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             _remote=(InetSocketAddress)_socket.getRemoteSocketAddress();
    390
    391         return _remote==null?-1:_remote.getPort();
    392     }
    393
    394     /* ------------------------------------------------------------ */
    395     /*
    396      * @see org.mortbay.io.EndPoint#getConnection()
    397      */
    398     public Object getTransport()
    399     {
    400         return _channel;
    401     }
    402
    403     /* ------------------------------------------------------------ */
    404     public void flush()
    405         throws IOException
    406     {
    407     }
    408
    409     /* ------------------------------------------------------------ */
    410     public boolean isBufferingInput()
    411     {
    412         return false;
    413     }
    414
    415     /* ------------------------------------------------------------ */
    416     public boolean isBufferingOutput()
    417     {
    418         return false;
    419     }
    420
    421     /* ------------------------------------------------------------ */
    422     public boolean isBufferred()
    423     {
    424         return false;
    425     }
    426 }