Java tutorial
/******************************************************************************* * Copyright (c) 2000, 2006 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 descent.internal.ui.wizards.buildpaths; 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.core.resources.ResourcesPlugin; import org.eclipse.swt.widgets.Shell; import org.eclipse.jface.dialogs.MessageDialog; import descent.core.ClasspathContainerInitializer; import descent.core.IClasspathAttribute; import descent.core.IClasspathContainer; import descent.core.IClasspathEntry; import descent.core.IJavaModel; import descent.core.IJavaProject; import descent.core.JavaCore; import descent.core.JavaModelException; import descent.ui.JavaUI; import descent.internal.ui.JavaPlugin; import descent.internal.ui.wizards.NewWizardMessages; /** * */ public class BuildPathSupport { public static final String JRE_PREF_PAGE_ID = "descent.debug.ui.preferences.VMPreferencePage"; //$NON-NLS-1$ private BuildPathSupport() { super(); } /** * Finds a source attachment for a new archive in the existing classpaths. * @param elem The new classpath entry * @return A path to be taken for the source attachment or <code>null</code> */ public static IPath guessSourceAttachment(CPListElement elem) { if (elem.getEntryKind() == IClasspathEntry.CPE_CONTAINER) { return null; } IJavaProject currProject = elem.getJavaProject(); // can be null try { // try if the jar itself contains the source IJavaModel jmodel = JavaCore.create(ResourcesPlugin.getWorkspace().getRoot()); IJavaProject[] jprojects = jmodel.getJavaProjects(); for (int i = 0; i < jprojects.length; i++) { IJavaProject curr = jprojects[i]; if (!curr.equals(currProject)) { IClasspathEntry[] entries = curr.getRawClasspath(); for (int k = 0; k < entries.length; k++) { IClasspathEntry entry = entries[k]; if (entry.getEntryKind() == elem.getEntryKind() && entry.getPath().equals(elem.getPath())) { IPath attachPath = entry.getSourceAttachmentPath(); if (attachPath != null && !attachPath.isEmpty()) { return attachPath; } } } } } } catch (JavaModelException e) { JavaPlugin.log(e.getStatus()); } return null; } /** * Finds a javadoc location for a new archive in the existing classpaths. * @param elem The new classpath entry * @return A javadoc location found in a similar classpath entry or <code>null</code>. */ public static String guessJavadocLocation(CPListElement elem) { if (elem.getEntryKind() == IClasspathEntry.CPE_CONTAINER) { return null; } IJavaProject currProject = elem.getJavaProject(); // can be null try { // try if the jar itself contains the source IJavaModel jmodel = JavaCore.create(ResourcesPlugin.getWorkspace().getRoot()); IJavaProject[] jprojects = jmodel.getJavaProjects(); for (int i = 0; i < jprojects.length; i++) { IJavaProject curr = jprojects[i]; if (!curr.equals(currProject)) { IClasspathEntry[] entries = curr.getRawClasspath(); for (int k = 0; k < entries.length; k++) { IClasspathEntry entry = entries[k]; if (entry.getEntryKind() == elem.getEntryKind() && entry.getPath().equals(elem.getPath())) { IClasspathAttribute[] attributes = entry.getExtraAttributes(); for (int n = 0; n < attributes.length; n++) { IClasspathAttribute attrib = attributes[n]; if (IClasspathAttribute.JAVADOC_LOCATION_ATTRIBUTE_NAME.equals(attrib.getName())) { return attrib.getValue(); } } } } } } } catch (JavaModelException e) { JavaPlugin.log(e.getStatus()); } return null; } private static class UpdatedClasspathContainer implements IClasspathContainer { private IClasspathEntry[] fNewEntries; private IClasspathContainer fOriginal; public UpdatedClasspathContainer(IClasspathContainer original, IClasspathEntry[] newEntries) { fNewEntries = newEntries; fOriginal = original; } public IClasspathEntry[] getClasspathEntries() { return fNewEntries; } public String getDescription() { return fOriginal.getDescription(); } public int getKind() { return fOriginal.getKind(); } public IPath getPath() { return fOriginal.getPath(); } } /** * Apply a modified classpath entry to the classpath. The classpath entry can also be from a classpath container. * @param shell If not null and the entry could not be found on the projects classpath, a dialog will ask to put the entry on the classpath * @param newEntry The modified entry. The entry's kind or path must be unchanged. * @param changedAttributes The attibutes that have changed. See {@link CPListElement} 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 modifyClasspathEntry(Shell shell, IClasspathEntry newEntry, String[] changedAttributes, IJavaProject jproject, IPath containerPath, IProgressMonitor monitor) throws CoreException { if (containerPath != null) { updateContainerClasspath(jproject, containerPath, newEntry, changedAttributes, monitor); } else { updateProjectClasspath(shell, jproject, newEntry, changedAttributes, monitor); } } /** * Apply a modified classpath entry to the classpath. The classpath entry can also be from a classpath container. * @param shell If not null and the entry could not be found on the projects classpath, a dialog will ask to put the entry on the classpath * @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 modifyClasspathEntry(Shell shell, IClasspathEntry newEntry, IJavaProject jproject, IPath containerPath, IProgressMonitor monitor) throws CoreException { modifyClasspathEntry(shell, newEntry, null, jproject, containerPath, monitor); } private static void updateContainerClasspath(IJavaProject jproject, IPath containerPath, IClasspathEntry newEntry, String[] changedAttributes, IProgressMonitor monitor) throws CoreException { IClasspathContainer container = JavaCore.getClasspathContainer(containerPath, jproject); if (container == null) { throw new CoreException(new Status(IStatus.ERROR, JavaUI.ID_PLUGIN, IStatus.ERROR, "Container " + containerPath + " cannot be resolved", null)); //$NON-NLS-1$//$NON-NLS-2$ } IClasspathEntry[] entries = container.getClasspathEntries(); IClasspathEntry[] newEntries = new IClasspathEntry[entries.length]; for (int i = 0; i < entries.length; i++) { IClasspathEntry curr = entries[i]; if (curr.getEntryKind() == newEntry.getEntryKind() && curr.getPath().equals(newEntry.getPath())) { newEntries[i] = getUpdatedEntry(curr, newEntry, changedAttributes, jproject); } else { newEntries[i] = curr; } } requestContainerUpdate(jproject, container, newEntries); monitor.worked(1); } private static IClasspathEntry getUpdatedEntry(IClasspathEntry currEntry, IClasspathEntry updatedEntry, String[] updatedAttributes, IJavaProject jproject) { if (updatedAttributes == null) { return updatedEntry; // used updated entry 'as is' } CPListElement currElem = CPListElement.createFromExisting(currEntry, jproject); CPListElement newElem = CPListElement.createFromExisting(updatedEntry, jproject); for (int i = 0; i < updatedAttributes.length; i++) { String attrib = updatedAttributes[i]; currElem.setAttribute(attrib, newElem.getAttribute(attrib)); } return currElem.getClasspathEntry(); } /** * 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(IJavaProject jproject, IClasspathContainer container, IClasspathEntry[] newEntries) throws CoreException { IPath containerPath = container.getPath(); IClasspathContainer updatedContainer = new UpdatedClasspathContainer(container, newEntries); ClasspathContainerInitializer initializer = JavaCore .getClasspathContainerInitializer(containerPath.segment(0)); if (initializer != null) { initializer.requestClasspathContainerUpdate(containerPath, jproject, updatedContainer); } } private static void updateProjectClasspath(Shell shell, IJavaProject jproject, IClasspathEntry newEntry, String[] changedAttributes, IProgressMonitor monitor) throws JavaModelException { IClasspathEntry[] oldClasspath = jproject.getRawClasspath(); int nEntries = oldClasspath.length; ArrayList newEntries = new ArrayList(nEntries + 1); int entryKind = newEntry.getEntryKind(); IPath jarPath = newEntry.getPath(); boolean found = false; for (int i = 0; i < nEntries; i++) { IClasspathEntry curr = oldClasspath[i]; if (curr.getEntryKind() == entryKind && curr.getPath().equals(jarPath)) { // add modified entry newEntries.add(getUpdatedEntry(curr, newEntry, changedAttributes, jproject)); found = true; } else { newEntries.add(curr); } } if (!found) { if (!putJarOnClasspathDialog(shell)) { return; } // add new newEntries.add(newEntry); } IClasspathEntry[] newClasspath = (IClasspathEntry[]) newEntries .toArray(new IClasspathEntry[newEntries.size()]); jproject.setRawClasspath(newClasspath, monitor); } private static boolean putJarOnClasspathDialog(final Shell shell) { if (shell == null) { return false; } final boolean[] result = new boolean[1]; shell.getDisplay().syncExec(new Runnable() { public void run() { String title = NewWizardMessages.BuildPathSupport_putoncpdialog_title; String message = NewWizardMessages.BuildPathSupport_putoncpdialog_message; result[0] = MessageDialog.openQuestion(shell, title, message); } }); return result[0]; } }