| /******************************************************************************* |
| * Copyright (c) 2000, 2017 IBM Corporation and others. |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0. |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| *******************************************************************************/ |
| package org.eclipse.dltk.internal.ui.wizards.buildpath; |
| |
| import java.util.ArrayList; |
| |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.dltk.core.BuildpathContainerInitializer; |
| import org.eclipse.dltk.core.DLTKCore; |
| import org.eclipse.dltk.core.IBuildpathContainer; |
| import org.eclipse.dltk.core.IBuildpathEntry; |
| import org.eclipse.dltk.core.IScriptProject; |
| import org.eclipse.dltk.core.ModelException; |
| import org.eclipse.dltk.internal.ui.wizards.NewWizardMessages; |
| import org.eclipse.dltk.ui.DLTKUIPlugin; |
| import org.eclipse.jface.dialogs.MessageDialog; |
| import org.eclipse.swt.widgets.Shell; |
| |
| /** |
| * |
| */ |
| public class BuildPathSupport { |
| |
| public static final String InterpreterEnvironment_PREF_PAGE_ID = "org.eclipse.dltk.debug.ui.preferences.InterpreterPreferencePage"; //$NON-NLS-1$ |
| |
| private BuildPathSupport() { |
| super(); |
| } |
| |
| private static class UpdatedBuildpathContainer |
| implements IBuildpathContainer { |
| |
| private IBuildpathEntry[] fNewEntries; |
| private IBuildpathContainer fOriginal; |
| |
| public UpdatedBuildpathContainer(IBuildpathContainer original, |
| IBuildpathEntry[] newEntries) { |
| fNewEntries = newEntries; |
| fOriginal = original; |
| } |
| |
| @Override |
| public IBuildpathEntry[] getBuildpathEntries() { |
| return fNewEntries; |
| } |
| |
| @Override |
| public String getDescription() { |
| return fOriginal.getDescription(); |
| } |
| |
| @Override |
| public int getKind() { |
| return fOriginal.getKind(); |
| } |
| |
| @Override |
| public IPath getPath() { |
| return fOriginal.getPath(); |
| } |
| |
| } |
| |
| /** |
| * Apply a modified buildpath entry to the buildpath. The buildpath entry |
| * can also be from a buildpath container. |
| * |
| * @param shell |
| * If not null and the entry could not be found on the projects |
| * buildpath, a dialog will ask to put the entry on the buildpath |
| * @param newEntry |
| * The modified entry. The entry's kind or path must be |
| * unchanged. |
| * @param changedAttributes |
| * The attibutes that have changed. See {@link BPListElement} for |
| * constants values. |
| * @param jproject |
| * Project where the entry belongs to |
| * @param containerPath |
| * The path of the entry's parent container or <code>null</code> |
| * if the entry is not in a container |
| * @param monitor |
| * The progress monitor to use |
| * @throws CoreException |
| */ |
| public static void modifyBuildpathEntry(Shell shell, |
| IBuildpathEntry newEntry, String[] changedAttributes, |
| IScriptProject jproject, IPath containerPath, |
| IProgressMonitor monitor) throws CoreException { |
| if (containerPath != null) { |
| updateContainerBuildpath(jproject, containerPath, newEntry, |
| changedAttributes, monitor); |
| } else { |
| updateProjectBuildpath(shell, jproject, newEntry, changedAttributes, |
| monitor); |
| } |
| } |
| |
| /** |
| * Apply a modified buildpath entry to the buildpath. The buildpath entry |
| * can also be from a buildpath container. |
| * |
| * @param shell |
| * If not null and the entry could not be found on the projects |
| * buildpath, a dialog will ask to put the entry on the buildpath |
| * @param newEntry |
| * The modified entry. The entry's kind or path must be |
| * unchanged. |
| * @param jproject |
| * Project where the entry belongs to |
| * @param containerPath |
| * The path of the entry's parent container or <code>null</code> |
| * if the entry is not in a container |
| * @param monitor |
| * The progress monitor to use |
| * @throws CoreException |
| */ |
| public static void modifyBuildpathEntry(Shell shell, |
| IBuildpathEntry newEntry, IScriptProject jproject, |
| IPath containerPath, IProgressMonitor monitor) |
| throws CoreException { |
| modifyBuildpathEntry(shell, newEntry, null, jproject, containerPath, |
| monitor); |
| } |
| |
| private static void updateContainerBuildpath(IScriptProject project, |
| IPath containerPath, IBuildpathEntry newEntry, |
| String[] changedAttributes, IProgressMonitor monitor) |
| throws CoreException { |
| IBuildpathContainer container = DLTKCore |
| .getBuildpathContainer(containerPath, project); |
| if (container == null) { |
| throw new CoreException(new Status(IStatus.ERROR, |
| DLTKUIPlugin.PLUGIN_ID, IStatus.ERROR, |
| "Container " + containerPath + " cannot be resolved", //$NON-NLS-1$//$NON-NLS-2$ |
| null)); |
| } |
| IBuildpathEntry[] entries = container.getBuildpathEntries(); |
| IBuildpathEntry[] newEntries = new IBuildpathEntry[entries.length]; |
| for (int i = 0; i < entries.length; i++) { |
| IBuildpathEntry curr = entries[i]; |
| if (curr.getEntryKind() == newEntry.getEntryKind() |
| && curr.getPath().equals(newEntry.getPath())) { |
| newEntries[i] = getUpdatedEntry(curr, newEntry, |
| changedAttributes, project); |
| } else { |
| newEntries[i] = curr; |
| } |
| } |
| requestContainerUpdate(project, container, newEntries); |
| monitor.worked(1); |
| } |
| |
| private static IBuildpathEntry getUpdatedEntry(IBuildpathEntry currEntry, |
| IBuildpathEntry updatedEntry, String[] updatedAttributes, |
| IScriptProject jproject) { |
| if (updatedAttributes == null) { |
| return updatedEntry; // used updated entry 'as is' |
| } |
| BPListElement currElem = BPListElement.createFromExisting(currEntry, |
| jproject); |
| BPListElement newElem = BPListElement.createFromExisting(updatedEntry, |
| jproject); |
| for (int i = 0; i < updatedAttributes.length; i++) { |
| String attrib = updatedAttributes[i]; |
| currElem.setAttribute(attrib, newElem.getAttribute(attrib)); |
| } |
| return currElem.getBuildpathEntry(); |
| } |
| |
| /** |
| * Request a container update. |
| * |
| * @param jproject |
| * The project of the container |
| * @param container |
| * The container to requesta change to |
| * @param newEntries |
| * The updated entries |
| * @throws CoreException |
| */ |
| public static void requestContainerUpdate(IScriptProject jproject, |
| IBuildpathContainer container, IBuildpathEntry[] newEntries) |
| throws CoreException { |
| IPath containerPath = container.getPath(); |
| IBuildpathContainer updatedContainer = new UpdatedBuildpathContainer( |
| container, newEntries); |
| BuildpathContainerInitializer initializer = DLTKCore |
| .getBuildpathContainerInitializer(containerPath.segment(0)); |
| if (initializer != null) { |
| initializer.requestBuildpathContainerUpdate(containerPath, jproject, |
| updatedContainer); |
| if (DLTKCore.DEBUG) { |
| System.err.println( |
| "BuildPathSupport: Add user library preference page container"); //$NON-NLS-1$ |
| // initializer.requestBuildpathContainerUpdate(containerPath, |
| // UserLibraryPreferencePage.getPlaceholderProject(), |
| // updatedContainer); |
| // DLTKCore.setBuildpathContainer(containerPath, new |
| // IScriptProject[] {jproject, |
| // UserLibraryPreferencePage.getPlaceholderProject()}, new |
| // IBuildpathContainer[] {updatedContainer, updatedContainer}, |
| // null); // force updating of containers, bug 62250 |
| } |
| } |
| } |
| |
| private static void updateProjectBuildpath(Shell shell, |
| IScriptProject jproject, IBuildpathEntry newEntry, |
| String[] changedAttributes, IProgressMonitor monitor) |
| throws ModelException { |
| IBuildpathEntry[] oldBuildpath = jproject.getRawBuildpath(); |
| int nEntries = oldBuildpath.length; |
| ArrayList<IBuildpathEntry> newEntries = new ArrayList<>(nEntries + 1); |
| int entryKind = newEntry.getEntryKind(); |
| IPath archivePath = newEntry.getPath(); |
| boolean found = false; |
| for (int i = 0; i < nEntries; i++) { |
| IBuildpathEntry curr = oldBuildpath[i]; |
| if (curr.getEntryKind() == entryKind |
| && curr.getPath().equals(archivePath)) { |
| // add modified entry |
| newEntries.add(getUpdatedEntry(curr, newEntry, |
| changedAttributes, jproject)); |
| found = true; |
| } else { |
| newEntries.add(curr); |
| } |
| } |
| if (!found) { |
| if (!putArchiveOnBuildpathDialog(shell)) { |
| return; |
| } |
| // add new |
| newEntries.add(newEntry); |
| } |
| IBuildpathEntry[] newBuildpath = newEntries |
| .toArray(new IBuildpathEntry[newEntries.size()]); |
| jproject.setRawBuildpath(newBuildpath, monitor); |
| } |
| |
| private static boolean putArchiveOnBuildpathDialog(final Shell shell) { |
| if (shell == null) { |
| return false; |
| } |
| |
| final boolean[] result = new boolean[1]; |
| shell.getDisplay().syncExec(() -> { |
| String title = NewWizardMessages.BuildPathSupport_putoncpdialog_title; |
| String message = NewWizardMessages.BuildPathSupport_putoncpdialog_message; |
| result[0] = MessageDialog.openQuestion(shell, title, message); |
| }); |
| return result[0]; |
| } |
| } |