Package chrriis.dj.nativeswing.swtimpl.core

Source Code of chrriis.dj.nativeswing.swtimpl.core.OutProcessSocketsMessagingInterface$SWTOutProcessSocketsMessagingInterface

/*
* Christopher Deckers (chrriis@nextencia.net)
* http://www.nextencia.net
*
* See the file "readme.txt" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
package chrriis.dj.nativeswing.swtimpl.core;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;

import javax.swing.SwingUtilities;

import org.eclipse.swt.widgets.Display;

import chrriis.dj.nativeswing.swtimpl.Message;
import chrriis.dj.nativeswing.swtimpl.NSSystemPropertySWT;

/**
* @author Christopher Deckers
*/
abstract class OutProcessSocketsMessagingInterface extends MessagingInterface {

  public OutProcessSocketsMessagingInterface(boolean isNativeSide, Socket socket, boolean exitOnEndOfStream, int pid) {
    super(isNativeSide, pid);
    this.socket = socket;
    initialize(exitOnEndOfStream);
  }

  private ObjectOutputStream oos;
  private ObjectInputStream ois;

  @Override
  public void destroy() {
    setAlive(false);
    try {
      ois.close();
    } catch(Exception e) {
    }
  }

  private Socket socket;

  @Override
  protected void openChannel() {
    try {
      oos = new ObjectOutputStream(new BufferedOutputStream(socket.getOutputStream()) {
        @Override
        public synchronized void write(int b) throws IOException {
          super.write(b);
          oosByteCount++;
        }
        @Override
        public synchronized void write(byte[] b, int off, int len) throws IOException {
          super.write(b, off, len);
          oosByteCount += len;
        }
      });
      oos.flush();
      ois = new ObjectInputStream(new BufferedInputStream(socket.getInputStream()));
    } catch(IOException e) {
      throw new RuntimeException(e);
    }
  }

  @Override
  protected void closeChannel() {
    try {
      oos.close();
    } catch(Exception e) {
    }
    try {
      ois.close();
    } catch(Exception e) {
    }
    try {
      socket.close();
    } catch(Exception e) {
    }
    socket = null;
  }

  private static final int OOS_RESET_THRESHOLD;

  static {
    String maxByteCountProperty = NSSystemPropertySWT.INTERFACE_STREAMRESETTHRESHOLD.get();
    if(maxByteCountProperty != null) {
      OOS_RESET_THRESHOLD = Integer.parseInt(maxByteCountProperty);
    } else {
      OOS_RESET_THRESHOLD = 500000;
    }
  }

  private int oosByteCount;

  @Override
  protected void writeMessageToChannel(Message message) throws IOException {
    synchronized(oos) {
      oos.writeUnshared(message);
      oos.flush();
      // Messages are cached, so we need to reset() from time to time to clean the cache, or else we get an OutOfMemoryError.
      if(oosByteCount > OOS_RESET_THRESHOLD) {
        oos.reset();
        oosByteCount = 0;
      }
    }
  }

  @Override
  protected Message readMessageFromChannel() throws IOException, ClassNotFoundException {
    Object o = ois.readUnshared();
    if(o instanceof Message) {
      Message message = (Message)o;
      if(IS_DEBUGGING_MESSAGES) {
        System.err.println("RECV: " + SWTNativeInterface.getMessageID(message) + ", " + message);
      }
      return message;
    }
    System.err.println("Unknown message: " + o);
    return null;
  }

  static class SWTOutProcessSocketsMessagingInterface extends OutProcessSocketsMessagingInterface {

    private Display display;

    public SWTOutProcessSocketsMessagingInterface(Socket socket, final boolean exitOnEndOfStream, Display display, int pid) {
      super(true, socket, exitOnEndOfStream, pid);
      this.display = display;
    }

    @Override
    protected void asyncUIExec(Runnable runnable) {
      display.asyncExec(runnable);
    }

    @Override
    public boolean isUIThread() {
      return Thread.currentThread() == display.getThread();
    }

    @Override
    protected void terminate() {
      if(isNativeSide() && Boolean.parseBoolean(NSSystemPropertySWT.PEERVM_DEBUG_PRINTSTOPMESSAGE.get())) {
        System.err.println("Stopping peer VM #" + getPID());
      }
      super.terminate();
    }

  }

  static class SwingOutProcessSocketsMessagingInterface extends OutProcessSocketsMessagingInterface {

    private final Process process;

    public SwingOutProcessSocketsMessagingInterface(Socket socket, final boolean exitOnEndOfStream, Process process, int pid) {
      super(false, socket, exitOnEndOfStream, pid);
      this.process = process;
    }

    @Override
    protected void asyncUIExec(Runnable runnable) {
      SwingUtilities.invokeLater(runnable);
    }

    @Override
    public boolean isUIThread() {
      return SwingUtilities.isEventDispatchThread();
    }

    @Override
    public void destroy() {
      super.destroy();
      // It is unclear whether there is any benefit in waiting for the peer VM to be closed (I don't think of any conceptually).
      // However, a user seems to have an issue that is improved when doing so, so let's have this waiting conditional.
      if(process != null && Boolean.parseBoolean(NSSystemPropertySWT.INTERFACE_OUTPROCESS_SYNCCLOSING.get())) {
        while(true) {
          try {
            process.waitFor();
            break;
          } catch (InterruptedException e) {
          }
        }
      }
    }

  }

}
TOP

Related Classes of chrriis.dj.nativeswing.swtimpl.core.OutProcessSocketsMessagingInterface$SWTOutProcessSocketsMessagingInterface

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.