// Purpose.  Proxy design pattern
// 1. Create a "wrapper" for a remote, or expensive, or sensitive target
// 2. Encapsulate the complexity/overhead of the target in the wrapper
// 3. The client deals with the wrapper
// 4. The wrapper delegates to the target
// 5. To support plug-compatibility of wrapper and target, create an interface

import java.io.*;   import java.net.*;

interface SocketInterface {                // 5. To support plug-compatibility
   String readLine();                      //    between the wrapper and the
   void   writeLine( String str );         //    target, create an interface
   void   dispose(); }

public class ProxyDemo {
   public static void main( String[] args ) {
      SocketInterface socket = new SocketProxy( "127.0.0.1", 8189,
         args[0].equals("first") ? true : false );     // 3. The client deals
      String  str = null;                              //    with the wrapper
      boolean skip = true;
      while (true) {
         if (args[0].equals("second")  &&  skip) skip = ! skip;
         else {
            str = socket.readLine();
            System.out.println( "Receive - " + str );  // java ProxyDemo first
            if (str.equals("quit")) break;             // Receive - 123 456
         }                                             // Send ---- 234 567
         System.out.print( "Send ---- " );             // Receive - 345 678
         str = Read.aString();                         //
         socket.writeLine( str );                      // java ProxyDemo second
         if (str.equals("quit")) break;                // Send ---- 123 456
      }                                                // Receive - 234 567
      socket.dispose();                                // Send ---- 345 678
}  }

class SocketProxy implements SocketInterface { // 1. Create a "wrapper" for a
   private Socket         socket;              //    remote, or expensive, or
   private BufferedReader in;                  //    sensitive target
   private PrintWriter    out;

   public SocketProxy( String host, int port, boolean wait ) {
      try {
         if (wait) {
            ServerSocket server = new ServerSocket( port );
            socket = server.accept();           // 2. Encapsulate the complexi-
         } else                                 //    ty/overhead of the target
            socket = new Socket( host, port );  //    in the wrapper
         in  = new BufferedReader( new InputStreamReader(
                  socket.getInputStream()));
         out = new PrintWriter( socket.getOutputStream(), true );
      } catch( IOException e ) { e.printStackTrace(); }
   }
   public String readLine() {
      String str = null;
      try { str = in.readLine();
      } catch( IOException e ) { e.printStackTrace(); }
      return str;
   }
   public void writeLine( String str ) {
      out.println( str );             // 4. The wrapper delegates to the target
   }
   public void dispose() {
      try { socket.close();
      } catch( IOException e ) { e.printStackTrace(); }
}  }