/******************************************************************************* * Copyright (c) 2015, 2017 Pivotal, 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, Inc. - initial API and implementation *******************************************************************************/ package org.springframework.ide.eclipse.boot.launch.livebean; import java.util.EnumSet; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; import org.springframework.ide.eclipse.boot.launch.livebean.JmxBeanSupport.Feature; import org.springframework.ide.eclipse.boot.launch.util.DelegatingLaunchConfigurationTabSection; import org.springsource.ide.eclipse.commons.livexp.core.LiveExpression; import org.springsource.ide.eclipse.commons.livexp.core.LiveVariable; import org.springsource.ide.eclipse.commons.livexp.core.ValidationResult; import org.springsource.ide.eclipse.commons.livexp.core.ValueListener; import org.springsource.ide.eclipse.commons.livexp.ui.IPageWithSections; import org.springsource.ide.eclipse.commons.livexp.ui.UIConstants; import org.springsource.ide.eclipse.commons.livexp.ui.WizardPageSection; /** * LaunchTabSection that enables LiveBean graph support by adding required * VM and program arguments. * * @author Kris De Volder */ public class EnableJmxSection extends DelegatingLaunchConfigurationTabSection { private static final boolean DEBUG = false;//(""+Platform.getLocation()).contains("kdvolder"); private static void debug(String string) { if (DEBUG) { System.out.println(string); } } static class UI extends WizardPageSection { private Button jmxCheckbox; private Button liveBeanCheckbox; private Button lifeCycleCheckbox; private Text portWidget; private EnableJmxFeaturesModel model; private Text terminationTimeoutWidget; public UI(IPageWithSections owner, EnableJmxFeaturesModel model) { super(owner); this.model = model; } @Override public void createContents(Composite page) { Composite composite = new Composite(page, SWT.NONE); composite.setLayout(GridLayoutFactory.fillDefaults().numColumns(3).create()); jmxCheckbox = new Button(composite, SWT.CHECK); jmxCheckbox.setText("Enable JMX"); jmxCheckbox.setToolTipText(computeTooltipText( "Enables JMX. This is required for Live Bean support and Life Cycle Management." + "It also allows STS to access information about request-mappings on your app. "+ "Adds these vm args:\n", Feature.JMX)); String portToolTip = "The port used for communicating with JMX beans (0 means STS should pick the port automatically on startup). " + "The same port is used/shared by both 'Life Cycle Management' and the 'Live Beans Graph'"; final Label label = new Label(composite, SWT.NONE); label.setText("Port:"); portWidget = new Text(composite, SWT.BORDER); GridDataFactory.fillDefaults().hint(UIConstants.fieldLabelWidthHint(portWidget, 7), SWT.DEFAULT) .applyTo(portWidget); label.setToolTipText(portToolTip); portWidget.setToolTipText(portToolTip); composite = new Composite(page, SWT.NONE); GridLayout layout = GridLayoutFactory.fillDefaults().numColumns(3).margins(0, 0).create(); layout.marginLeft = UIConstants.fieldLabelWidthHint(label, 4); composite.setLayout(layout); liveBeanCheckbox = new Button(composite, SWT.CHECK); liveBeanCheckbox.setText("Enable Live Bean support."); liveBeanCheckbox.setToolTipText(computeTooltipText( "Enables support for Live Beans Graph View by adding vm args:\n", Feature.LIVE_BEAN_GRAPH)); GridDataFactory.fillDefaults().span(3, 1).applyTo(liveBeanCheckbox); lifeCycleCheckbox = new Button(composite, SWT.CHECK); lifeCycleCheckbox.setText("Enable Life Cycle Management."); lifeCycleCheckbox.setToolTipText(computeTooltipText( "Requires Boot 1.3.0. Allows Boot Dashboard View to track 'STARTING' state of Boot Apps; allows STS to ask Boot Apps to shutdown nicely. " + "Adds these vm args: \n", Feature.LIFE_CYCLE)); final Label terminationTimeoutLabel = new Label(composite, SWT.NONE); terminationTimeoutLabel.setText("Termination timeout (ms):"); terminationTimeoutWidget = new Text(composite, SWT.BORDER); GridDataFactory.fillDefaults().hint(UIConstants.fieldLabelWidthHint(terminationTimeoutWidget, 7), SWT.DEFAULT) .applyTo(terminationTimeoutWidget); terminationTimeoutWidget.setToolTipText("How long STS should wait, after asking Boot App nicely to stop, before attemptting to kill the process more forcibly."); model.jmxEnabled.addListener((exp, enable) -> { portWidget.setEnabled(enable); liveBeanCheckbox.setEnabled(enable); lifeCycleCheckbox.setEnabled(enable); label.setEnabled(enable); terminationTimeoutLabel.setEnabled(enable); }); model.lifeCycleEnabled.addListener(new ValueListener<Boolean>() { @Override public void gotValue(LiveExpression<Boolean> exp, Boolean value) { terminationTimeoutWidget.setEnabled(value); } }); connectCheckbox(model.jmxEnabled, jmxCheckbox); connectCheckbox(model.liveBeanEnabled, liveBeanCheckbox); connectCheckbox(model.lifeCycleEnabled, lifeCycleCheckbox); connectTextWidget(model.port, portWidget); connectTextWidget(model.terminationTimeout, terminationTimeoutWidget); } private static void connectTextWidget(final LiveVariable<String> model, final Text widget) { model.addListener(new ValueListener<String>() { public void gotValue(LiveExpression<String> exp, String value) { String oldValue = widget.getText(); if (!oldValue.equals(value)) { widget.setText(value); } } }); widget.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { model.setValue(widget.getText()); } }); } private String computeTooltipText(String baseMsg, Feature feature) { if (feature==Feature.JMX) { return baseMsg + JmxBeanSupport.jmxBeanVmArgs("${jmxPort}", EnumSet.of(feature)); } else { return baseMsg + feature.vmArg; } } @Override public LiveExpression<ValidationResult> getValidator() { return model.getValidator(); } } public EnableJmxSection(IPageWithSections owner, EnableJmxFeaturesModel model) { super(owner, model, new UI(owner, model)); } private static void connectCheckbox(final LiveVariable<Boolean> checkedState, final Button widget) { final String name = widget.getText(); checkedState.addListener(new ValueListener<Boolean>() { public void gotValue(LiveExpression<Boolean> exp, Boolean value) { boolean enable = value!=null && value; debug("Widget '"+name+"' <- "+enable); widget.setSelection(enable); } }); widget.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { boolean enable = widget.getSelection(); debug("Model '"+name+"' <- "+enable); checkedState.setValue(enable); } }); } }