Bug 514760 - [9] Run configuration should support notion of modules

Change-Id: Iaf3a9a967a5d3e6368f5c207ed45a32e5eb4c5c9
Also-by:  Jay Arthanareeswaran <jarthana@in.ibm.com>
Signed-off-by: Sarika Sinha <sarika.sinha@in.ibm.com>
Signed-off-by:  Jay Arthanareeswaran <jarthana@in.ibm.com>
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/classpath/ClasspathEntry.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/classpath/ClasspathEntry.java
index 33d2430..cea0745 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/classpath/ClasspathEntry.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/classpath/ClasspathEntry.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * 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
@@ -254,4 +254,9 @@
 		}
 		return null;
 	}
+
+	@Override
+	public boolean isAutomodule() {
+		return this.entry.isAutomodule();
+	}
 }
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/AbstractRuntimeClasspathEntry.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/AbstractRuntimeClasspathEntry.java
index 1185ae0..4f7042f 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/AbstractRuntimeClasspathEntry.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/AbstractRuntimeClasspathEntry.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * 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
@@ -260,4 +260,9 @@
 	protected void setJavaProject(IJavaProject javaProject) {
 		fJavaProject = javaProject;
 	}
+
+	@Override
+	public boolean isAutomodule() {
+		return false;
+	}
 }
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/DefaultProjectClasspathEntry.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/DefaultProjectClasspathEntry.java
index 472fbbd..569eaa2 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/DefaultProjectClasspathEntry.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/DefaultProjectClasspathEntry.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- *  Copyright (c) 2000, 2015 IBM Corporation and others.
+ *  Copyright (c) 2000, 2017 IBM Corporation and others.
  *  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
