blob: fc26a475743fa52c684d036c9c13fd8cd51cc939 [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.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.SocketException;
import java.nio.channels.AsynchronousCloseException;
import java.nio.channels.SocketChannel;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.m2m.qvt.oml.debug.core.QVTODebugCore;
import org.eclipse.m2m.qvt.oml.debug.core.vm.protocol.VMRequest;
import org.eclipse.m2m.qvt.oml.debug.core.vm.protocol.VMResponse;
import org.eclipse.m2m.qvt.oml.debug.core.vm.protocol.VMTerminateRequest;
abstract class AbstractRequestProcessor {
private boolean fTerminated;
private InputStream fRequestStream;
private OutputStream fResponseStream;
private Socket fRequestSocket;
public AbstractRequestProcessor(Socket requestSocket) throws IOException {
if (requestSocket == null || !requestSocket.isConnected()
|| requestSocket.isClosed()) {
throw new IllegalArgumentException("Socket not connected or closed"); //$NON-NLS-1$
}
if(requestSocket.getChannel() == null) {
throw new IllegalArgumentException("Requires a socket with open channel"); //$NON-NLS-1$
}
fRequestStream = new BufferedInputStream(requestSocket.getInputStream());
fResponseStream = new BufferedOutputStream(requestSocket.getOutputStream());
fRequestSocket = requestSocket;
fTerminated = false;
}
public void run() throws IOException {
ObjectInputStream requestObjects = null;
ObjectOutputStream responseObjects = null;
try {
responseObjects = new ObjectOutputStream(fResponseStream);
// Note: blocks until the first request => object input stream reads the header
requestObjects = new ObjectInputStream(fRequestStream);
while (!fTerminated) {
VMResponse response;
VMRequest request;
Object rawRequest;
try {
rawRequest = requestObjects.readObject();
} catch (AsynchronousCloseException e) {
// continue to check if we have been interrupted
continue;
} catch (SocketException e) {
// FIXME - ??
e.printStackTrace();
fTerminated = true;
break;
} catch (IOException e) {
if(e instanceof EOFException) {
QVTODebugCore.TRACE.trace("VM Server - Client disconnected, going to shutdown");
fTerminated = true;
break;
}
// TODO - traces should see that logged exception
rawRequest = null;
QVTODebugCore.log(e);
} catch (ClassNotFoundException e) {
rawRequest = null;
// could not unmarshall request, just report an fError
// TODO - invalid request
response = VMResponse.createERROR();
}
request = validateRequestObject(rawRequest);
if (request != null) {
try {
response = processRequest(request);
} catch(CoreException e) {
System.err.println(e.getStatus());
fTerminated = true;
break;
}
} else {
// TODO invalid request
response = VMResponse.createERROR();
}
try {
responseObjects.writeObject(response);
responseObjects.flush();
} catch (IOException e) {
reportSendReponseError(response, e);
}
if (request instanceof VMTerminateRequest) {
// time to exit request processing
fTerminated = true;
break;
}
} // request processing loop
} finally {
// Note: object streams close the underlying I/O streams
if (responseObjects != null) {
SocketUtil.close(responseObjects);
}
if (requestObjects != null) {
SocketUtil.close(requestObjects);
}
}
}
protected void postTerminate() {
// do nothing
}
protected abstract VMResponse processRequest(VMRequest request) throws CoreException;
private VMRequest validateRequestObject(Object rawRequest) {
if (rawRequest instanceof VMRequest == false) {
QVTODebugCore.TRACE.trace("Invalid VM request: " + rawRequest); //$NON-NLS-1$
return null;
}
return (VMRequest) rawRequest;
}
private void reportSendReponseError(VMResponse response, IOException e) {
QVTODebugCore.TRACE.catching(VMServer.class, "sendResponse", e); //$NON-NLS-1$
QVTODebugCore.log(e);
}
public void terminate() {
synchronized (this) {
fTerminated = true;
SocketChannel channel = fRequestSocket.getChannel();
assert channel != null;
// interrupt the socket channel
try {
channel.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}