/******************************************************************************* * Copyright (c) 2013 Pivotal Software, Inc. * 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: * Pivotal Software, Inc. - initial API and implementation *******************************************************************************/ package org.springframework.ide.eclipse.boot.dash.devtools; import org.eclipse.core.resources.IProject; import org.eclipse.debug.core.ILaunch; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.IStreamListener; import org.eclipse.debug.core.model.IDebugTarget; import org.eclipse.debug.core.model.IProcess; import org.eclipse.debug.core.model.IStreamMonitor; import org.springframework.ide.eclipse.boot.core.BootActivator; import org.springframework.ide.eclipse.boot.core.BootPropertyTester; import org.springframework.ide.eclipse.boot.dash.model.BootDashElement; import org.springframework.ide.eclipse.boot.dash.model.BootProjectDashElementFactory; import org.springframework.ide.eclipse.boot.dash.model.BootProjectDashElement; import org.springframework.ide.eclipse.boot.dash.model.LocalBootDashModel; import org.springframework.ide.eclipse.boot.launch.BootLaunchConfigurationDelegate; import org.springframework.ide.eclipse.boot.util.ProcessTracker; import org.springframework.ide.eclipse.boot.util.ProcessTracker.ProcessListener; import org.springsource.ide.eclipse.commons.livexp.ui.Disposable; /** * Responsible for 'poking' local boot dash elements when they need to refresh port info * after boot devtools does an in-place restart of an app. * <p> * As devtools autonously refreshes an app without any involvement of Eclipse... the only way we * can see that something happened to the process is by watching the process's output. * <p> * A DevtoolsPortRefresher uses a 'ProcessTracker' to attach an output monitor to any local process * that is being started and corresponds to a local boot dash element with devtools enabled. * * @author Kris De Volder */ public class DevtoolsPortRefresher implements Disposable, ProcessListener { private ProcessTracker processTracker; private BootProjectDashElementFactory elementFactory; public DevtoolsPortRefresher(LocalBootDashModel localBootDashModel, BootProjectDashElementFactory elementFactory) { processTracker = new ProcessTracker(this); this.elementFactory = elementFactory; } @Override public void dispose() { processTracker.dispose(); } @Override public void debugTargetCreated(ProcessTracker tracker, IDebugTarget target) { IProcess process = target.getProcess(); if (process!=null) { // may be null. E.g. for CF debug targets there's no local process attached to debug target. processCreated(tracker, process); } } @Override public void processCreated(ProcessTracker tracker, IProcess process) { final BootProjectDashElement element = getElementFor(process); if (element!=null) { process.getStreamsProxy().getOutputStreamMonitor().addListener(new IStreamListener() { public void streamAppended(String text, IStreamMonitor monitor) { if (text.contains("started on port")) { element.refreshLivePorts(); } } }); } } /** * Gets the element this process is related to, if the element is 'interesting'. * @return The element or null (if there's no corresponding element or its not 'interesting') */ private BootProjectDashElement getElementFor(IProcess process) { ILaunch launch = process.getLaunch(); try { if (launch!=null) { ILaunchConfiguration conf = launch.getLaunchConfiguration(); if (conf!=null && conf.getType().getIdentifier().equals(BootLaunchConfigurationDelegate.TYPE_ID)) { IProject p = BootLaunchConfigurationDelegate.getProject(conf); if (p!=null && BootPropertyTester.hasDevtools(p)) { BootDashElement e = elementFactory.createOrGet(p); if (BootPropertyTester.hasDevtools(p)) { if (e instanceof BootProjectDashElement) { // this test should always succeed but check it anyway return (BootProjectDashElement) e; } } } } } } catch (Exception e) { BootActivator.log(e); } return null; } @Override public void debugTargetTerminated(ProcessTracker tracker, IDebugTarget target) { //don't care } @Override public void processTerminated(ProcessTracker tracker, IProcess process) { //don't care } }