@@ -299,7 +299,7 @@
 								IPackageFragmentRoot[] roots = project.findPackageFragmentRoots(entry);
 								for (int i = 0; i < roots.length; i++) {
 									IPackageFragmentRoot root = roots[i];
-									r = JavaRuntime.newArchiveRuntimeClasspathEntry(root.getPath());
+									r = JavaRuntime.newArchiveRuntimeClasspathEntry(root.getPath(), entry.getSourceAttachmentPath(), entry.getSourceAttachmentRootPath(), entry.getAccessRules(), entry.getExtraAttributes(), entry.isExported());
 									r.setSourceAttachmentPath(entry.getSourceAttachmentPath());
 									r.setSourceAttachmentRootPath(entry.getSourceAttachmentRootPath());
 									if (!expandedPath.contains(r)) {
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/RuntimeClasspathEntry.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/RuntimeClasspathEntry.java
index df2e510..b413741 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/RuntimeClasspathEntry.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/RuntimeClasspathEntry.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * 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
@@ -716,4 +716,15 @@
 	public void setJavaProject(IJavaProject project) {
 		fJavaProject = project;
 	}
+
+	@Override
+	public boolean isAutomodule() {
+		IClasspathAttribute[] extraAttributes = getClasspathEntry().getExtraAttributes();
+		for (IClasspathAttribute attribute : extraAttributes) {
+			if (IClasspathAttribute.AUTOMATIC_MODULE.equals(attribute.getName()) && Boolean.TRUE.toString().equals(attribute.getValue())) {
+				return true;
+			}
+		}
+		return false;
+	}
 }
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/StandardVMDebugger.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/StandardVMDebugger.java
index ed11b38..055c424 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/StandardVMDebugger.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/StandardVMDebugger.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * 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
@@ -209,6 +209,12 @@
 		addArguments(ensureEncoding(launch, allVMArgs), arguments);
 		addBootClassPathArguments(arguments, config);
 
+		String[] mp = config.getModulepath();
+		if (isModular(config, fVMInstance) && (mp != null && mp.length > 0)) {
+			arguments.add("-p"); //$NON-NLS-1$
+			arguments.add(convertClassPath(mp));
+		}
+
 		String[] cp= config.getClassPath();
 		int cpidx = -1;
 		if (cp.length > 0) {
@@ -217,7 +223,19 @@
 			arguments.add(convertClassPath(cp));
 		}
 
-		arguments.add(config.getClassToLaunch());
+		if (isModular(config, fVMInstance) && (mp != null && mp.length > 0)) {
+			arguments.add("-m"); //$NON-NLS-1$
+			arguments.add(config.getModuleDescription() + "/" + config.getClassToLaunch()); //$NON-NLS-1$
+		} else {
+			arguments.add(config.getClassToLaunch());
+		}
+
+		/*
+		 * String[] cp= config.getClassPath(); int cpidx = -1; if (cp.length > 0) { cpidx = arguments.size(); arguments.add("-classpath");
+		 * //$NON-NLS-1$ arguments.add(convertClassPath(cp)); }
+		 *
+		 * arguments.add(config.getClassToLaunch());
+		 */
 		addArguments(config.getProgramArguments(), arguments);
 
 		//With the newer VMs and no backwards compatibility we have to always prepend the current env path (only the runtime one)
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/StandardVMRunner.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/StandardVMRunner.java
index b120007..87d178e 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/StandardVMRunner.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/StandardVMRunner.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- *  Copyright (c) 2000, 2016 IBM Corporation and others.
+ *  Copyright (c) 2000, 2017 IBM Corporation and others.
  *  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
@@ -372,6 +372,12 @@
 
 		addBootClassPathArguments(arguments, config);
 
+		String[] mp = config.getModulepath();
+		if (isModular(config, fVMInstance) && (mp != null && mp.length > 0)) {
+			arguments.add("-p"); //$NON-NLS-1$
+			arguments.add(convertClassPath(mp));
+		}
+
 		String[] cp= config.getClassPath();
 		int cpidx = -1;
 		if (cp.length > 0) {
@@ -379,7 +385,13 @@
 			arguments.add("-classpath"); //$NON-NLS-1$
 			arguments.add(convertClassPath(cp));
 		}
-		arguments.add(config.getClassToLaunch());
+
+		if (isModular(config, fVMInstance) && (mp != null && mp.length > 0)) {
+			arguments.add("-m"); //$NON-NLS-1$
+			arguments.add(config.getModuleDescription() + "/" + config.getClassToLaunch()); //$NON-NLS-1$
+		} else {
+			arguments.add(config.getClassToLaunch());
+		}
 
 		String[] programArgs= config.getProgramArguments();
 		addArguments(programArgs, arguments);
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/AbstractJavaLaunchConfigurationDelegate.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/AbstractJavaLaunchConfigurationDelegate.java
index d46cb52..030b2ca 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/AbstractJavaLaunchConfigurationDelegate.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/AbstractJavaLaunchConfigurationDelegate.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * 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
@@ -41,7 +41,9 @@
 import org.eclipse.debug.core.sourcelookup.ISourceLookupDirector;
 import org.eclipse.jdt.core.IJavaModelMarker;
 import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
 import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.debug.core.IJavaDebugTarget;
 import org.eclipse.jdt.debug.core.IJavaMethodBreakpoint;
 import org.eclipse.jdt.debug.core.JDIDebugModel;
@@ -410,21 +412,93 @@
 		IRuntimeClasspathEntry[] entries = JavaRuntime
 				.computeUnresolvedRuntimeClasspath(configuration);
 		entries = JavaRuntime.resolveRuntimeClasspath(entries, configuration);
-		List<String> userEntries = new ArrayList<>(entries.length);
 		Set<String> set = new HashSet<>(entries.length);
+		IJavaProject proj = JavaRuntime.getJavaProject(configuration);
 		for (int i = 0; i < entries.length; i++) {
-			if (entries[i].getClasspathProperty() == IRuntimeClasspathEntry.USER_CLASSES) {
-				String location = entries[i].getLocation();
+			IRuntimeClasspathEntry entry = entries[i];
+			if (entry.getClasspathProperty() == IRuntimeClasspathEntry.USER_CLASSES) {
+				String location = entry.getLocation();
 				if (location != null) {
-					if (!set.contains(location)) {
-						userEntries.add(location);
+					if (proj.getModuleDescription() != null) {
+						if (isModuleEntry(proj, entry)) {
+							continue;
+						}
+						set.add(location);
+					} else {
 						set.add(location);
 					}
 				}
 			}
 		}
-		return userEntries.toArray(new String[userEntries.size()]);
+		return set.toArray(new String[set.size()]);
 	}
+
+	/**
+	 * Returns the entries that should appear on the user portion of the classpath and modulepath as specified by the given launch configuration, as
+	 * an array of resolved strings. The returned array is empty if no classpath and modulepath is specified.
+	 *
+	 * @param configuration
+	 *            launch configuration
+	 * @return the classpath and modulepath specified by the given launch configuration, possibly an empty array
+	 * @exception CoreException
+	 *                if unable to retrieve the attribute
+	 * @since 3.9
+	 */
+	public String[][] getClasspathAndModulepath(ILaunchConfiguration config) throws CoreException {
+		IRuntimeClasspathEntry[] entries = JavaRuntime.computeUnresolvedRuntimeClasspath(config);
+		entries = JavaRuntime.resolveRuntimeClasspath(entries, config);
+		String[][] path = new String[2][entries.length];
+		Set<String> classpathSet = new HashSet<>(entries.length);
+		Set<String> modulepathSet = new HashSet<>(entries.length);
+		IJavaProject proj = JavaRuntime.getJavaProject(config);
+		for (IRuntimeClasspathEntry entry : entries) {
+			if (entry.getClasspathProperty() == IRuntimeClasspathEntry.USER_CLASSES) {
+				String location = entry.getLocation();
+				if (location != null) {
+					if (proj.getModuleDescription() != null) {
+						if (isModuleEntry(proj, entry)) {
+							modulepathSet.add(location);
+						} else {
+							classpathSet.add(location);
+						}
+					}
+					else {
+						classpathSet.add(location);
+					}
+				}
+			}
+		}
+		path[0] = classpathSet.toArray(new String[classpathSet.size()]);
+		path[1] = modulepathSet.toArray(new String[modulepathSet.size()]);
+		return path;
+	}
+
+
+	private boolean isModuleEntry(IJavaProject proj, IRuntimeClasspathEntry entry) throws JavaModelException {
+		switch (entry.getType()) {
+			case IRuntimeClasspathEntry.PROJECT:
+				IResource resource = entry.getResource();
+				if (resource != null && resource.getType() == IResource.PROJECT) {
+					IJavaProject javaProject = JavaCore.create((IProject) resource);
+					if (proj.getElementName().equals(javaProject.getElementName()) || javaProject.getModuleDescription() != null) {
+						return true;
+					}
+				}
+				break;
+			default:
+				if (entry.isAutomodule()) {
+					return true;
+				}
+				// This is based on the assumption that the entries don't contain any container or variable entries.
+				IPackageFragmentRoot root = proj.findPackageFragmentRoot(entry.getPath());
+				if (root.getModuleDescription() != null) {
+					return true;
+				}
+				break;
+		}
+		return false;
+	}
+
 	/**
 	 * Returns the Java project specified by the given launch configuration, or
 	 * <code>null</code> if none.
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/AbstractVMRunner.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/AbstractVMRunner.java
index 3c7dfff..cfe6696 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/AbstractVMRunner.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/AbstractVMRunner.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * 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
@@ -25,6 +25,7 @@
 import org.eclipse.debug.core.DebugPlugin;
 import org.eclipse.debug.core.ILaunch;
 import org.eclipse.debug.core.model.IProcess;
+import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.internal.launching.LaunchingMessages;
 import org.eclipse.jdt.internal.launching.LaunchingPlugin;
 import org.eclipse.osgi.service.environment.Constants;
@@ -208,4 +209,29 @@
 		System.arraycopy(launchVMArgs, 0, allVMArgs, vmVMArgs.length, launchVMArgs.length);
 		return allVMArgs;
 	}
+
+	/**
+	 * Examines the project and install for presence of module and execution support.
+	 *
+	 * @param config
+	 *            runner configuration
+	 * @param vmInstall
+	 *            VM install
+	 * @return <code>true</code> if project is a module and uses JRE version 9 or more, or <code>false</code> otherwise
+	 * @since 3.9
+	 */
+	protected boolean isModular(VMRunnerConfiguration config, IVMInstall vmInstall) {
+		if (config.getModuleDescription() != null && config.getModuleDescription().length() > 0 && vmInstall instanceof AbstractVMInstall) {
+			AbstractVMInstall install = (AbstractVMInstall) vmInstall;
+			String vmver = install.getJavaVersion();
+			// versionToJdkLevel only handles 3 char versions = 1.5, 1.6, 1.9, etc
+			if (vmver.length() > 3) {
+				vmver = vmver.substring(0, 3);
+			}
+			if (JavaCore.compareJavaVersions(vmver, JavaCore.VERSION_9) >= 0) {
+				return true;
+			}
+		}
+		return false;
+	}
 }
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/IRuntimeClasspathEntry.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/IRuntimeClasspathEntry.java
index 165632b..6b33bd6 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/IRuntimeClasspathEntry.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/IRuntimeClasspathEntry.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * 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
@@ -347,4 +347,12 @@
 	 * @since 3.0
 	 */
 	public IJavaProject getJavaProject();
+
+	/**
+	 * Returns <code>true</code> if the java project associated is an AutoModule.
+	 *
+	 * @return <code>true</code> if the Java project associated is an AutoModule or <code>null</false> if none
+	 * @since 3.9
+	 */
+	public boolean isAutomodule();
 }
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/JavaLaunchDelegate.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/JavaLaunchDelegate.java
index 089ed83..ead3496 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/JavaLaunchDelegate.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/JavaLaunchDelegate.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * 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
@@ -18,6 +18,8 @@
 import org.eclipse.core.runtime.NullProgressMonitor;
 import org.eclipse.debug.core.ILaunch;
 import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IModuleDescription;
 import org.eclipse.jdt.internal.launching.LaunchingMessages;
 import org.eclipse.osgi.util.NLS;
 
