/******************************************************************************* * Copyright (c) 2017 Rogue Wave Software Inc. and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Rogue Wave Software Inc. - initial implementation *******************************************************************************/ package org.eclipse.php.phpunit.model.connection; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; import java.util.Map; import org.apache.commons.lang3.StringUtils; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.ILaunch; import org.eclipse.debug.core.ILaunchesListener2; import org.eclipse.osgi.util.NLS; import org.eclipse.php.phpunit.PHPUnitMessages; import org.eclipse.php.phpunit.PHPUnitPlugin; import org.eclipse.php.phpunit.model.elements.PHPUnitElementManager; import org.eclipse.php.phpunit.ui.launch.PHPUnitLaunchUtils; import org.eclipse.php.phpunit.ui.view.PHPUnitView; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonSyntaxException; import com.google.gson.internal.LinkedTreeMap; public class PHPUnitConnectionListener implements Runnable, ILaunchesListener2 { protected ILaunch launch; protected int port = 0; protected ServerSocket serverSocket; protected Socket socket; private Thread listenThread; private Gson gson = new GsonBuilder().create(); public PHPUnitConnectionListener(final int port, final ILaunch launch) { this.port = port; this.launch = launch; } protected void handleReport(final Socket socket) { if (!PHPUnitLaunchUtils.isPHPUnitRunning()) { return; } try { final PHPUnitMessageParser parser = PHPUnitMessageParser.getInstance(); parser.clean(); parser.setDebugTarget(PHPUnitView.getDefault().getLaunch().getDebugTarget()); final BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); String line; parser.setInProgress(true); while ((line = reader.readLine()) != null && parser.isInProgress()) { try { processLine(line, parser); } catch (JsonSyntaxException e) { PHPUnitPlugin.log(e); } } } catch (final IOException e) { PHPUnitPlugin.log(e); } } private void processLine(String line, PHPUnitMessageParser parser) throws JsonSyntaxException { if (StringUtils.isEmpty(line) || line.charAt(0) != '{') { return; } Map<?, ?> value = gson.fromJson(line, LinkedTreeMap.class); parser.parseMessage(value, PHPUnitView.getDefault().getViewer()); PHPUnitView.getDefault().refresh(PHPUnitElementManager.getInstance().getRoot()); } @Override public void launchesAdded(final ILaunch[] launches) { // ignore } @Override public void launchesChanged(final ILaunch[] launches) { // ignore } @Override public void launchesRemoved(final ILaunch[] launches) { // ignore } @Override public void launchesTerminated(final ILaunch[] launches) { for (ILaunch launche : launches) if (launche == launch && launche.isTerminated()) { if (!PHPUnitMessageParser.getInstance().isInProgress()) { PHPUnitView.getDefault().stopRunning(true); } DebugPlugin.getDefault().getLaunchManager().removeLaunchListener(this); } } @Override public void run() { final ILaunch launch = PHPUnitView.getDefault().getLaunch(); int tries = 3; String message = PHPUnitMessages.PHPUnitView_Run_Error; do try { serverSocket = new ServerSocket(port, 1); serverSocket.setSoTimeout(5000); serverSocket.setReuseAddress(true); socket = serverSocket.accept(); handleReport(socket); } catch (final IOException e) { tries--; if (tries == 0) { PHPUnitPlugin.log(e); message = NLS.bind(PHPUnitMessages.PHPUnitView_Run_SocketError, port, e.getMessage()); } } finally { shutdown(false); } while ((tries > 0 && socket == null) || (!launch.isTerminated() && "debug".equals(launch.getLaunchMode()))); //$NON-NLS-1$ PHPUnitView.getDefault().stop(PHPUnitElementManager.getInstance().getRoot(), message); } public void shutdown(boolean terminateLaunch) { try { if (socket != null && !socket.isClosed()) { socket.close(); } } catch (final Exception e) { } try { if (serverSocket != null && !serverSocket.isClosed()) { serverSocket.close(); } } catch (final IOException e) { } if (terminateLaunch && launch != null && !launch.isTerminated()) { try { launch.terminate(); } catch (final DebugException e) { } } PHPUnitMessageParser.getInstance().setInProgress(false); } public void start() { listenThread = new Thread(this, "PHPUnit PHPUnitConnectionListener"); //$NON-NLS-1$ listenThread.start(); } }