/******************************************************************************* * 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 * Frits Jalvingh - Contribution for Bug 459831 - [launching] Support attaching * external annotations to a JRE container *******************************************************************************/ package org.eclipse.jdt.internal.debug.ui.jres; import java.io.File; import java.net.URL; import java.util.Iterator; 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.internal.ui.SWTFactory; import org.eclipse.jdt.core.IClasspathAttribute; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.debug.ui.IJavaDebugUIConstants; import org.eclipse.jdt.debug.ui.launchConfigurations.AbstractVMInstallPage; import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin; import org.eclipse.jdt.internal.debug.ui.jres.LibraryContentProvider.SubElement; import org.eclipse.jdt.internal.launching.EEVMInstall; import org.eclipse.jdt.internal.launching.EEVMType; import org.eclipse.jdt.launching.IRuntimeClasspathEntry; import org.eclipse.jdt.launching.IVMInstall; import org.eclipse.jdt.launching.JavaRuntime; import org.eclipse.jdt.launching.LibraryLocation; import org.eclipse.jdt.launching.VMStandin; import org.eclipse.jdt.launching.environments.ExecutionEnvironmentDescription; import org.eclipse.jdt.ui.wizards.BuildPathDialogAccess; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.FileDialog; /** * Control used to edit the libraries associated with a VM install */ public class VMLibraryBlock extends AbstractVMInstallPage implements SelectionListener, ISelectionChangedListener { /** * Attribute name for the last path used to open a file/directory chooser * dialog. */ protected static final String LAST_PATH_SETTING = "LAST_PATH_SETTING"; //$NON-NLS-1$ /** * the prefix for dialog setting pertaining to this block */ protected static final String DIALOG_SETTINGS_PREFIX = "VMLibraryBlock"; //$NON-NLS-1$ protected boolean fInCallback = false; protected VMStandin fVmInstall; //widgets protected LibraryContentProvider fLibraryContentProvider; protected TreeViewer fLibraryViewer; private Button fUpButton; private Button fDownButton; private Button fRemoveButton; private Button fAddButton; private Button fJavadocButton; private Button fSourceButton; protected Button fDefaultButton; private IStatus[] fLibStatus; private Button fAnnotationsButton; /** * Constructs a new wizard page with the given name. * * @param pageName page name */ VMLibraryBlock() { super(JREMessages.VMLibraryBlock_2); fLibStatus = new IStatus[]{Status.OK_STATUS}; } /* (non-Javadoc) * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite) */ @Override public void createControl(Composite parent) { Font font = parent.getFont(); Composite comp = SWTFactory.createComposite(parent, font, 2, 1, GridData.FILL_BOTH, 0, 0); fLibraryViewer= new TreeViewer(comp); GridData gd = new GridData(GridData.FILL_BOTH); gd.heightHint = 6; fLibraryViewer.getControl().setLayoutData(gd); fLibraryContentProvider= new LibraryContentProvider(); fLibraryViewer.setContentProvider(fLibraryContentProvider); fLibraryViewer.setLabelProvider(new LibraryLabelProvider()); fLibraryViewer.setInput(this); fLibraryViewer.addSelectionChangedListener(this); Composite pathButtonComp = SWTFactory.createComposite(comp, font, 1, 1, GridData.VERTICAL_ALIGN_BEGINNING | GridData.HORIZONTAL_ALIGN_FILL, 0, 0); fAddButton = SWTFactory.createPushButton(pathButtonComp, JREMessages.VMLibraryBlock_7, JREMessages.VMLibraryBlock_16, null); fAddButton.addSelectionListener(this); fJavadocButton = SWTFactory.createPushButton(pathButtonComp, JREMessages.VMLibraryBlock_3, JREMessages.VMLibraryBlock_17, null); fJavadocButton.setEnabled(false); fJavadocButton.addSelectionListener(this); fSourceButton = SWTFactory.createPushButton(pathButtonComp, JREMessages.VMLibraryBlock_11, JREMessages.VMLibraryBlock_18, null); fSourceButton.setEnabled(false); fSourceButton.addSelectionListener(this); fAnnotationsButton = SWTFactory.createPushButton(pathButtonComp, JREMessages.VMExternalAnnsBlock_3, JREMessages.VMExternalAnnsBlock_4, null); fAnnotationsButton.setEnabled(false); fAnnotationsButton.addSelectionListener(this); fLibraryViewer.addDoubleClickListener(new IDoubleClickListener() { @Override public void doubleClick(DoubleClickEvent event) { IStructuredSelection sel = (IStructuredSelection)event.getViewer().getSelection(); Object obj = sel.getFirstElement(); if(obj instanceof SubElement) { edit(sel, ((SubElement)obj).getType()); } } }); fRemoveButton = SWTFactory.createPushButton(pathButtonComp, JREMessages.VMLibraryBlock_6, JREMessages.VMLibraryBlock_12, null); fRemoveButton.setEnabled(false); fRemoveButton.addSelectionListener(this); fUpButton = SWTFactory.createPushButton(pathButtonComp, JREMessages.VMLibraryBlock_4, JREMessages.VMLibraryBlock_13, null); fUpButton.setEnabled(false); fUpButton.addSelectionListener(this); fDownButton = SWTFactory.createPushButton(pathButtonComp, JREMessages.VMLibraryBlock_5, JREMessages.VMLibraryBlock_14, null); fDownButton.setEnabled(false); fDownButton.addSelectionListener(this); fDefaultButton = SWTFactory.createPushButton(pathButtonComp, JREMessages.VMLibraryBlock_9, JREMessages.VMLibraryBlock_15, null); fDefaultButton.addSelectionListener(this); setControl(comp); } /** * The "default" button has been toggled */ private void restoreDefaultLibraries() { LibraryLocation[] libs = null; File installLocation = null; if (fVmInstall != null) { if (EEVMType.ID_EE_VM_TYPE.equals(fVmInstall.getVMInstallType().getId())) { File definitionFile = null; String path = fVmInstall.getAttribute(EEVMInstall.ATTR_DEFINITION_FILE); if (path != null) { definitionFile = new File(path); } if (definitionFile != null) { try { ExecutionEnvironmentDescription desc = new ExecutionEnvironmentDescription(definitionFile); libs = desc.getLibraryLocations(); } catch (CoreException e) { libs = new LibraryLocation[0]; } } else { libs = new LibraryLocation[0]; } } else { installLocation = fVmInstall.getInstallLocation(); if (installLocation == null) { libs = new LibraryLocation[0]; } else { libs = fVmInstall.getVMInstallType().getDefaultLibraryLocations(installLocation); } } } fLibraryContentProvider.setLibraries(libs); update(); } /** * Updates buttons and status based on current libraries */ private void update() { updateButtons(); IStatus status = Status.OK_STATUS; if (fLibraryContentProvider.getLibraries().length == 0) { status = new Status(IStatus.ERROR, JDIDebugUIPlugin.getUniqueIdentifier(), IJavaDebugUIConstants.INTERNAL_ERROR, "Libraries cannot be empty.", null); //$NON-NLS-1$ } LibraryStandin[] standins = fLibraryContentProvider.getStandins(); for (int i = 0; i < standins.length; i++) { IStatus st = standins[i].validate(); if (!st.isOK()) { status = st; break; } } fLibStatus[0] = status; if (status.isOK()) { setErrorMessage(null); setPageComplete(true); } else { setErrorMessage(status.getMessage()); setPageComplete(false); } // must force since this page is a 'sub-page' and may not be considered the current page if (getContainer().getCurrentPage() != this) { getContainer().updateMessage(); getContainer().updateButtons(); } } /** * Determines if the current libraries displayed to the user are the default location * for the given vm working copy. * @param vm the virtual machine to check for the default location * @return true if the current set of locations are the defaults, false otherwise */ protected boolean isDefaultLocations(IVMInstall vm) { LibraryLocation[] libraryLocations = fLibraryContentProvider.getLibraries(); if (vm == null || libraryLocations == null) { return true; } File installLocation = vm.getInstallLocation(); if (installLocation != null) { LibraryLocation[] def = vm.getVMInstallType().getDefaultLibraryLocations(installLocation); if (def.length == libraryLocations.length) { for (int i = 0; i < def.length; i++) { if (!def[i].equals(libraryLocations[i])) { return false; } } return true; } } return false; } /* (non-Javadoc) * @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent) */ @Override public void widgetSelected(SelectionEvent e) { boolean completed = true; Object source= e.getSource(); if (source == fUpButton) { fLibraryContentProvider.up((IStructuredSelection) fLibraryViewer.getSelection()); } else if (source == fDownButton) { fLibraryContentProvider.down((IStructuredSelection) fLibraryViewer.getSelection()); } else if (source == fRemoveButton) { fLibraryContentProvider.remove((IStructuredSelection) fLibraryViewer.getSelection()); } else if (source == fAddButton) { completed = add((IStructuredSelection) fLibraryViewer.getSelection()); } else if(source == fJavadocButton) { edit((IStructuredSelection) fLibraryViewer.getSelection(), SubElement.JAVADOC_URL); } else if(source == fSourceButton) { edit((IStructuredSelection) fLibraryViewer.getSelection(), SubElement.SOURCE_PATH); } else if (source == fAnnotationsButton) { edit((IStructuredSelection) fLibraryViewer.getSelection(), SubElement.EXTERNAL_ANNOTATIONS_PATH); } else if (source == fDefaultButton) { restoreDefaultLibraries(); } if (completed) { update(); } } /* (non-Javadoc) * @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent) */ @Override public void widgetDefaultSelected(SelectionEvent e) {} /** * Adds external libraries to the JRE. Returns <code>true</code> if successful and * <code>false</code> if canceled. */ private boolean add(IStructuredSelection selection) { IDialogSettings dialogSettings= JDIDebugUIPlugin.getDefault().getDialogSettings(); String lastUsedPath= dialogSettings.get(LAST_PATH_SETTING); if (lastUsedPath == null) { lastUsedPath= ""; //$NON-NLS-1$ } FileDialog dialog= new FileDialog(fLibraryViewer.getControl().getShell(), SWT.MULTI); dialog.setText(JREMessages.VMLibraryBlock_10); dialog.setFilterExtensions(new String[] {"*.jar;*.zip","*.*"}); //$NON-NLS-1$ //$NON-NLS-2$ dialog.setFilterPath(lastUsedPath); String res= dialog.open(); if (res == null) { return false; } String[] fileNames= dialog.getFileNames(); int nChosen= fileNames.length; IPath filterPath= new Path(dialog.getFilterPath()); LibraryLocation[] libs= new LibraryLocation[nChosen]; for (int i= 0; i < nChosen; i++) { libs[i]= new LibraryLocation(filterPath.append(fileNames[i]).makeAbsolute(), Path.EMPTY, Path.EMPTY); } dialogSettings.put(LAST_PATH_SETTING, filterPath.toOSString()); fLibraryContentProvider.add(libs, selection); return true; } /** * Open the javadoc location dialog or the source location dialog, and set the result * to the selected libraries. */ private void edit(IStructuredSelection selection, int type) { Object obj = selection.getFirstElement(); LibraryStandin standin = null; if(obj instanceof LibraryStandin) { standin = (LibraryStandin) obj; } else if(obj instanceof SubElement){ SubElement sub = (SubElement)obj; standin = sub.getParent(); } if(standin != null) { LibraryLocation library = standin.toLibraryLocation(); if (type == SubElement.JAVADOC_URL) { URL[] urls = BuildPathDialogAccess.configureJavadocLocation(fLibraryViewer.getControl().getShell(), library.getSystemLibraryPath().toOSString(), library.getJavadocLocation()); if (urls != null) { fLibraryContentProvider.setJavadoc(urls[0], selection); } } else if(type == SubElement.SOURCE_PATH){ IRuntimeClasspathEntry entry = JavaRuntime.newArchiveRuntimeClasspathEntry(library.getSystemLibraryPath()); entry.setSourceAttachmentPath(library.getSystemLibrarySourcePath()); entry.setSourceAttachmentRootPath(library.getPackageRootPath()); IClasspathEntry classpathEntry = BuildPathDialogAccess.configureSourceAttachment(fLibraryViewer.getControl().getShell(), entry.getClasspathEntry()); if (classpathEntry != null) { fLibraryContentProvider.setSourcePath(classpathEntry.getSourceAttachmentPath(), classpathEntry.getSourceAttachmentRootPath(), selection); } } else if(type == SubElement.EXTERNAL_ANNOTATIONS_PATH) { IRuntimeClasspathEntry entry = JavaRuntime.newArchiveRuntimeClasspathEntry(library.getSystemLibraryPath()); entry.setExternalAnnotationsPath(library.getExternalAnnotationsPath()); IClasspathAttribute[] extraAttributes = entry.getClasspathEntry().getExtraAttributes(); String annotationPathString = findClasspathAttribute(extraAttributes, IClasspathAttribute.EXTERNAL_ANNOTATION_PATH); IPath annotationPath = null == annotationPathString ? null : new Path(annotationPathString); IPath newPath = BuildPathDialogAccess.configureExternalAnnotationsAttachment(fLibraryViewer.getControl().getShell(), annotationPath); if (null == newPath) { return; } fLibraryContentProvider.setAnnotationsPath(newPath.segmentCount() == 0 ? null : newPath, selection); } } } private static String findClasspathAttribute(IClasspathAttribute[] attributes, String name) { for(int i = attributes.length; --i >= 0;) { if(name.equals(attributes[i].getName())) { return attributes[i].getValue(); } } return null; } /* (non-Javadoc) * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent) */ @Override public void selectionChanged(SelectionChangedEvent event) { updateButtons(); } /** * Refresh the enable/disable state for the buttons. */ private void updateButtons() { IStructuredSelection selection = (IStructuredSelection) fLibraryViewer.getSelection(); fRemoveButton.setEnabled(!selection.isEmpty()); boolean enableUp = true, enableDown = true, allSource = true, allJavadoc = true, allAnnotations = true, allRoots = true; Object[] libraries = fLibraryContentProvider.getElements(null); if (selection.isEmpty() || libraries.length == 0) { enableUp = false; enableDown = false; } else { Object first = libraries[0]; Object last = libraries[libraries.length - 1]; for (Iterator<?> iter= selection.iterator(); iter.hasNext();) { Object element= iter.next(); Object lib; if (element instanceof SubElement) { allRoots = false; SubElement subElement= (SubElement)element; lib = (subElement).getParent().toLibraryLocation(); switch (subElement.getType()) { case SubElement.JAVADOC_URL: allSource = false; allAnnotations = false; break; case SubElement.SOURCE_PATH: allAnnotations = false; allJavadoc = false; break; case SubElement.EXTERNAL_ANNOTATIONS_PATH: allJavadoc = false; allSource = false; break; } } else { lib = element; allSource = false; allJavadoc = false; allAnnotations = false; } if (lib == first) { enableUp = false; } if (lib == last) { enableDown = false; } } } fUpButton.setEnabled(enableUp); fDownButton.setEnabled(enableDown); fJavadocButton.setEnabled(!selection.isEmpty() && (allJavadoc || allRoots)); fSourceButton.setEnabled(!selection.isEmpty() && (allSource || allRoots)); fAnnotationsButton.setEnabled(!selection.isEmpty() && (allAnnotations || allRoots)); } /* (non-Javadoc) * @see org.eclipse.jdt.debug.ui.launchConfigurations.AbstractVMInstallPage#finish() */ @Override public boolean finish() { if (fVmInstall != null) { if (isDefaultLocations(fVmInstall)) { fVmInstall.setLibraryLocations(null); } else { LibraryLocation[] libs = fLibraryContentProvider.getLibraries(); fVmInstall.setLibraryLocations(libs); } } return true; } /* (non-Javadoc) * @see org.eclipse.jdt.debug.ui.launchConfigurations.AbstractVMInstallPage#getSelection() */ @Override public VMStandin getSelection() { return fVmInstall; } /* (non-Javadoc) * @see org.eclipse.jdt.debug.ui.launchConfigurations.AbstractVMInstallPage#setSelection(org.eclipse.jdt.launching.VMStandin) */ @Override public void setSelection(VMStandin vm) { super.setSelection(vm); LibraryLocation[] libraryLocations = null; if (vm == null) { libraryLocations = new LibraryLocation[0]; } else { libraryLocations = JavaRuntime.getLibraryLocations(vm); } fVmInstall = vm; fLibraryContentProvider.setLibraries(libraryLocations); } /* (non-Javadoc) * @see org.eclipse.jdt.debug.ui.launchConfigurations.AbstractVMInstallPage#getVMStatus() */ @Override protected IStatus[] getVMStatus() { return fLibStatus; } }