Skip to content

Commit

Permalink
[eclipse] Make the embedding runner able to use the command line -D d…
Browse files Browse the repository at this point in the history
…efinitions.

Signed-off-by: Stéphane Galland <galland@arakhne.org>
  • Loading branch information
gallandarakhneorg committed Dec 5, 2020
1 parent 0d5f64d commit df956d6
Show file tree
Hide file tree
Showing 7 changed files with 308 additions and 121 deletions.
@@ -0,0 +1,191 @@
/*
* $Id$
*
* SARL is an general-purpose agent programming language.
* More details on http://www.sarl.io
*
* Copyright (C) 2014-2020 the original authors or authors.
*
* 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://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License 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 io.sarl.eclipse.launching.runner.general;

import java.lang.reflect.Method;
import java.text.MessageFormat;
import java.util.Properties;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.arakhne.afc.bootique.variables.VariableNames;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin;
import org.eclipse.jdt.launching.IVMRunner;
import org.eclipse.jdt.launching.VMRunnerConfiguration;
import org.eclipse.swt.widgets.Shell;

import io.sarl.eclipse.SARLEclipsePlugin;

/**
* Abstract implementation of a VM runner that is running in the current Eclipse VM.
* This implementation is for debugging of SREs.
*
* @author $Author: sgalland$
* @version $FullVersion$
* @mavengroupid $GroupId$
* @mavenartifactid $ArtifactId$
* @since 0.12
*/
public abstract class AbstractEmbeddedVMRunner implements IVMRunner {

/** Standard extension for JAR files.
*/
protected static final String JAR_EXTENSION = ".jar"; //$NON-NLS-1$

/** Standard slash, that is used in URLs a separator.
*/
protected static final String SLASH = "/"; //$NON-NLS-1$

/** Standard slash, that is used in URLs a separator.
*/
protected static final String DEFINITION_PATTERN = "^[-/]D([^=]+)=(.*)$"; //$NON-NLS-1$

@Override
public final void run(VMRunnerConfiguration configuration, ILaunch launch, IProgressMonitor monitor)
throws CoreException {
try {
final Job myJob = createJob(configuration, launch);
monitor.done();
if (myJob != null) {
myJob.schedule();
}
} catch (Exception exception) {
throw new CoreException(SARLEclipsePlugin.getDefault().createStatus(IStatus.ERROR, exception));
}
}

/** Create the main class finder.
*
* @return the main class finder.
*/
protected abstract MainClassFinder getMainClassFinder();

private void resetProperties() {
final Properties props = System.getProperties();
final Iterator<Entry<Object, Object>> iterator = props.entrySet().iterator();
while (iterator.hasNext()) {
final Entry<Object, Object> entry = iterator.next();
final String name = entry.getKey().toString();
if (name.startsWith(VariableNames.BOOTIQUE_PROPERTY_PREFIX)) {
iterator.remove();
}
}
}

private void registerProperties(VMRunnerConfiguration configuration) {
final Properties props = System.getProperties();
final Pattern pattern = Pattern.compile(DEFINITION_PATTERN);
for (final String arg : configuration.getVMArguments()) {
final Matcher matcher = pattern.matcher(arg);
if (matcher.matches()) {
final String name = matcher.group(1);
final String value = matcher.group(2);
props.setProperty(name, value);
}
}
}

/** Create the job that enables to run the SRE into the current Eclipse JVM.
*
* @param configuration description of the VM configuration (that is set without considering the embedding state of the VM).
* @param launch description of the launch.
* @param embeddingClassLoader the class loader to be used for embedding the program, or {@code null} if one.
* @return the job.
*/
protected Job createJob(VMRunnerConfiguration configuration, ILaunch launch) {
final Job myJob = new Job(launch.getLaunchConfiguration().getName()) {
@Override
public IStatus run(IProgressMonitor monitor) {
monitor.subTask(MessageFormat.format(Messages.AbstractEmbeddedVMRunner_0, launch.getLaunchConfiguration().getName()));
final MainClassFinder mcFinder = getMainClassFinder();
try {
resetProperties();
registerProperties(configuration);
//
mcFinder.initialize(configuration, launch);
//
final String mainClass = configuration.getClassToLaunch();
//
final Class<?> clazz = mcFinder.getMainClass(mainClass);
//
final Method mainMethod = clazz.getDeclaredMethod("main", String[].class); //$NON-NLS-1$
mainMethod.invoke(null, (Object) configuration.getProgramArguments());
return SARLEclipsePlugin.getDefault().createOkStatus();
} catch (Throwable exception) {
return SARLEclipsePlugin.getDefault().createStatus(IStatus.ERROR, exception);
} finally {
mcFinder.release();
monitor.done();
}
}
};
return myJob;
}

/**
* Convenience method to return the active workbench window shell.
*
* @return active workbench window shell
*/
protected static Shell getShell() {
return JDIDebugUIPlugin.getActiveWorkbenchShell();
}

/** Finder of the main class.
*
* @author $Author: sgalland$
* @version $FullVersion$
* @mavengroupid $GroupId$
* @mavenartifactid $ArtifactId$
* @since 0.12
*/
protected interface MainClassFinder {

/** Initialize the finder.
*
* @param configuration the VM configuration to use.
* @param launch the launching tool.
*/
void initialize(VMRunnerConfiguration configuration, ILaunch launch);

/** Find the main class to be launched.
*
* @param mainClass the fully qualified name of the class to launch.
* @return the main class.
* @throws Exception if the class cannot be loaded.
*/
Class<?> getMainClass(String mainClass) throws Exception;

/** Release the finder.
*/
void release();

}

}
Expand Up @@ -465,7 +465,7 @@ protected void createRunConfiguration(IProgressMonitor monitor) throws CoreExcep

