/******************************************************************************* * 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 * http://www.eclipse.org/legal/epl-v10.html * *******************************************************************************/ 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]; } }