/*******************************************************************************
* Copyright (c) 2017 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:
* GoPivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.boot.launch.cli;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationType;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.core.ILaunchManager;
import org.osgi.framework.Version;
import org.osgi.framework.VersionRange;
import org.springframework.ide.eclipse.boot.core.cli.BootCliUtils;
import org.springframework.ide.eclipse.boot.core.cli.CloudCliUtils;
import org.springframework.ide.eclipse.boot.core.cli.install.IBootInstall;
import org.springframework.ide.eclipse.boot.launch.BootLaunchConfigurationDelegate;
import org.springframework.ide.eclipse.boot.launch.livebean.JmxBeanSupport;
import org.springframework.ide.eclipse.boot.launch.util.PortFinder;
import org.springframework.ide.eclipse.boot.util.Log;
/**
* Spring Cloud CLI service launch configuration
*
* @author Alex Boyko
*
*/
public class CloudCliServiceLaunchConfigurationDelegate extends BootCliLaunchConfigurationDelegate {
private static final VersionRange SPRING_CLOUD_CLI_JAVA_OPTS_FORMAT_CHANGE_VERSION_RANGE = new VersionRange("1.3.0");
public final static String TYPE_ID = "org.springframework.ide.eclipse.boot.launch.cloud.cli.service";
public final static String ATTR_CLOUD_SERVICE_ID = "local-cloud-service-id";
private List<String> getCloudCliServiceVmArguments(ILaunchConfiguration configuration, int jmxPort) {
List<String> vmArgs = new ArrayList<>();
EnumSet<JmxBeanSupport.Feature> enabled = BootLaunchConfigurationDelegate
.getEnabledJmxFeatures(configuration);
if (!enabled.isEmpty()) {
String enableLiveBeanArgs = JmxBeanSupport.jmxBeanVmArgs(jmxPort, enabled);
vmArgs.addAll(Arrays.asList(enableLiveBeanArgs.split("\n")));
}
if (BootLaunchConfigurationDelegate.supportsAnsiConsoleOutput()) {
vmArgs.add("-Dspring.output.ansi.enabled=always");
}
return vmArgs;
}
protected String[] getProgramArgs(IBootInstall bootInstall, ILaunch launch, ILaunchConfiguration configuration) {
try {
int jmxPort = getJmxPort(configuration);
// Set the JMX port for launch
launch.setAttribute(BootLaunchConfigurationDelegate.JMX_PORT, String.valueOf(jmxPort));
String serviceId = configuration.getAttribute(ATTR_CLOUD_SERVICE_ID, (String) null);
List<String> vmArgs = getCloudCliServiceVmArguments(configuration, jmxPort);
List<String> args = new ArrayList<>(3 + vmArgs.size());
args.add("cloud");
args.add(serviceId);
if (!vmArgs.isEmpty()) {
args.add("--");
args.add("--logging.level.org.springframework.cloud.launcher.deployer=DEBUG");
Version cloudCliVersion = CloudCliUtils.getVersion(bootInstall);
// Format of java options changes as of spring-cloud-cli 1.3.0
if (cloudCliVersion != null && SPRING_CLOUD_CLI_JAVA_OPTS_FORMAT_CHANGE_VERSION_RANGE.includes(cloudCliVersion)) {
args.add("--spring.cloud.launcher.deployables." + serviceId + ".properties.spring.cloud.deployer.local.javaOpts=" + String.join(",", vmArgs));
} else {
args.add("--spring.cloud.launcher.deployables." + serviceId + ".properties.JAVA_OPTS=" + String.join(",", vmArgs));
}
}
return args.toArray(new String[args.size()]);
} catch (Exception e) {
Log.log(e);
return new String[0];
}
}
private int getJmxPort(ILaunchConfiguration configuration) {
int port = 0;
try {
port = Integer.parseInt(BootLaunchConfigurationDelegate.getJMXPort(configuration));
} catch (Exception e) {
// ignore: bad data in launch config.
}
if (port == 0) {
try {
// slightly better than calling JmxBeanSupport.randomPort()
port = PortFinder.findFreePort();
} catch (IOException e) {
Log.log(e);
}
}
return port;
}
public static boolean isLocalCloudServiceLaunch(ILaunchConfiguration conf) {
try {
if (conf!=null) {
String type = conf.getType().getIdentifier();
return TYPE_ID.equals(type);
}
} catch (Exception e) {
Log.log(e);
}
return false;
}
public static ILaunchConfigurationWorkingCopy createLaunchConfig(String serviceId) throws CoreException {
ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();
ILaunchConfigurationType type = launchManager.getLaunchConfigurationType(TYPE_ID);
ILaunchConfigurationWorkingCopy config = type.newInstance(null, serviceId);
config.setAttribute(ATTR_CLOUD_SERVICE_ID, serviceId);
BootLaunchConfigurationDelegate.setEnableLiveBeanSupport(config, BootLaunchConfigurationDelegate.DEFAULT_ENABLE_LIVE_BEAN_SUPPORT);
BootLaunchConfigurationDelegate.setEnableLifeCycle(config, BootLaunchConfigurationDelegate.DEFAULT_ENABLE_LIFE_CYCLE);
BootLaunchConfigurationDelegate.setTerminationTimeout(config,""+BootLaunchConfigurationDelegate.DEFAULT_TERMINATION_TIMEOUT);
BootLaunchConfigurationDelegate.setJMXPort(config, ""+BootLaunchConfigurationDelegate.DEFAULT_JMX_PORT);
BootLaunchConfigurationDelegate.setEnableAnsiConsoleOutput(config, BootLaunchConfigurationDelegate.supportsAnsiConsoleOutput());
return config;
}
public static boolean canUseLifeCycle(ILaunch launch) {
ILaunchConfiguration conf = launch.getLaunchConfiguration();
return conf!=null && canUseLifeCycle(conf);
}
public static boolean canUseLifeCycle(ILaunchConfiguration conf) {
try {
if (!TYPE_ID.equals(conf.getType().getIdentifier())) {
return false;
}
IBootInstall bootInstall = BootCliUtils.getSpringBootInstall();
if (!SPRING_CLOUD_CLI_JAVA_OPTS_FORMAT_CHANGE_VERSION_RANGE.includes(Version.valueOf(BootCliUtils.getSpringBootInstall().getVersion()))) {
return false;
}
Version cloudCliVersion = CloudCliUtils.getVersion(bootInstall);
if (cloudCliVersion == null || !CloudCliUtils.CLOUD_CLI_JAVA_OPTS_SUPPORTING_VERSIONS.includes(cloudCliVersion)) {
return false;
}
return BootLaunchConfigurationDelegate.getEnableLifeCycle(conf);
} catch (Exception e) {
// Ignore
}
return false;
}
}