@@ -69,19 +71,31 @@
 			Map<String, Object> vmAttributesMap = getVMSpecificAttributesMap(configuration);
 
 			// Classpath
-			String[] classpath = getClasspath(configuration);
+			String[][] paths = getClasspathAndModulepath(configuration);
+
+
 
 			// Create VM config
-			VMRunnerConfiguration runConfig = new VMRunnerConfiguration(mainTypeName, classpath);
+			VMRunnerConfiguration runConfig = new VMRunnerConfiguration(mainTypeName, paths[0]);
 			runConfig.setProgramArguments(execArgs.getProgramArgumentsArray());
 			runConfig.setEnvironment(envp);
 			runConfig.setVMArguments(execArgs.getVMArgumentsArray());
 			runConfig.setWorkingDirectory(workingDirName);
 			runConfig.setVMSpecificAttributesMap(vmAttributesMap);
+			// current module name, if so
+			IJavaProject proj = JavaRuntime.getJavaProject(configuration);
+			IModuleDescription module = proj.getModuleDescription();
+			String modName = module == null ? null : module.getElementName();
+			if (modName != null) {
+				runConfig.setModuleDescription(modName);
+			}
 
 			// Bootpath
 			runConfig.setBootClassPath(getBootpath(configuration));
 
+			// module path
+			runConfig.setModulepath(paths[1]);
+
 			// check for cancellation
 			if (monitor.isCanceled()) {
 				return;
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/JavaRuntime.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/JavaRuntime.java
index 660a104..3ea048c 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/JavaRuntime.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/JavaRuntime.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * 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
@@ -56,6 +56,7 @@
 import org.eclipse.core.variables.VariablesPlugin;
 import org.eclipse.debug.core.ILaunchConfiguration;
 import org.eclipse.debug.core.sourcelookup.ISourceContainer;
+import org.eclipse.jdt.core.IAccessRule;
 import org.eclipse.jdt.core.IClasspathAttribute;
 import org.eclipse.jdt.core.IClasspathContainer;
 import org.eclipse.jdt.core.IClasspathEntry;
@@ -660,6 +661,28 @@
 	}
 
 	/**
+	 * Returns a new runtime classpath entry for the given archive (possibly
+	 * external).
+	 *
+	 * @param path absolute path to an archive
+ 	 * @param sourceAttachmentPath the absolute path of the corresponding source archive or folder,
+	 *   or <code>null</code> if none. Note, since 3.0, an empty path is allowed to denote no source attachment.
+	 *   and will be automatically converted to <code>null</code>. Since 3.4, this path can also denote a path external
+	 *   to the workspace.
+	 * @param sourceAttachmentRootPath the location of the root of the source files within the source archive or folder
+	 *    or <code>null</code> if this location should be automatically detected.
+	 * @param accessRules the possibly empty list of access rules for this entry
+	 * @param extraAttributes the possibly empty list of extra attributes to persist with this entry
+	 * @param isExported indicates whether this entry is contributed to dependent
+	 * 	  projects in addition to the output location
+	 * @return runtime classpath entry
+	 * @since 3.9
+	 */
+	public static IRuntimeClasspathEntry newArchiveRuntimeClasspathEntry(IPath path, IPath sourceAttachmentPath, IPath sourceAttachmentRootPath, IAccessRule[] accessRules, IClasspathAttribute[] extraAtributes, boolean isExported) {
+		return newRuntimeClasspathEntry(JavaCore.newLibraryEntry(path, sourceAttachmentPath, sourceAttachmentRootPath, accessRules, extraAtributes, isExported));
+	}
+
+	/**
 	 * Returns a new runtime classpath entry for the classpath
 	 * variable with the given path.
 	 *
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/VMRunnerConfiguration.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/VMRunnerConfiguration.java
index 86037ae..e1a5637 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/VMRunnerConfiguration.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/VMRunnerConfiguration.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * 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
@@ -31,6 +31,8 @@
 	private String[] fEnvironment;
 	private String[] fClassPath;
 	private String[] fBootClassPath;
+	private String[] fModulepath;
+	private String fModuleDescription;
 	private String fWorkingDirectory;
 	private Map<String, Object> fVMSpecificAttributesMap;
 	private boolean fResume = true;
@@ -264,4 +266,46 @@
 	public boolean isResumeOnStartup() {
 		return fResume;
 	}
+
+	/**
+	 * Sets the modulepath.
+	 *
+	 * @param modulepath
+	 *            modulepath
+	 * @since 3.9
+	 */
+	public void setModulepath(String[] modulepath) {
+		this.fModulepath = modulepath;
+	}
+
+	/**
+	 * Returns the Modulepath.
+	 *
+	 * @return the modulepath
+	 * @since 3.9
+	 */
+	public String[] getModulepath() {
+		return this.fModulepath;
+	}
+
+	/**
+	 * Sets the fModuleDescription.
+	 *
+	 * @param fModuleDescription
+	 *            fModuleDescription
+	 * @since 3.9
+	 */
+	public void setModuleDescription(String fModuleDescription) {
+		this.fModuleDescription = fModuleDescription;
+	}
+
+	/**
+	 * Returns the ModuleDescription.
+	 *
+	 * @return the ModuleDescription
+	 * @since 3.9
+	 */
+	public String getModuleDescription() {
+		return this.fModuleDescription;
+	}
 }