001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.ui.wizards.buildpaths;
011:
012: import java.util.ArrayList;
013:
014: import org.eclipse.core.runtime.CoreException;
015: import org.eclipse.core.runtime.IPath;
016: import org.eclipse.core.runtime.IProgressMonitor;
017: import org.eclipse.core.runtime.IStatus;
018: import org.eclipse.core.runtime.Status;
019:
020: import org.eclipse.core.resources.ResourcesPlugin;
021:
022: import org.eclipse.swt.widgets.Shell;
023:
024: import org.eclipse.jface.dialogs.MessageDialog;
025:
026: import org.eclipse.jdt.core.ClasspathContainerInitializer;
027: import org.eclipse.jdt.core.IClasspathAttribute;
028: import org.eclipse.jdt.core.IClasspathContainer;
029: import org.eclipse.jdt.core.IClasspathEntry;
030: import org.eclipse.jdt.core.IJavaModel;
031: import org.eclipse.jdt.core.IJavaProject;
032: import org.eclipse.jdt.core.JavaCore;
033: import org.eclipse.jdt.core.JavaModelException;
034:
035: import org.eclipse.jdt.internal.corext.util.Messages;
036:
037: import org.eclipse.jdt.ui.JavaUI;
038:
039: import org.eclipse.jdt.internal.ui.JavaPlugin;
040: import org.eclipse.jdt.internal.ui.wizards.NewWizardMessages;
041:
042: /**
043: *
044: */
045: public class BuildPathSupport {
046:
047: public static final String JRE_PREF_PAGE_ID = "org.eclipse.jdt.debug.ui.preferences.VMPreferencePage"; //$NON-NLS-1$
048:
049: private BuildPathSupport() {
050: super ();
051: }
052:
053: /**
054: * Returns a deprecation message for a classpath variable name.
055: *
056: * @param variableName classpath variable name
057: * @return the deprecation message, or <code>null</code> iff
058: * <code>variableName</code> is not a classpath variable or the
059: * variable is not deprecated
060: */
061: public static String getDeprecationMessage(String variableName) {
062: String deprecationMessage = JavaCore
063: .getClasspathVariableDeprecationMessage(variableName);
064: if (deprecationMessage == null)
065: return null;
066: else
067: return Messages.format(
068: NewWizardMessages.BuildPathSupport_deprecated,
069: new Object[] { variableName, deprecationMessage });
070: }
071:
072: /**
073: * Finds a source attachment for a new archive in the existing classpaths.
074: * @param elem The new classpath entry
075: * @return A path to be taken for the source attachment or <code>null</code>
076: */
077: public static IPath guessSourceAttachment(CPListElement elem) {
078: if (elem.getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
079: return null;
080: }
081: IJavaProject currProject = elem.getJavaProject(); // can be null
082: try {
083: // try if the jar itself contains the source
084: IJavaModel jmodel = JavaCore.create(ResourcesPlugin
085: .getWorkspace().getRoot());
086: IJavaProject[] jprojects = jmodel.getJavaProjects();
087: for (int i = 0; i < jprojects.length; i++) {
088: IJavaProject curr = jprojects[i];
089: if (!curr.equals(currProject)) {
090: IClasspathEntry[] entries = curr.getRawClasspath();
091: for (int k = 0; k < entries.length; k++) {
092: IClasspathEntry entry = entries[k];
093: if (entry.getEntryKind() == elem.getEntryKind()
094: && entry.getPath().equals(
095: elem.getPath())) {
096: IPath attachPath = entry
097: .getSourceAttachmentPath();
098: if (attachPath != null
099: && !attachPath.isEmpty()) {
100: return attachPath;
101: }
102: }
103: }
104: }
105: }
106: } catch (JavaModelException e) {
107: JavaPlugin.log(e.getStatus());
108: }
109: return null;
110: }
111:
112: /**
113: * Finds a javadoc location for a new archive in the existing classpaths.
114: * @param elem The new classpath entry
115: * @return A javadoc location found in a similar classpath entry or <code>null</code>.
116: */
117: public static String guessJavadocLocation(CPListElement elem) {
118: if (elem.getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
119: return null;
120: }
121: IJavaProject currProject = elem.getJavaProject(); // can be null
122: try {
123: // try if the jar itself contains the source
124: IJavaModel jmodel = JavaCore.create(ResourcesPlugin
125: .getWorkspace().getRoot());
126: IJavaProject[] jprojects = jmodel.getJavaProjects();
127: for (int i = 0; i < jprojects.length; i++) {
128: IJavaProject curr = jprojects[i];
129: if (!curr.equals(currProject)) {
130: IClasspathEntry[] entries = curr.getRawClasspath();
131: for (int k = 0; k < entries.length; k++) {
132: IClasspathEntry entry = entries[k];
133: if (entry.getEntryKind() == elem.getEntryKind()
134: && entry.getPath().equals(
135: elem.getPath())) {
136: IClasspathAttribute[] attributes = entry
137: .getExtraAttributes();
138: for (int n = 0; n < attributes.length; n++) {
139: IClasspathAttribute attrib = attributes[n];
140: if (IClasspathAttribute.JAVADOC_LOCATION_ATTRIBUTE_NAME
141: .equals(attrib.getName())) {
142: return attrib.getValue();
143: }
144: }
145: }
146: }
147: }
148: }
149: } catch (JavaModelException e) {
150: JavaPlugin.log(e.getStatus());
151: }
152: return null;
153: }
154:
155: private static class UpdatedClasspathContainer implements
156: IClasspathContainer {
157:
158: private IClasspathEntry[] fNewEntries;
159: private IClasspathContainer fOriginal;
160:
161: public UpdatedClasspathContainer(IClasspathContainer original,
162: IClasspathEntry[] newEntries) {
163: fNewEntries = newEntries;
164: fOriginal = original;
165: }
166:
167: public IClasspathEntry[] getClasspathEntries() {
168: return fNewEntries;
169: }
170:
171: public String getDescription() {
172: return fOriginal.getDescription();
173: }
174:
175: public int getKind() {
176: return fOriginal.getKind();
177: }
178:
179: public IPath getPath() {
180: return fOriginal.getPath();
181: }
182: }
183:
184: /**
185: * Apply a modified classpath entry to the classpath. The classpath entry can also be from a classpath container.
186: * @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
187: * @param newEntry The modified entry. The entry's kind or path must be unchanged.
188: * @param changedAttributes The attibutes that have changed. See {@link CPListElement} for constants values.
189: * @param jproject Project where the entry belongs to
190: * @param containerPath The path of the entry's parent container or <code>null</code> if the entry is not in a container
191: * @param monitor The progress monitor to use
192: * @throws CoreException
193: */
194: public static void modifyClasspathEntry(Shell shell,
195: IClasspathEntry newEntry, String[] changedAttributes,
196: IJavaProject jproject, IPath containerPath,
197: IProgressMonitor monitor) throws CoreException {
198: if (containerPath != null) {
199: updateContainerClasspath(jproject, containerPath, newEntry,
200: changedAttributes, monitor);
201: } else {
202: updateProjectClasspath(shell, jproject, newEntry,
203: changedAttributes, monitor);
204: }
205: }
206:
207: /**
208: * Apply a modified classpath entry to the classpath. The classpath entry can also be from a classpath container.
209: * @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
210: * @param newEntry The modified entry. The entry's kind or path must be unchanged.
211: * @param jproject Project where the entry belongs to
212: * @param containerPath The path of the entry's parent container or <code>null</code> if the entry is not in a container
213: * @param monitor The progress monitor to use
214: * @throws CoreException
215: */
216: public static void modifyClasspathEntry(Shell shell,
217: IClasspathEntry newEntry, IJavaProject jproject,
218: IPath containerPath, IProgressMonitor monitor)
219: throws CoreException {
220: modifyClasspathEntry(shell, newEntry, null, jproject,
221: containerPath, monitor);
222: }
223:
224: private static void updateContainerClasspath(IJavaProject jproject,
225: IPath containerPath, IClasspathEntry newEntry,
226: String[] changedAttributes, IProgressMonitor monitor)
227: throws CoreException {
228: IClasspathContainer container = JavaCore.getClasspathContainer(
229: containerPath, jproject);
230: if (container == null) {
231: throw new CoreException(
232: new Status(
233: IStatus.ERROR,
234: JavaUI.ID_PLUGIN,
235: IStatus.ERROR,
236: "Container " + containerPath + " cannot be resolved", null)); //$NON-NLS-1$//$NON-NLS-2$
237: }
238: IClasspathEntry[] entries = container.getClasspathEntries();
239: IClasspathEntry[] newEntries = new IClasspathEntry[entries.length];
240: for (int i = 0; i < entries.length; i++) {
241: IClasspathEntry curr = entries[i];
242: if (curr.getEntryKind() == newEntry.getEntryKind()
243: && curr.getPath().equals(newEntry.getPath())) {
244: newEntries[i] = getUpdatedEntry(curr, newEntry,
245: changedAttributes, jproject);
246: } else {
247: newEntries[i] = curr;
248: }
249: }
250: requestContainerUpdate(jproject, container, newEntries);
251: monitor.worked(1);
252: }
253:
254: private static IClasspathEntry getUpdatedEntry(
255: IClasspathEntry currEntry, IClasspathEntry updatedEntry,
256: String[] updatedAttributes, IJavaProject jproject) {
257: if (updatedAttributes == null) {
258: return updatedEntry; // used updated entry 'as is'
259: }
260: CPListElement currElem = CPListElement.createFromExisting(
261: currEntry, jproject);
262: CPListElement newElem = CPListElement.createFromExisting(
263: updatedEntry, jproject);
264: for (int i = 0; i < updatedAttributes.length; i++) {
265: String attrib = updatedAttributes[i];
266: currElem.setAttribute(attrib, newElem.getAttribute(attrib));
267: }
268: return currElem.getClasspathEntry();
269: }
270:
271: /**
272: * Request a container update.
273: * @param jproject The project of the container
274: * @param container The container to requesta change to
275: * @param newEntries The updated entries
276: * @throws CoreException
277: */
278: public static void requestContainerUpdate(IJavaProject jproject,
279: IClasspathContainer container, IClasspathEntry[] newEntries)
280: throws CoreException {
281: IPath containerPath = container.getPath();
282: IClasspathContainer updatedContainer = new UpdatedClasspathContainer(
283: container, newEntries);
284: ClasspathContainerInitializer initializer = JavaCore
285: .getClasspathContainerInitializer(containerPath
286: .segment(0));
287: if (initializer != null) {
288: initializer.requestClasspathContainerUpdate(containerPath,
289: jproject, updatedContainer);
290: }
291: }
292:
293: private static void updateProjectClasspath(Shell shell,
294: IJavaProject jproject, IClasspathEntry newEntry,
295: String[] changedAttributes, IProgressMonitor monitor)
296: throws JavaModelException {
297: IClasspathEntry[] oldClasspath = jproject.getRawClasspath();
298: int nEntries = oldClasspath.length;
299: ArrayList newEntries = new ArrayList(nEntries + 1);
300: int entryKind = newEntry.getEntryKind();
301: IPath jarPath = newEntry.getPath();
302: boolean found = false;
303: for (int i = 0; i < nEntries; i++) {
304: IClasspathEntry curr = oldClasspath[i];
305: if (curr.getEntryKind() == entryKind
306: && curr.getPath().equals(jarPath)) {
307: // add modified entry
308: newEntries.add(getUpdatedEntry(curr, newEntry,
309: changedAttributes, jproject));
310: found = true;
311: } else {
312: newEntries.add(curr);
313: }
314: }
315: if (!found) {
316: if (!putJarOnClasspathDialog(shell)) {
317: return;
318: }
319: // add new
320: newEntries.add(newEntry);
321: }
322: IClasspathEntry[] newClasspath = (IClasspathEntry[]) newEntries
323: .toArray(new IClasspathEntry[newEntries.size()]);
324: jproject.setRawClasspath(newClasspath, monitor);
325: }
326:
327: private static boolean putJarOnClasspathDialog(final Shell shell) {
328: if (shell == null) {
329: return false;
330: }
331:
332: final boolean[] result = new boolean[1];
333: shell.getDisplay().syncExec(new Runnable() {
334: public void run() {
335: String title = NewWizardMessages.BuildPathSupport_putoncpdialog_title;
336: String message = NewWizardMessages.BuildPathSupport_putoncpdialog_message;
337: result[0] = MessageDialog.openQuestion(shell, title,
338: message);
339: }
340: });
341: return result[0];
342: }
343: }
|