/******************************************************************************* * Copyright (c) 2000, 2015 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 * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.debug.ui.launchConfigurations; import java.util.Map; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchConfigurationType; import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; import org.eclipse.debug.internal.ui.SWTFactory; import org.eclipse.debug.ui.ILaunchConfigurationTab; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.debug.ui.IJavaDebugUIConstants; import org.eclipse.jdt.internal.debug.ui.IJavaDebugHelpContextIds; import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin; import org.eclipse.jdt.internal.debug.ui.jres.JREDescriptor; import org.eclipse.jdt.internal.debug.ui.jres.JREsComboBlock; import org.eclipse.jdt.internal.debug.ui.launcher.LauncherMessages; import org.eclipse.jdt.launching.AbstractVMInstall; import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants; import org.eclipse.jdt.launching.IVMInstall; import org.eclipse.jdt.launching.JavaRuntime; import org.eclipse.jdt.launching.environments.IExecutionEnvironment; import org.eclipse.jdt.ui.ISharedImages; import org.eclipse.jdt.ui.JavaUI; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.ui.PlatformUI; /** * A launch configuration tab that displays and edits the VM install * launch configuration attributes. * <p> * Clients may call {@link #setHelpContextId(String)} on this tab prior to control * creation to alter the default context help associated with this tab. * </p> * <p> * This class may be instantiated. * </p> * @since 2.0 * @noextend This class is not intended to be sub-classed by clients. */ public class JavaJRETab extends JavaLaunchTab { // JRE Block protected JREsComboBlock fJREBlock; // Dynamic JRE UI widgets protected ILaunchConfigurationTab fDynamicTab; protected Composite fDynamicTabHolder; protected boolean fUseDynamicArea = true; protected ILaunchConfigurationWorkingCopy fWorkingCopy; protected ILaunchConfiguration fLaunchConfiguration; // State protected boolean fIsInitializing = false; // Selection changed listener (checked JRE) private IPropertyChangeListener fCheckListener = new IPropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent event) { handleSelectedJREChanged(); } }; /** * Constructor */ public JavaJRETab() { setHelpContextId(IJavaDebugHelpContextIds.LAUNCH_CONFIGURATION_DIALOG_JRE_TAB); } /* (non-Javadoc) * @see org.eclipse.debug.ui.ILaunchConfigurationTab#dispose() */ @Override public void dispose() { super.dispose(); if (fJREBlock != null) { fJREBlock.removePropertyChangeListener(fCheckListener); } } /** * @see ILaunchConfigurationTab#createControl(Composite) */ @Override public void createControl(Composite parent) { Font font = parent.getFont(); Composite topComp = SWTFactory.createComposite(parent, font, 1, 1, GridData.FILL_HORIZONTAL, 0, 0); fJREBlock = new JREsComboBlock(true); fJREBlock.setDefaultJREDescriptor(getDefaultJREDescriptor()); fJREBlock.setSpecificJREDescriptor(getSpecificJREDescriptor()); fJREBlock.createControl(topComp); Control control = fJREBlock.getControl(); fJREBlock.addPropertyChangeListener(fCheckListener); control.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); setDynamicTabHolder(SWTFactory.createComposite(topComp, font, 1, 1, GridData.FILL_BOTH, 0, 0)); setControl(topComp); PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), getHelpContextId()); } protected void setDynamicTabHolder(Composite tabHolder) { this.fDynamicTabHolder = tabHolder; } protected Composite getDynamicTabHolder() { return fDynamicTabHolder; } protected void setDynamicTab(ILaunchConfigurationTab tab) { fDynamicTab = tab; } protected ILaunchConfigurationTab getDynamicTab() { return fDynamicTab; } /** * @see ILaunchConfigurationTab#setDefaults(ILaunchConfigurationWorkingCopy) */ @Override public void setDefaults(ILaunchConfigurationWorkingCopy config) { setLaunchConfigurationWorkingCopy(config); ILaunchConfigurationTab dynamicTab = getDynamicTab(); if (dynamicTab != null) { dynamicTab.setDefaults(config); } } /** * @see ILaunchConfigurationTab#initializeFrom(ILaunchConfiguration) */ @Override public void initializeFrom(ILaunchConfiguration configuration) { fIsInitializing = true; getControl().setRedraw(false); setLaunchConfiguration(configuration); updateJREFromConfig(configuration); fJREBlock.setDefaultJREDescriptor(getDefaultJREDescriptor()); ILaunchConfigurationTab dynamicTab = getDynamicTab(); if (dynamicTab != null) { dynamicTab.initializeFrom(configuration); } getControl().setRedraw(true); fIsInitializing = false; } /** * @see ILaunchConfigurationTab#performApply(ILaunchConfigurationWorkingCopy) */ @Override @SuppressWarnings("deprecation") public void performApply(ILaunchConfigurationWorkingCopy configuration) { if (fJREBlock.isDefaultJRE()) { configuration.setAttribute(IJavaLaunchConfigurationConstants.ATTR_JRE_CONTAINER_PATH, (String)null); } else { IPath containerPath = fJREBlock.getPath(); String portablePath = null; if (containerPath != null) { portablePath = containerPath.toPortableString(); } configuration.setAttribute(IJavaLaunchConfigurationConstants.ATTR_JRE_CONTAINER_PATH, portablePath); } // erase old attributes in case the user changed from 'specific JRE' to 'default' - see bug 152446 configuration.setAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_INSTALL_NAME, (String)null); configuration.setAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_INSTALL_TYPE, (String)null); // Handle any attributes in the VM-specific area ILaunchConfigurationTab dynamicTab = getDynamicTab(); if (dynamicTab == null) { configuration.setAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_INSTALL_TYPE_SPECIFIC_ATTRS_MAP, (Map<String, String>)null); } else { dynamicTab.performApply(configuration); } } /** * @see ILaunchConfigurationTab#isValid(ILaunchConfiguration) */ @Override public boolean isValid(ILaunchConfiguration config) { setErrorMessage(null); setMessage(null); IStatus status = fJREBlock.getStatus(); if (!status.isOK()) { setErrorMessage(status.getMessage()); return false; } if(!isExternalToolConfiguration(fLaunchConfiguration)) { status = checkCompliance(); if (!status.isOK()) { setErrorMessage(status.getMessage()); return false; } } ILaunchConfigurationTab dynamicTab = getDynamicTab(); if (dynamicTab != null) { return dynamicTab.isValid(config); } return true; } /** * Returns if the specified <code>ILaunchConfiguration</code> is an ant or external tool * type. * @param configuration the {@link ILaunchConfiguration} * @return true if the specified <code>ILaunchConfiguration</code> is an ant or external tools * type configuration * * @since 3.4 */ private boolean isExternalToolConfiguration(ILaunchConfiguration configuration) { try { ILaunchConfigurationType type = configuration.getType(); String id = type.getIdentifier(); return id != null && (id.equals("org.eclipse.ant.AntLaunchConfigurationType") || //$NON-NLS-1$ id.equals("org.eclipse.ant.AntBuilderLaunchConfigurationType") || //$NON-NLS-1$ id.equals("org.eclipse.ui.externaltools.ProgramLaunchConfigurationType") || //$NON-NLS-1$ id.equals("org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType")); //$NON-NLS-1$ } catch (CoreException e) { return false; } } /** * Checks to make sure the class file compliance level and the selected VM are compatible * i.e. such that the selected JRE can run the currently compiled code * @return the status of the check * @since 3.3 */ private IStatus checkCompliance() { IJavaProject javaProject = getJavaProject(); if (javaProject == null) { return Status.OK_STATUS; } String source = LauncherMessages.JavaJRETab_3; String compliance = javaProject.getOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, false); if(compliance == null) { compliance = javaProject.getOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, true); source = LauncherMessages.JavaJRETab_4; } IPath vmPath = fJREBlock.getPath(); if (vmPath != null) { IVMInstall vm = null; if(JavaRuntime.newDefaultJREContainerPath().equals(vmPath)) { if(javaProject.isOpen()) { try { vm = JavaRuntime.getVMInstall(getJavaProject()); } catch (CoreException e) { JDIDebugUIPlugin.log(e); return Status.OK_STATUS; } if(vm == null) { vm = JavaRuntime.getVMInstall(vmPath); } } } else { vm = JavaRuntime.getVMInstall(vmPath); } String environmentId = JavaRuntime.getExecutionEnvironmentId(vmPath); if(vm instanceof AbstractVMInstall) { AbstractVMInstall install = (AbstractVMInstall) vm; String vmver = install.getJavaVersion(); if(vmver != null) { int val = compliance.compareTo(vmver); if(val > 0) { String setting = null; if (environmentId == null) { setting = LauncherMessages.JavaJRETab_2; } else { setting = LauncherMessages.JavaJRETab_1; } return new Status(IStatus.ERROR, IJavaDebugUIConstants.PLUGIN_ID, IStatus.ERROR, NLS.bind(LauncherMessages.JavaJRETab_0, new String[] {setting, source, compliance}), null); } } } return Status.OK_STATUS; } // when no VM path is specified return the error status from the JRE block return fJREBlock.getStatus(); } /** * @see ILaunchConfigurationTab#getName() */ @Override public String getName() { return LauncherMessages.JavaJRETab__JRE_1; } /** * @see ILaunchConfigurationTab#getImage() */ @Override public Image getImage() { return JavaUI.getSharedImages().getImage(ISharedImages.IMG_OBJS_LIBRARY); } /** * @see org.eclipse.debug.ui.AbstractLaunchConfigurationTab#getId() * * @since 3.3 */ @Override public String getId() { return "org.eclipse.jdt.debug.ui.javaJRETab"; //$NON-NLS-1$ } /** * This method updates the jre selection from the <code>ILaunchConfiguration</code> * @param config the config to update from */ @SuppressWarnings("deprecation") protected void updateJREFromConfig(ILaunchConfiguration config) { try { String path = config.getAttribute(IJavaLaunchConfigurationConstants.ATTR_JRE_CONTAINER_PATH, (String)null); if (path != null) { fJREBlock.setPath(Path.fromPortableString(path)); return; } } catch (CoreException e) { JDIDebugUIPlugin.log(e); } String vmName = null; String vmTypeID = null; try { vmTypeID = config.getAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_INSTALL_TYPE, (String)null); vmName = config.getAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_INSTALL_NAME, (String)null); } catch (CoreException ce) { JDIDebugUIPlugin.log(ce); } selectJRE(vmTypeID, vmName); } /** * Notification that the user changed the selection in the JRE combination box. */ protected void handleSelectedJREChanged() { loadDynamicJREArea(); // always set the newly created area with defaults ILaunchConfigurationWorkingCopy wc = getLaunchConfigurationWorkingCopy(); if (getDynamicTab() == null) { // remove any VM specific arguments from the config if (wc == null) { if (getLaunchConfiguration().isWorkingCopy()) { wc = (ILaunchConfigurationWorkingCopy)getLaunchConfiguration(); } } if (!fIsInitializing) { if (wc != null) { wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_INSTALL_TYPE_SPECIFIC_ATTRS_MAP, (Map<String, String>)null); } } } else { if (wc == null) { try { ILaunchConfiguration config = getLaunchConfiguration(); if (config.isWorkingCopy()) { // get a fresh copy to work on, only if there is an original to do so wc = (ILaunchConfigurationWorkingCopy) config; if(wc.getOriginal() != null) { wc.getOriginal().getWorkingCopy(); } } else { wc = getLaunchConfiguration().getWorkingCopy(); } } catch (CoreException e) { IStatus status = e.getStatus(); JDIDebugUIPlugin.statusDialog(status); JDIDebugUIPlugin.log(status); return; } } if (!fIsInitializing) { getDynamicTab().setDefaults(wc); getDynamicTab().initializeFrom(wc); } } updateLaunchConfigurationDialog(); } protected void selectJRE(String typeID, String vmName) { if (typeID == null || vmName == null) { fJREBlock.setPath(JavaRuntime.newDefaultJREContainerPath()); } else { fJREBlock.setPath(JavaRuntime.newJREContainerPath(typeID, vmName)); } } /** * Return the class that implements <code>ILaunchConfigurationTab</code> * that is registered against the install type of the currently selected VM. * @return the backing {@link ILaunchConfigurationTab} */ protected ILaunchConfigurationTab getTabForCurrentJRE() { if (!fJREBlock.isDefaultJRE()) { IPath path = fJREBlock.getPath(); if (path != null && JavaRuntime.getExecutionEnvironmentId(path) == null) { IVMInstall vm = fJREBlock.getJRE(); if (vm != null) { String vmInstallTypeID = vm.getVMInstallType().getId(); return JDIDebugUIPlugin.getDefault().getVMInstallTypePage(vmInstallTypeID); } } } return null; } /** * Show the contributed piece of UI that was registered for the install type * of the currently selected VM. */ protected void loadDynamicJREArea() { // Dispose of any current child widgets in the tab holder area Control[] children = getDynamicTabHolder().getChildren(); for (int i = 0; i < children.length; i++) { children[i].dispose(); } if (isUseDynamicJREArea()) { // Retrieve the dynamic UI for the current JRE setDynamicTab(getTabForCurrentJRE()); if (getDynamicTab() == null) { return; } // Ask the dynamic UI to create its Control getDynamicTab().setLaunchConfigurationDialog(getLaunchConfigurationDialog()); getDynamicTab().createControl(getDynamicTabHolder()); getDynamicTabHolder().layout(); } } protected ILaunchConfigurationWorkingCopy getLaunchConfigurationWorkingCopy() { return fWorkingCopy; } /** * Overridden here so that any error message in the dynamic UI gets returned. * * @see ILaunchConfigurationTab#getErrorMessage() */ @Override public String getErrorMessage() { ILaunchConfigurationTab tab = getDynamicTab(); if ((super.getErrorMessage() != null) || (tab == null)) { return super.getErrorMessage(); } return tab.getErrorMessage(); } protected void setLaunchConfigurationWorkingCopy(ILaunchConfigurationWorkingCopy workingCopy) { fWorkingCopy = workingCopy; } protected ILaunchConfiguration getLaunchConfiguration() { return fLaunchConfiguration; } protected void setLaunchConfiguration(ILaunchConfiguration launchConfiguration) { fLaunchConfiguration = launchConfiguration; } /** * Sets whether this tab will display the VM specific arguments area * if a JRE supports VM specific arguments. * * @param visible whether this tab will display the VM specific arguments area * if a JRE supports VM specific arguments */ public void setVMSpecificArgumentsVisible(boolean visible) { fUseDynamicArea = visible; } protected boolean isUseDynamicJREArea() { return fUseDynamicArea; } protected JREDescriptor getDefaultJREDescriptor() { return new JREDescriptor() { /* (non-Javadoc) * @see org.eclipse.jdt.internal.debug.ui.jres.DefaultJREDescriptor#getDescription() */ @Override public String getDescription() { IJavaProject project = getJavaProject(); String name = LauncherMessages.JavaJRETab_7; if (project == null) { IVMInstall vm = JavaRuntime.getDefaultVMInstall(); if (vm != null) { name = vm.getName(); } return NLS.bind(LauncherMessages.JavaJRETab_8, new String[]{name}); } try { String eeName = null; IClasspathEntry[] classpath = project.getRawClasspath(); for (int i = 0; i < classpath.length; i++) { IClasspathEntry entry = classpath[i]; if (entry.getEntryKind() == IClasspathEntry.CPE_CONTAINER) { if (JavaRuntime.JRE_CONTAINER.equals(entry.getPath().segment(0))) { String id = JavaRuntime.getExecutionEnvironmentId(entry.getPath()); if (id != null) { IExecutionEnvironment env = JavaRuntime.getExecutionEnvironmentsManager().getEnvironment(id); if (env != null) { eeName = env.getId(); break; } } } } } IVMInstall vm = JavaRuntime.getVMInstall(project); if (vm != null) { name = vm.getName(); } if (eeName != null) { return NLS.bind(LauncherMessages.JavaJRETab_5, new String[]{eeName, name}); } } catch (CoreException e) { } return NLS.bind(LauncherMessages.JavaJRETab_9, new String[]{name}); } }; } protected JREDescriptor getSpecificJREDescriptor() { return null; } /** * Returns the Java project associated with the current config being edited, * or <code>null</code> if none. * * @return java project or <code>null</code> */ protected IJavaProject getJavaProject() { if (getLaunchConfiguration() != null) { try { String name = getLaunchConfiguration().getAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, (String)null); if (name != null && name.length() > 0) { IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(name); if (project.exists()) { return JavaCore.create(project); } } } catch (CoreException e) { JDIDebugUIPlugin.log(e); } } return null; } /* (non-Javadoc) * @see org.eclipse.debug.ui.ILaunchConfigurationTab#activated(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy) */ @Override public void activated(ILaunchConfigurationWorkingCopy workingCopy) { // update the default JRE description, in case it has changed // based on the selected project fJREBlock.refresh(); } /* (non-Javadoc) * @see org.eclipse.debug.ui.ILaunchConfigurationTab#deactivated(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy) */ @Override public void deactivated(ILaunchConfigurationWorkingCopy workingCopy) { // do nothing when deactivated } }