⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 servicereader.java

📁 移动Agent编程工具Naplet
💻 JAVA
字号:

/*
 * @<#> ServiceReader.java, version 0.0.1, 1/1/2001
 *
 * THIS PROGRAM IS FREE SOFTWARE; YOU CAN DISTRIBUTE IT AND/OR
 * MODIFY IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE 
 * AS PUBLISHED BY THE FREE SOFTWARE FOUNDATION.
 *
 * THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
 * BUT WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE 
 * GNU GENERAL PUBLIC LICENSE FOR MORE DETAILS.
 *
 * Copyright (c) 2000 Wayne State University. All Rights Reserved.
 */

package naplet.serviceChannel;

import java.io.Reader;
import java.io.IOException;

import naplet.*;
import naplet.serviceChannel.*;

/**
 * Piped character-input streams between naplets and priviledged services.
 * The pipe is non-symmetric in the sense that a ServiceReader may exist 
 * alone and can be connected by NapletWriters at different instances. 
 * By contrast, Java's built-in <code>PipedReader</code> and <code>PipedWriter
 * </code> are symmetric and they are dependent on each other.  
 *
 * @version 0.0.1, 1/1/2001
 * @author C. Xu (czxu@yahoo.com)
 */

public class ServiceReader extends Reader 
{
      boolean closedByServer = false;
      boolean closedByNaplet = false;
      boolean connected = false;

      /**
       * Non-symmetric piped reader/writer. The ServiceReader is a primary 
       * party which can exist alone and be connected to secondary parties 
       * at different time.
       */

      NapletWriter source = null;
	
      static final int PIPE_SIZE = 1024;
      char buffer[] = new char[PIPE_SIZE];

      /**
       * The position index pair in the circular buffer at which the 
       * next character of data will be stored by NapletWriter and read
       * by ServiceReader. <code>in&lt;0</code> implies the buffer is empty, 
       * <code>in==out</code> implies the buffer is full
       */
      int in = -1;
      int out = 0;

      /**
       * Creates a <code>ServiceReader</code> with an open input channel. 
       * A <code>NapletWriter<code> must be connected to it before it 
       * being used.  
       *
       * @see     naplet.ServiceReader#connect(naplet.NapletWriter)
       */
      public ServiceReader( )
      {
      }

      /**
       * Connect a NapletWriter to the ServiceReader. 
       * If the sink is already connected, throws an IOException
       */
      protected void connect( NapletWriter src )
	 throws IOException 
      {
	 if ( src == null )
	 {
            throw new NullPointerException( );
	 }

	 synchronized ( lock )
	 {
	    while ( connected )
	    {
	       if ( source == null )
	       {
		  throw new NapletInternalError( 
		     "Null source in a connected pipe" );
	       }

	       if ( source.equals( src ) ) 
	       { 
		  closedByNaplet = false;
		  in = -1;
		  out = 0;
	       } // Already connected by itself
	       else 
	       {
		  System.out.println( "Already connected by other source" );
		 
		  try 
		  {
		     lock.wait( );
		  } 
		  catch ( InterruptedException ie ) 
		  {
		     throw new java.io.InterruptedIOException( );
		  }
	       }
	    }

	    source = src;
	    src.sink = this;
	    in = -1;
	    out = 0;
	    connected = true;

	    // To release any waiting ServiceReader
	    lock.notifyAll();
	 }
      }

 
      /**
       * Close this piped stream and releases any system resources 
       * associated with the stream. A question is how to safely close 
       * the pipe. 
       *
       * @exception  IOException  if an I/O error occurs.
       */
      public void close( )  
	 throws IOException 
      {
	 synchronized ( lock )
	 {
	    in = -1;
	    closedByServer = true;
	    connected = false;
	 }	
      }

      /**
       * Write a char of data to the pipe stream.  If the pipe is unconnected,
       * an IOException is thrown. This method will block if the pipe is full.
       */
      void receive( int c )
	 throws IOException
      {
	 synchronized ( lock )
	 {
	    if ( !connected )
	    {
	       if ( closedByServer )
	       {
		  throw new IOException( "Service is discontinued" );
	       }
	       else
	       {
		  throw new IOException( "Pipe not connected" );
	       }
            } 
			
	    while ( in == out ) 
	    {    
	       // Pipe is full, wake up readers and wait for it.
	       lock.notifyAll( );	
	    
	       try
	       {
		  lock.wait( );
	       } 
	       catch ( InterruptedException ex )
	       {
		  throw new java.io.InterruptedIOException( );
	       }

	       if ( closedByServer )
	       {
		  throw new IOException( "Pipe closed by Server" );
	       }
	    }

	    if ( in < 0 ) 
	    {			
	       in = 0;
	    }  // If pipe is empty

	    buffer[in++] = ( char ) c;

	    if ( in >= buffer.length ) 
	    {
	       in = 0;
	    }

	    lock.notifyAll();
	 }
      }

