/*
* Copyright 2010-2012 Amazon Technologies, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://aws.amazon.com/apache2.0
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
* OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and
* limitations under the License.
*/
package com.amazonaws.eclipse.elasticbeanstalk.server.ui.configEditor.basic;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.UpdateValueStrategy;
import org.eclipse.core.databinding.conversion.IConverter;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.core.databinding.observable.value.IValueChangeListener;
import org.eclipse.core.databinding.observable.value.ValueChangeEvent;
import org.eclipse.jface.databinding.swt.SWTObservables;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
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 com.amazonaws.eclipse.elasticbeanstalk.Environment;
import com.amazonaws.eclipse.elasticbeanstalk.server.ui.configEditor.EnvironmentConfigDataModel;
import com.amazonaws.services.elasticbeanstalk.model.ConfigurationOptionDescription;
/**
* Human readable editor for container / jvm options
*/
public class ContainerConfigEditorSection extends HumanReadableConfigEditorSection {
private static final Map<String, String> humanReadableNames = new HashMap<String, String>();
static {
humanReadableNames.put("Xms", "Initial JVM Heap Size (-Xms argument)");
humanReadableNames.put("Xmx", "Maximum JVM Heap Size (-Xmx argument)");
humanReadableNames.put("XX:MaxPermSize", "Maximum JVM PermGen Size (-XX:MaxPermSize argument)");
humanReadableNames.put("JVM Options", "Additional Tomcat JVM command line options");
humanReadableNames.put("LogPublicationControl", "Enable log file rotation to Amazon S3");
}
private static final String[] fieldOrder = new String[] { "Xms", "Xmx", "XX:MaxPermSize", "JVM Options", "LogPublicationControl"};
public ContainerConfigEditorSection(BasicEnvironmentConfigEditorPart basicEnvironmentConfigurationEditorPart, EnvironmentConfigDataModel model, Environment environment, DataBindingContext bindingContext) {
super(basicEnvironmentConfigurationEditorPart, model, environment, bindingContext);
}
@Override
protected Map<String, String> getHumanReadableNames() {
return humanReadableNames;
}
@Override
protected String[] getFieldOrder() {
return fieldOrder;
}
@Override
protected String getSectionName() {
return "Container / JVM Options";
}
@Override
protected String getSectionDescription() {
return "These settings control command-line options for " + "your container and the underlying JVM.";
}
@Override
protected void createSectionControls(Composite composite) {
super.createSectionControls(composite);
createDebugEnablementControl(composite);
}
private void createDebugEnablementControl(Composite composite) {
final Button enablement = toolkit.createButton(composite, "Enable remote debugging", SWT.CHECK);
GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, false);
layoutData.horizontalSpan = 2;
enablement.setLayoutData(layoutData);
final Label portLabel = toolkit.createLabel(composite, "Remote debugging port:");
portLabel.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false));
final Text portText = toolkit.createText(composite, "");
layoutTextField(portText);
ConfigurationOptionDescription jvmOptions = null;
for ( ConfigurationOptionDescription opt : options ) {
if ( "JVM Options".equals(opt.getName()) ) {
jvmOptions = opt;
break;
}
}
if ( jvmOptions == null )
throw new RuntimeException("Couldn't determine JVM options");
/*
* These bindings are complicated because we don't copy the value across
* directly. Instead, we modify the JVM options string (or respond to
* modification of it).
*/
final IObservableValue jvmOptionsObservable = model.observeEntry(jvmOptions);
final IObservableValue textObservable = SWTObservables.observeText(portText, SWT.Modify);
final IObservableValue enablementObservable = SWTObservables.observeSelection(enablement);
IValueChangeListener listener = new IValueChangeListener() {
public void handleValueChange(ValueChangeEvent event) {
portText.setEnabled((Boolean) enablementObservable.getValue());
portLabel.setEnabled((Boolean) enablementObservable.getValue());
}
};
enablementObservable.addValueChangeListener(listener);
setupBindingsForDebugPort(jvmOptionsObservable, textObservable);
setupBindingsForDebugEnablement(jvmOptionsObservable, enablementObservable);
listener.handleValueChange(null);
}
protected void setupBindingsForDebugEnablement(final IObservableValue jvmOptionsObservable,
final IObservableValue enablementObservable) {
UpdateValueStrategy debugEnabledModelToTarget = new UpdateValueStrategy(
UpdateValueStrategy.POLICY_UPDATE);
UpdateValueStrategy debugEnabledTargetToModel = new UpdateValueStrategy(
UpdateValueStrategy.POLICY_UPDATE);
debugEnabledModelToTarget.setConverter(new IConverter() {
public Object getToType() {
return Boolean.class;
}
public Object getFromType() {
return String.class;
}
public Object convert(Object fromObject) {
return ((String)fromObject).contains("-Xdebug");
}
});
debugEnabledTargetToModel.setConverter(new IConverter() {
public Object getToType() {
return String.class;
}
public Object getFromType() {
return Boolean.class;
}
public Object convert(Object fromObject) {
String currentOptions = (String) jvmOptionsObservable.getValue();
if ( (Boolean) fromObject ) {
if ( !currentOptions.contains("-Xdebug") ) {
currentOptions += " " + "-Xdebug";
}
} else {
Matcher matcher = Pattern.compile("-Xdebug").matcher(currentOptions);
if ( matcher.find() )
currentOptions = matcher.replaceFirst("");
matcher = Pattern.compile("-Xrunjdwp:\\S+").matcher(currentOptions);
if ( matcher.find() )
currentOptions = matcher.replaceFirst("");
}
return currentOptions;
}
});
bindingContext.bindValue(enablementObservable, jvmOptionsObservable, debugEnabledTargetToModel,
debugEnabledModelToTarget).updateModelToTarget();
}
protected void setupBindingsForDebugPort(final IObservableValue jvmOptionsObservable,
final IObservableValue textObservable) {
UpdateValueStrategy portTargetToModel = new UpdateValueStrategy(
UpdateValueStrategy.POLICY_UPDATE);
portTargetToModel.setConverter(new IConverter() {
public Object getToType() {
return String.class;
}
public Object getFromType() {
return String.class;
}
public Object convert(Object fromObject) {
String debugPort = (String) fromObject;
String currentOptions = (String) jvmOptionsObservable.getValue();
if ( debugPort != null && debugPort.length() > 0 ) {
if ( !currentOptions.contains("-Xrunjdwp:") ) {
currentOptions += " " + "-Xrunjdwp:transport=dt_socket,address=" + debugPort
+ ",server=y,suspend=n";
} else {
Matcher matcher = Pattern.compile("(-Xrunjdwp:\\S*address=)\\d+").matcher(currentOptions);
if ( matcher.find() )
currentOptions = matcher.replaceFirst(matcher.group(1) + debugPort);
}
} else {
Matcher matcher = Pattern.compile("-Xrunjdwp:\\S+").matcher(currentOptions);
if ( matcher.find() )
currentOptions = matcher.replaceFirst("");
}
return currentOptions;
}
});
UpdateValueStrategy portModelToTarget = new UpdateValueStrategy(
UpdateValueStrategy.POLICY_UPDATE);
portModelToTarget.setConverter(new IConverter() {
public Object getToType() {
return String.class;
}
public Object getFromType() {
return String.class;
}
public Object convert(Object fromObject) {
String debugPort = Environment.getDebugPort((String) fromObject);
if (debugPort != null)
return debugPort;
return "";
}
});
bindingContext.bindValue(textObservable, jvmOptionsObservable, portTargetToModel, portModelToTarget)
.updateModelToTarget();
}
}