blob: 350b79187fd9d131640cc167fd70214e8460aa3c [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2018 xored software, Inc. and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* xored software, Inc. - initial API and Implementation
* xored software, Inc. - remove DLTKDebugPlugin preferences dependency (Alex Panchenko)
*******************************************************************************/
package org.eclipse.dltk.internal.debug.core.model;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.dltk.dbgp.DbgpServer;
import org.eclipse.dltk.dbgp.IDbgpServerListener;
import org.eclipse.dltk.dbgp.IDbgpSession;
import org.eclipse.dltk.dbgp.IDbgpSessionInfo;
import org.eclipse.dltk.dbgp.IDbgpThreadAcceptor;
import org.eclipse.dltk.dbgp.internal.IDbgpTerminationListener;
import org.eclipse.dltk.debug.core.DLTKDebugPlugin;
import org.eclipse.dltk.debug.core.DLTKDebugPreferenceConstants;
import org.eclipse.dltk.debug.core.IDbgpService;
public class DbgpService
implements IDbgpService, IDbgpTerminationListener, IDbgpServerListener {
private static final int FROM_PORT = 10000;
private static final int TO_PORT = 50000;
protected static final int SERVER_SOCKET_TIMEOUT = 500;
protected static final int CLIENT_SOCKET_TIMEOUT = 10000000;
private DbgpServer server;
private final Map<String, IDbgpThreadAcceptor> acceptors = Collections
.synchronizedMap(new HashMap<>());
private int serverPort;
private void stopServer() {
if (server != null) {
try {
server.removeTerminationListener(this);
server.setListener(null);
server.requestTermination();
try {
server.waitTerminated();
} catch (InterruptedException e) {
DLTKDebugPlugin.log(e);
}
} finally {
server = null;
}
}
}
private void startServer(int port) {
serverPort = port;
server = createServer(port);
server.addTerminationListener(this);
server.setListener(this);
server.start();
}
protected DbgpServer createServer(int port) {
return new DbgpServer(port, CLIENT_SOCKET_TIMEOUT);
}
private void restartServer(int port) {
stopServer();
startServer(port);
}
public DbgpService(int port) {
if (port == DLTKDebugPreferenceConstants.DBGP_AVAILABLE_PORT) {
port = DbgpServer.findAvailablePort(FROM_PORT, TO_PORT);
}
startServer(port);
}
public void shutdown() {
stopServer();
}
@Override
public int getPort() {
return serverPort;
}
/**
* Waits until the socket is actually started using the default timeout.
*
* @return <code>true</code> if socket was successfully started and
* <code>false</code> otherwise.
*/
public boolean waitStarted() {
return server != null && server.waitStarted();
}
/**
* Waits until the socket is actually started using specified timeout.
*
* @return <code>true</code> if socket was successfully started and
* <code>false</code> otherwise.
*/
public boolean waitStarted(long timeout) {
return server != null && server.waitStarted(timeout);
}
// Acceptors
@Override
public void registerAcceptor(String id, IDbgpThreadAcceptor acceptor) {
acceptors.put(id, acceptor);
}
@Override
public IDbgpThreadAcceptor unregisterAcceptor(String id) {
return acceptors.remove(id);
}
public void restart(int newPort) {
if (newPort != DLTKDebugPreferenceConstants.DBGP_AVAILABLE_PORT) {
// Only restart if concrete port specified
restartServer(newPort);
}
}
// IDbgpTerminationListener
@Override
public void objectTerminated(Object object, Exception e) {
if (e != null) {
DLTKDebugPlugin.log(e);
final Job job = new Job(Messages.DbgpService_ServerRestart) {
@Override
protected IStatus run(IProgressMonitor monitor) {
restartServer(serverPort);
return Status.OK_STATUS;
}
};
job.schedule(2000);
}
}
@Override
public boolean available() {
return true;
}
// INewDbgpServerListener
@Override
public void clientConnected(IDbgpSession session) {
final IDbgpSessionInfo info = session.getInfo();
if (info != null) {
final IDbgpThreadAcceptor acceptor = acceptors
.get(info.getIdeKey());
if (acceptor != null) {
acceptor.acceptDbgpThread(session, new NullProgressMonitor());
} else {
session.requestTermination();
}
}
}
}