final String[] classpath;
final String[] modulepath;
if (JavaRuntime.isModularConfiguration(this.configuration) && owner.supportsModule()) {
if (owner.supportsModularProjectAndLauncher(this.configuration)) {
final String[][] paths = owner.getClasspathAndModulepath(this.configuration);
if (paths != null && paths[0] != null) {
classpath = paths[0];
Expand Down
Expand Up @@ -30,6 +30,7 @@
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import javax.inject.Inject;

import org.eclipse.core.runtime.CoreException;
Expand Down Expand Up @@ -118,6 +119,16 @@ public boolean supportsModule() {
return super.supportsModule();
}

/** Replies if both the current launch configuration and the provided configuration
* supports modules.
*
* @param configuration the configuration to test.
* @return {@code true} if both the configuration (i.e. the project and the concrete launch configuration.
*/
public boolean supportsModularProjectAndLauncher(ILaunchConfiguration configuration) {
return JavaRuntime.isModularConfiguration(configuration) && supportsModule();
}

/** Clear any buffered value.
*/
protected synchronized void clearBuffers() {
Expand Down Expand Up @@ -577,7 +588,10 @@ public final String getProgramArguments(ILaunchConfiguration configuration) thro
@Override
public IVMRunner getVMRunner(ILaunchConfiguration configuration, String mode) throws CoreException {
if (getConfigurationAccessor().isEmbeddedSRE(configuration)) {
return new EmbeddedVMRunner();
if (!supportsModularProjectAndLauncher(configuration)) {
return new EmbeddedNotModularVMRunner();
}
throw new IllegalStateException();
}
return super.getVMRunner(configuration, mode);
}
Expand Down
@@ -0,0 +1,99 @@
/*
* $Id$
*
* SARL is an general-purpose agent programming language.
* More details on http://www.sarl.io
*
* Copyright (C) 2014-2020 the original authors or authors.
*
* 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://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License 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 io.sarl.eclipse.launching.runner.general;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;

import org.arakhne.afc.vmutil.ClassLoaderFinder;
import org.arakhne.afc.vmutil.DynamicURLClassLoader;
import org.arakhne.afc.vmutil.FileSystem;
import org.arakhne.afc.vmutil.URISchemeType;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.jdt.launching.VMRunnerConfiguration;

/**
* Implementation of a VM runner that is running in the current Eclipse VM assuming it is running on
* a Java that cannot support modules.
* This implementation is for debugging of SREs.
*
* @author $Author: sgalland$
* @version $FullVersion$
* @mavengroupid $GroupId$
* @mavenartifactid $ArtifactId$
*/
public class EmbeddedNotModularVMRunner extends AbstractEmbeddedVMRunner {

@Override
protected MainClassFinder getMainClassFinder() {
return new CpMainClassFinder();
}

/** Finder of the main class.
*
* @author $Author: sgalland$
* @version $FullVersion$
* @mavengroupid $GroupId$
* @mavenartifactid $ArtifactId$
* @since 0.12
*/
protected static class CpMainClassFinder implements MainClassFinder {

private ClassLoader classLoader;

@Override
public void initialize(VMRunnerConfiguration configuration, ILaunch launch) {
final String[] classpath = configuration.getClassPath();
final URL[] classPathURLs = new URL[classpath.length];
Arrays.parallelSetAll(classPathURLs, index -> {
String path = classpath[index];
final URL url = FileSystem.convertStringToURL(path, false);
path = url.getFile();
if (!path.endsWith(JAR_EXTENSION) && !path.endsWith(SLASH)) {
path = path + SLASH;
}
try {
return new URL(URISchemeType.FILE.name(), null, path);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
});
//
this.classLoader = DynamicURLClassLoader.newInstance(ClassLoader.getSystemClassLoader(), classPathURLs);
//
ClassLoaderFinder.setPreferredClassLoader(this.classLoader);
}

@Override
public Class<?> getMainClass(String mainClass) throws Exception {
return this.classLoader.loadClass(mainClass);
}

@Override
public void release() {
ClassLoaderFinder.popPreferredClassLoader();
}

}

}

0 comments on commit df956d6

Please sign in to comment.