blob: 7de0de4b6568cd9d303e01e8ace14427f0c290e3 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2018 R.Dvorak and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Radek Dvorak - initial API and implementation
*******************************************************************************/
package org.eclipse.m2m.qvt.oml.debug.core.app;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.m2m.qvt.oml.debug.core.DebugOptions;
import org.eclipse.m2m.qvt.oml.debug.core.QVTODebugCore;
import org.eclipse.m2m.qvt.oml.debug.core.vm.IQVTOVirtualMachineShell;
import org.eclipse.m2m.qvt.oml.debug.core.vm.protocol.VMEvent;
import org.eclipse.m2m.qvt.oml.debug.core.vm.protocol.VMTerminateEvent;
class VMEventDispatcher {
interface TerminationListener {
void terminated();
}
private final class DispatchJob implements Runnable {
private final Object startLock;
private final int fPort;
private boolean fReady;
private boolean fRunning;
DispatchJob(int port) {
this.startLock = new Object();
fPort = port;
fReady = false;
fRunning = false;
}
public void run() {
QVTODebugCore.TRACE.trace(DebugOptions.VM,
"VM Server Event Dispatcher started");
ObjectOutputStream eventStream = null;
ServerSocket serverSocket = null;
Socket eventSocket = null;
try {
synchronized (startLock) {
fReady = true;
startLock.notify();
}
serverSocket = new ServerSocket(fPort);
eventSocket = serverSocket.accept();
QVTODebugCore.TRACE.trace(DebugOptions.VM,
"VM Server Event Dispatcher accepted connection");
eventStream = new ObjectOutputStream(eventSocket.getOutputStream());
doRun(eventStream);
} catch(IOException e) {
e.printStackTrace();
// TODO - failed to initialize
QVTODebugCore.log(e);
} finally {
if(eventStream != null) {
SocketUtil.close(eventStream);
}
if(eventSocket != null) {
SocketUtil.close(eventSocket);
}
if(serverSocket != null) {
SocketUtil.close(serverSocket);
}
}
}
private void doRun(ObjectOutputStream eventStream) {
IQVTOVirtualMachineShell vm;
// FIXME
try {
vm = fVMProvider.getVM();
} catch (CoreException e) {
// Note: we are not to report this issues, just one of the clients waiting for
// the VM initialization on background
QVTODebugCore.TRACE.trace(DebugOptions.VM,
"VM Server Event dispatcher exiting, VM failed not available"); //$NON-NLS-1$
return;
}
fRunning = true;
while (fRunning) {
VMEvent event = null;
try {
event = vm.readVMEvent();
} catch (IOException e) {
QVTODebugCore.TRACE.trace(DebugOptions.VM,
"VM Server Event dispatcher interrupted"); //$NON-NLS-1$
}
if (event != null) {
QVTODebugCore.TRACE.trace(DebugOptions.VM,
"VM Server - sending VM event: " + event); //$NON-NLS-1$
try {
eventStream.writeObject(event);
eventStream.flush();
} catch (IOException e) {
// TODO
e.printStackTrace();
}
}
if(event == null || event instanceof VMTerminateEvent) {
// Note: VMTerminate has already been sent, we can exit
fRunning = false;
fReady = false;
terminated();
continue;
}
}
QVTODebugCore.TRACE.trace(DebugOptions.VM,
"VM Server Event dispather terminated"); //$NON-NLS-1$
}
private void waitToReachAccept() {
synchronized (startLock) {
while(!fReady) {
try {
startLock.wait();
} catch (InterruptedException e) {
// nothing
}
}
}
}
}
private VMProvider fVMProvider;
private Thread fDispatchThread;
private DispatchJob fDispatchJob;
private TerminationListener fTerminationListener;
VMEventDispatcher(VMProvider vmProvider, int port, TerminationListener listener) {
fDispatchJob = new DispatchJob(port);
fTerminationListener = listener;
fVMProvider = vmProvider;
}
protected void terminated() {
if(fTerminationListener != null) {
try {
fTerminationListener.terminated();
} catch(Throwable e) {
e.printStackTrace();
}
}
}
void start() {
synchronized (this) {
if(fDispatchThread != null) {
throw new IllegalStateException("Dispatcher already started"); //$NON-NLS-1$
}
fDispatchThread = new Thread(fDispatchJob, "QVTO Srv-VMEvent dispatch"); //$NON-NLS-1$
}
fDispatchThread.setDaemon(true);
fDispatchThread.start();
fDispatchJob.waitToReachAccept();
QVTODebugCore.TRACE.trace(DebugOptions.VM,
"VM Server Event dispatcher ready"); //$NON-NLS-1$
}
boolean joinTermination(long timeOut) {
try {
fDispatchThread.join(timeOut);
} catch (InterruptedException e) {
Thread.interrupted();
}
return !fDispatchThread.isAlive();
}
}