      /**
       * Receives data into an array of characters.  This method will
       * block until some input is available. 
       */
      void receive( char c[], int off, int len )
	 throws IOException
      {
	 synchronized ( lock )
	 {
	    if ( !connected )
	    {
	       if ( closedByServer )
	       {
		  throw new IOException( "Service is discontinued" );
	       }
	       else
	       {
		  throw new IOException( "Pipe not connected" );
	       }
            } 
	    
	    while ( --len >= 0 )
	    {
	       while ( in == out ) 
	       {    
		  // Pipe is full, wake up readers and wait for it.
		  lock.notifyAll( );	
	    
		  try
		  {
		     lock.wait( );
		  } 
		  catch ( InterruptedException ex )
		  {
		     throw new java.io.InterruptedIOException( );
		  }

		  if ( closedByServer )
		  {
		     throw new IOException( "Pipe closed by Server" );
		  }
	       }

	       if ( in < 0 ) 
	       {			
		  in = 0;
	       }  // If pipe is empty

	       buffer[in++] = c[off++];

	       if ( in >= buffer.length ) 
	       {
		  in = 0;
	       }
	    }

	    lock.notifyAll( );
	 }
      }

      /**
       * Reads the next character of data from this piped stream.
       * If no character is available because the end of the stream 
       * has been reached, the value <code>-1</code> is returned. 
       * 
       * This method blocks until input data is available, the end of
       * the stream is detected, or an exception is thrown. 
       *
       * If a thread was providing data characters
       * to the connected piped writer, but
       * the  thread is no longer alive, then an
       * <code>IOException</code> is thrown.
       *
       * @return     the next character of data, or <code>-1</code> 
       *             if the end of the stream is reached.
       * @exception  IOException  if the pipe is broken.
       */
      public int read( )
	 throws IOException
      {
	 synchronized ( lock )
	 {
	    while ( !connected && !closedByNaplet )
	    {
	       // If pipe is initially disconnected  
	       try
	       { 
		  lock.wait( );
	       } 
	       catch ( InterruptedException ie )
	       {
		  throw new java.io.InterruptedIOException( );
	       }
	    }

	    // If pipe is connected, or recently disconnected by Naplet
	    // Since a recently disconnected pipe may not be empty, it must
	    // be flushed before it is reset to the initial condition.
	    try 
	    { 
	       while ( in < 0 )
	       {  	
		  if ( !connected && closedByNaplet )
		  { 
		     // reset to initial state 
		     closedByNaplet = false; 
		     return -1;
		  }
		  
		  lock.notifyAll( );
		  lock.wait();
	       }  // The pipe is empty 		
	    }
	    catch ( InterruptedException ie )
	    {
	       close( );
	       throw new java.io.InterruptedIOException( 
		  "Service is discontinued" );
	    }
	    
	    int ret = buffer[out++];
	    if ( out >= buffer.length ) 
	    {
	       out = 0;
	    }

	    if ( in == out )
	    {   
	       in = -1;		
	       out = 0;
	    }  // Pipe is now empty 

	    lock.notifyAll( );
	    
	    return ret;
	 }
      }

      /**
       * Reads up to <code>len</code> characters of data from this piped
       * stream into an array of characters. Less than <code>len</code> 
       * characters will be read if the end of the data stream is reached. 
       * This method blocks until at least one character of input is 
       * available. If a thread was providing data characters to the 
       * connected piped output, but the thread is no longer alive, then 
       * an <code>IOException</code> is thrown.
       *
       * @param      cbuf     the buffer into which the data is read.
       * @param      off   the start offset of the data.
       * @param      len   the maximum number of characters read.
       * @return     the total number of characters read into the buffer, or
       *             <code>-1</code> if there is no more data because the end 
       *             of the stream has been reached.
       * @exception  IOException  if an I/O error occurs.
       */
      public int read( char cbuf[], int off, int len ) 
	 throws IOException 
      {
	 if ( ( off < 0 ) || ( off >= cbuf.length ) || ( len < 0 )
	      || ( ( off + len ) > cbuf.length ) || ( ( off + len ) < 0 ) )
	 {
	    throw new IndexOutOfBoundsException( "Index out of boundary" );
	 } 

	 /* possibly wait on the first character */
	 int c = read( );		
	 if ( c < 0 )
	 {
	    return -1;
	 }
	 else if ( len == 0 )
	 {
	    return 0;
	 }
	 
	 cbuf[off] = ( char ) c;

	 int rlen = 1;
	 synchronized ( lock )
	 {
	    while ( ( in >= 0 ) && ( --len > 0 ) )
	    {
	       cbuf[off + rlen] = buffer[out++];
	       rlen++;
	       
	       if ( out >= buffer.length )
	       {
		  out = 0;
	       }

	       if ( in == out )
	       {  
		  in = -1;
		  out = 0;
	       }  // Empty buffer
	    }

	    lock.notifyAll( );
	 }
	 
	 return rlen;
      }

      public synchronized boolean ready( )
	 throws IOException
      { 
	 if ( closedByServer )
	 {
	    throw new IOException( "Pipe closed" );
	 }

	 if ( in < 0 )
	 {
	    return false;
	 }

	 int count;
	 if ( out < in )
	 {
	    count = in - out;
	 }
	 else
	 {
	    count = buffer.length - out - in;
	 }

	 return ( count > 0 );
      }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -