KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > corext > buildpath > ClasspathModifier


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  * Matt Chapman, mpchapman@gmail.com - 89977 Make JDT .java agnostic
11  *******************************************************************************/

12 package org.eclipse.jdt.internal.corext.buildpath;
13
14 import java.net.URI JavaDoc;
15 import java.util.ArrayList JavaDoc;
16 import java.util.Collections JavaDoc;
17 import java.util.Iterator JavaDoc;
18 import java.util.List JavaDoc;
19
20 import org.eclipse.core.filesystem.EFS;
21 import org.eclipse.core.filesystem.IFileStore;
22
23 import org.eclipse.core.runtime.CoreException;
24 import org.eclipse.core.runtime.IPath;
25 import org.eclipse.core.runtime.IProgressMonitor;
26 import org.eclipse.core.runtime.IStatus;
27 import org.eclipse.core.runtime.MultiStatus;
28 import org.eclipse.core.runtime.NullProgressMonitor;
29 import org.eclipse.core.runtime.OperationCanceledException;
30 import org.eclipse.core.runtime.Path;
31 import org.eclipse.core.runtime.SubProgressMonitor;
32
33 import org.eclipse.core.resources.IContainer;
34 import org.eclipse.core.resources.IFile;
35 import org.eclipse.core.resources.IFolder;
36 import org.eclipse.core.resources.IProject;
37 import org.eclipse.core.resources.IResource;
38 import org.eclipse.core.resources.IWorkspace;
39 import org.eclipse.core.resources.IWorkspaceRoot;
40 import org.eclipse.core.resources.ResourcesPlugin;
41
42 import org.eclipse.jdt.core.IClasspathEntry;
43 import org.eclipse.jdt.core.IJavaElement;
44 import org.eclipse.jdt.core.IJavaModelStatus;
45 import org.eclipse.jdt.core.IJavaProject;
46 import org.eclipse.jdt.core.IPackageFragment;
47 import org.eclipse.jdt.core.IPackageFragmentRoot;
48 import org.eclipse.jdt.core.JavaConventions;
49 import org.eclipse.jdt.core.JavaCore;
50 import org.eclipse.jdt.core.JavaModelException;
51
52 import org.eclipse.jdt.internal.corext.util.Messages;
53
54 import org.eclipse.jdt.ui.PreferenceConstants;
55
56 import org.eclipse.jdt.internal.ui.dialogs.StatusInfo;
57 import org.eclipse.jdt.internal.ui.wizards.NewWizardMessages;
58 import org.eclipse.jdt.internal.ui.wizards.buildpaths.ArchiveFileFilter;
59 import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListElement;
60 import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListElementAttribute;
61 import org.eclipse.jdt.internal.ui.wizards.buildpaths.newsourcepage.ClasspathModifierQueries.OutputFolderValidator;
62
63 public class ClasspathModifier {
64
65     private ClasspathModifier() {}
66     
67     public static BuildpathDelta setOutputLocation(CPListElement elementToChange, IPath outputPath, boolean allowInvalidCP, CPJavaProject cpProject) throws CoreException {
68         BuildpathDelta result= new BuildpathDelta(NewWizardMessages.NewSourceContainerWorkbookPage_ToolBar_EditOutput_tooltip);
69         
70         IJavaProject javaProject= cpProject.getJavaProject();
71         IProject project= javaProject.getProject();
72         IWorkspace workspace= project.getWorkspace();
73         
74         IPath projectPath= project.getFullPath();
75         
76         if (!allowInvalidCP && cpProject.getDefaultOutputLocation().segmentCount() == 1 && !projectPath.equals(elementToChange.getPath())) {
77             String JavaDoc outputFolderName= PreferenceConstants.getPreferenceStore().getString(PreferenceConstants.SRCBIN_BINNAME);
78             cpProject.setDefaultOutputLocation(cpProject.getDefaultOutputLocation().append(outputFolderName));
79             List JavaDoc existingEntries= cpProject.getCPListElements();
80             CPListElement elem= ClasspathModifier.getListElement(javaProject.getPath(), existingEntries);
81             if (elem != null) {
82                 existingEntries.remove(elem);
83                 result.removeEntry(elem);
84             }
85         }
86         
87         if (outputPath != null)
88             exclude(outputPath, cpProject.getCPListElements(), new ArrayList JavaDoc(), cpProject.getJavaProject(), null);
89         
90         IPath oldOutputLocation= (IPath)elementToChange.getAttribute(CPListElement.OUTPUT);
91         if (oldOutputLocation != null && oldOutputLocation.segmentCount() > 1 && !oldOutputLocation.equals(cpProject.getDefaultOutputLocation())) {
92             include(cpProject, oldOutputLocation);
93             result.addDeletedResource(workspace.getRoot().getFolder(oldOutputLocation));
94         }
95         elementToChange.setAttribute(CPListElement.OUTPUT, outputPath);
96         
97         result.setDefaultOutputLocation(cpProject.getDefaultOutputLocation());
98         result.setNewEntries((CPListElement[])cpProject.getCPListElements().toArray(new CPListElement[cpProject.getCPListElements().size()]));
99         if (outputPath != null && outputPath.segmentCount() > 1) {
100             result.addCreatedResource(workspace.getRoot().getFolder(outputPath));
101         }
102         
103         return result;
104     }
105
106     public static IStatus checkSetOutputLocationPrecondition(CPListElement elementToChange, IPath outputPath, boolean allowInvalidCP, CPJavaProject cpProject) throws CoreException {
107         IJavaProject javaProject= cpProject.getJavaProject();
108         IProject project= javaProject.getProject();
109         IWorkspace workspace= project.getWorkspace();
110         
111         IPath projectPath= project.getFullPath();
112         
113         if (outputPath == null)
114             outputPath= cpProject.getDefaultOutputLocation();
115                         
116         IStatus pathValidation= workspace.validatePath(outputPath.toString(), IResource.PROJECT | IResource.FOLDER);
117         if (!pathValidation.isOK())
118             return new StatusInfo(IStatus.ERROR, Messages.format(NewWizardMessages.OutputLocationDialog_error_invalidpath, pathValidation.getMessage()));
119         
120         IWorkspaceRoot root= workspace.getRoot();
121         IResource res= root.findMember(outputPath);
122         if (res != null) {
123             // if exists, must be a folder or project
124
if (res.getType() == IResource.FILE)
125                 return new StatusInfo(IStatus.ERROR, NewWizardMessages.OutputLocationDialog_error_existingisfile);
126         }
127         
128         IStatus result= StatusInfo.OK_STATUS;
129         
130         int index= cpProject.indexOf(elementToChange);
131         cpProject= cpProject.createWorkingCopy();
132         elementToChange= cpProject.get(index);
133         
134         if (!allowInvalidCP && cpProject.getDefaultOutputLocation().segmentCount() == 1 && !projectPath.equals(elementToChange.getPath())) {
135             String JavaDoc outputFolderName= PreferenceConstants.getPreferenceStore().getString(PreferenceConstants.SRCBIN_BINNAME);
136             cpProject.setDefaultOutputLocation(cpProject.getDefaultOutputLocation().append(outputFolderName));
137             ClasspathModifier.removeFromClasspath(javaProject, cpProject.getCPListElements(), null);
138             result= new StatusInfo(IStatus.INFO, Messages.format(NewWizardMessages.OutputLocationDialog_removeProjectFromBP, cpProject.getDefaultOutputLocation()));
139         }
140         
141         exclude(outputPath, cpProject.getCPListElements(), new ArrayList JavaDoc(), cpProject.getJavaProject(), null);
142         
143         IPath oldOutputLocation= (IPath)elementToChange.getAttribute(CPListElement.OUTPUT);
144         if (oldOutputLocation != null && oldOutputLocation.segmentCount() > 1 && !oldOutputLocation.equals(cpProject.getDefaultOutputLocation())) {
145             include(cpProject, oldOutputLocation);
146         }
147         elementToChange.setAttribute(CPListElement.OUTPUT, outputPath);
148         
149         IJavaModelStatus status= JavaConventions.validateClasspath(javaProject, cpProject.getClasspathEntries(), cpProject.getDefaultOutputLocation());
150         if (!status.isOK()) {
151             if (allowInvalidCP) {
152                 return new StatusInfo(IStatus.WARNING, status.getMessage());
153             } else {
154                 return new StatusInfo(IStatus.ERROR, status.getMessage());
155             }
156         }
157         
158         if (outputPath.segmentCount() - projectPath.segmentCount() < 1)
159             return result;
160         
161         String JavaDoc lastSegment= outputPath.lastSegment();
162         if (lastSegment == null)
163             return result;
164         
165         if (lastSegment.equals(".settings") && outputPath.segmentCount() - projectPath.segmentCount() == 1) { //$NON-NLS-1$
166

167             StatusInfo statusInfo= new StatusInfo(IStatus.WARNING, NewWizardMessages.OutputLocation_SettingsAsLocation);
168             if (result.isOK()) {
169                 return statusInfo;
170             } else {
171                 MultiStatus ms= new MultiStatus(result.getPlugin(), result.getCode(), new IStatus[] {result, statusInfo}, statusInfo.getMessage(), null);
172                 return ms;
173             }
174         }
175         
176         if (lastSegment.length() > 1 && lastSegment.charAt(0) == '.') {
177             StatusInfo statusInfo= new StatusInfo(IStatus.WARNING, Messages.format(NewWizardMessages.OutputLocation_DotAsLocation, outputPath.toString()));
178             if (result.isOK()) {
179                 return statusInfo;
180             } else {
181                 MultiStatus ms= new MultiStatus(result.getPlugin(), result.getCode(), new IStatus[] {result, statusInfo}, statusInfo.getMessage(), null);
182                 return ms;
183             }
184         }
185         
186         return result;
187     }
188     
189     public static IStatus checkAddExternalJarsPrecondition(IPath[] absolutePaths, CPJavaProject cpProject) throws CoreException {
190         IStatus result= StatusInfo.OK_STATUS;
191         
192         IJavaProject javaProject= cpProject.getJavaProject();
193         
194         List JavaDoc newEntries= new ArrayList JavaDoc();
195         List JavaDoc duplicateEntries= new ArrayList JavaDoc();
196         List JavaDoc existingEntries= cpProject.getCPListElements();
197         for (int i= 0; i < absolutePaths.length; i++) {
198             CPListElement newEntry= new CPListElement(javaProject, IClasspathEntry.CPE_LIBRARY, absolutePaths[i], null);
199             if (existingEntries.contains(newEntry)) {
200                 duplicateEntries.add(newEntry);
201             } else {
202                 newEntries.add(newEntry);
203             }
204         }
205         
206         if (duplicateEntries.size() > 0) {
207             String JavaDoc message;
208             if (duplicateEntries.size() > 1) {
209                 StringBuffer JavaDoc buf= new StringBuffer JavaDoc();
210                 for (Iterator JavaDoc iterator= duplicateEntries.iterator(); iterator.hasNext();) {
211                     CPListElement dup= (CPListElement)iterator.next();
212                     buf.append('\n').append(dup.getPath().lastSegment());
213                 }
214                 message= Messages.format(NewWizardMessages.AddArchiveToBuildpathAction_DuplicateArchivesInfo_message, buf.toString());
215             } else {
216                 message= Messages.format(NewWizardMessages.AddArchiveToBuildpathAction_DuplicateArchiveInfo_message, ((CPListElement)duplicateEntries.get(0)).getPath().lastSegment());
217             }
218             result= new StatusInfo(IStatus.INFO, message);
219         }
220         
221         if (newEntries.size() == 0)
222             return result;
223         
224         cpProject= cpProject.createWorkingCopy();
225         existingEntries= cpProject.getCPListElements();
226     
227         for (Iterator JavaDoc iterator= newEntries.iterator(); iterator.hasNext();) {
228             CPListElement newEntry= (CPListElement)iterator.next();
229             insertAtEndOfCategory(newEntry, existingEntries);
230         }
231         
232         IJavaModelStatus cpStatus= JavaConventions.validateClasspath(javaProject, cpProject.getClasspathEntries(), cpProject.getDefaultOutputLocation());
233         if (!cpStatus.isOK())
234             return cpStatus;
235         
236         return result;
237     }
238     
239     public static BuildpathDelta addExternalJars(IPath[] absolutePaths, CPJavaProject cpProject) throws CoreException {
240         BuildpathDelta result= new BuildpathDelta(NewWizardMessages.NewSourceContainerWorkbookPage_ToolBar_AddJarCP_tooltip);
241         
242         IJavaProject javaProject= cpProject.getJavaProject();
243         
244         List JavaDoc existingEntries= cpProject.getCPListElements();
245         for (int i= 0; i < absolutePaths.length; i++) {
246             CPListElement newEntry= new CPListElement(javaProject, IClasspathEntry.CPE_LIBRARY, absolutePaths[i], null);
247             if (!existingEntries.contains(newEntry)) {
248                 insertAtEndOfCategory(newEntry, existingEntries);
249                 result.addEntry(newEntry);
250             }
251         }
252         
253         result.setNewEntries((CPListElement[])existingEntries.toArray(new CPListElement[existingEntries.size()]));
254         result.setDefaultOutputLocation(cpProject.getDefaultOutputLocation());
255         return result;
256     }
257     
258     public static BuildpathDelta removeFromBuildpath(CPListElement[] toRemove, CPJavaProject cpProject) {
259         
260         IJavaProject javaProject= cpProject.getJavaProject();
261         IPath projectPath= javaProject.getPath();
262         IWorkspaceRoot workspaceRoot= javaProject.getProject().getWorkspace().getRoot();
263         
264         List JavaDoc existingEntries= cpProject.getCPListElements();
265         BuildpathDelta result= new BuildpathDelta(NewWizardMessages.NewSourceContainerWorkbookPage_ToolBar_RemoveFromCP_tooltip);
266         
267         for (int i= 0; i < toRemove.length; i++) {
268             CPListElement element= toRemove[i];
269             existingEntries.remove(element);
270             result.removeEntry(element);
271             IPath path= element.getPath();
272             removeFilters(path, javaProject, existingEntries);
273             if (!path.equals(projectPath)) {
274                 IResource member= workspaceRoot.findMember(path);
275                 if (member != null)
276                     result.addDeletedResource(member);
277             } else if (cpProject.getDefaultOutputLocation().equals(projectPath) && containsSourceFolders(cpProject)) {
278                 String JavaDoc outputFolderName= PreferenceConstants.getPreferenceStore().getString(PreferenceConstants.SRCBIN_BINNAME);
279                 cpProject.setDefaultOutputLocation(cpProject.getDefaultOutputLocation().append(outputFolderName));
280             }
281         }
282         
283         result.setDefaultOutputLocation(cpProject.getDefaultOutputLocation());
284         result.setNewEntries((CPListElement[])existingEntries.toArray(new CPListElement[existingEntries.size()]));
285
286         return result;
287     }
288     
289     private static boolean containsSourceFolders(CPJavaProject cpProject) {
290         List JavaDoc elements= cpProject.getCPListElements();
291         for (Iterator JavaDoc iterator= elements.iterator(); iterator.hasNext();) {
292             CPListElement element= (CPListElement)iterator.next();
293             if (element.getEntryKind() == IClasspathEntry.CPE_SOURCE)
294                 return true;
295         }
296         return false;
297     }
298
299     private static void include(CPJavaProject cpProject, IPath path) {
300         List JavaDoc elements= cpProject.getCPListElements();
301         for (Iterator JavaDoc iterator= elements.iterator(); iterator.hasNext();) {
302             CPListElement element= (CPListElement)iterator.next();
303             element.removeFromExclusions(path);
304         }
305     }
306
307     /**
308      * Get the <code>IClasspathEntry</code> from the project and
309      * convert it into a list of <code>CPListElement</code>s.
310      *
311      * @param project the Java project to get it's build path entries from
312      * @return a list of <code>CPListElement</code>s corresponding to the
313      * build path entries of the project
314      * @throws JavaModelException
315      */

316     public static List JavaDoc getExistingEntries(IJavaProject project) throws JavaModelException {
317         IClasspathEntry[] classpathEntries= project.getRawClasspath();
318         ArrayList JavaDoc newClassPath= new ArrayList JavaDoc();
319         for (int i= 0; i < classpathEntries.length; i++) {
320             IClasspathEntry curr= classpathEntries[i];
321             newClassPath.add(CPListElement.createFromExisting(curr, project));
322         }
323         return newClassPath;
324     }
325
326     /**
327      * Try to find the corresponding and modified <code>CPListElement</code> for the root
328      * in the list of elements and return it.
329      * If no one can be found, the roots <code>ClasspathEntry</code> is converted to a
330      * <code>CPListElement</code> and returned.
331      *
332      * @param elements a list of <code>CPListElements</code>
333      * @param root the root to find the <code>ClasspathEntry</code> for represented by
334      * a <code>CPListElement</code>
335      * @return the <code>CPListElement</code> found in the list (matching by using the path) or
336      * the roots own <code>IClasspathEntry</code> converted to a <code>CPListElement</code>.
337      * @throws JavaModelException
338      */

339     public static CPListElement getClasspathEntry(List JavaDoc elements, IPackageFragmentRoot root) throws JavaModelException {
340         IClasspathEntry entry= root.getRawClasspathEntry();
341         for (int i= 0; i < elements.size(); i++) {
342             CPListElement element= (CPListElement) elements.get(i);
343             if (element.getPath().equals(root.getPath()) && element.getEntryKind() == entry.getEntryKind())
344                 return (CPListElement) elements.get(i);
345         }
346         CPListElement newElement= CPListElement.createFromExisting(entry, root.getJavaProject());
347         elements.add(newElement);
348         return newElement;
349     }
350
351     /**
352      * For a given <code>IResource</code>, try to
353      * convert it into a <code>IPackageFragmentRoot</code>
354      * if possible or return <code>null</code> if no
355      * fragment root could be created.
356      *
357      * @param resource the resource to be converted
358      * @return the <code>resource<code> as
359      * <code>IPackageFragment</code>,or <code>null</code>
360      * if failed to convert
361      */

362     public static IPackageFragment getFragment(IResource resource) {
363         IJavaElement elem= JavaCore.create(resource);
364         if (elem instanceof IPackageFragment)
365             return (IPackageFragment) elem;
366         return null;
367     }
368
369     /**
370      * Get the source folder of a given <code>IResource</code> element,
371      * starting with the resource's parent.
372      *
373      * @param resource the resource to get the fragment root from
374      * @param project the Java project
375      * @param monitor progress monitor, can be <code>null</code>
376      * @return resolved fragment root, or <code>null</code> the resource is not (in) a source folder
377      * @throws JavaModelException
378      */

379     public static IPackageFragmentRoot getFragmentRoot(IResource resource, IJavaProject project, IProgressMonitor monitor) throws JavaModelException {
380         if (monitor == null)
381             monitor= new NullProgressMonitor();
382         IJavaElement javaElem= null;
383         if (resource.getFullPath().equals(project.getPath()))
384             return project.getPackageFragmentRoot(resource);
385         IContainer container= resource.getParent();
386         do {
387             if (container instanceof IFolder)
388                 javaElem= JavaCore.create((IFolder) container);
389             if (container.getFullPath().equals(project.getPath())) {
390                 javaElem= project;
391                 break;
392             }
393             container= container.getParent();
394             if (container == null)
395                 return null;
396         } while (javaElem == null || !(javaElem instanceof IPackageFragmentRoot));
397         if (javaElem instanceof IJavaProject) {
398             if (!isSourceFolder((IJavaProject)javaElem))
399                 return null;
400             javaElem= project.getPackageFragmentRoot(project.getResource());
401         }
402         return (IPackageFragmentRoot) javaElem;
403     }
404
405     /**
406      * Get the <code>IClasspathEntry</code> for the
407      * given path by looking up all
408      * build path entries on the project
409      *
410      * @param path the path to find a build path entry for
411      * @param project the Java project
412      * @return the <code>IClasspathEntry</code> corresponding
413      * to the <code>path</code> or <code>null</code> if there
414      * is no such entry
415      * @throws JavaModelException
416      */

417     public static IClasspathEntry getClasspathEntryFor(IPath path, IJavaProject project, int entryKind) throws JavaModelException {
418         IClasspathEntry[] entries= project.getRawClasspath();
419         for (int i= 0; i < entries.length; i++) {
420             IClasspathEntry entry= entries[i];
421             if (entry.getPath().equals(path) && equalEntryKind(entry, entryKind))
422                 return entry;
423         }
424         return null;
425     }
426
427     /**
428      * Check whether the current selection is the project's
429      * default output folder or not
430      *
431      * @param attrib the attribute to be checked
432      * @return <code>true</code> if is the default output folder,
433      * <code>false</code> otherwise.
434      */

435     public static boolean isDefaultOutputFolder(CPListElementAttribute attrib) {
436         return attrib.getValue() == null;
437     }
438
439     /**
440      * Determines whether the current selection (of type
441      * <code>ICompilationUnit</code> or <code>IPackageFragment</code>)
442      * is on the inclusion filter of it's parent source folder.
443      *
444      * @param selection the current Java element
445      * @param project the Java project
446      * @param monitor progress monitor, can be <code>null</code>
447      * @return <code>true</code> if the current selection is included,
448      * <code>false</code> otherwise.
449      * @throws JavaModelException
450      */

451     public static boolean isIncluded(IJavaElement selection, IJavaProject project, IProgressMonitor monitor) throws JavaModelException {
452         if (monitor == null)
453             monitor= new NullProgressMonitor();
454         try {
455             monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_ContainsPath, 4);
456             IPackageFragmentRoot root= (IPackageFragmentRoot) selection.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
457             IClasspathEntry entry= root.getRawClasspathEntry();
458             if (entry == null)
459                 return false;
460             return contains(selection.getPath().removeFirstSegments(root.getPath().segmentCount()), entry.getInclusionPatterns(), new SubProgressMonitor(monitor, 2));
461         } finally {
462             monitor.done();
463         }
464     }
465
466     /**
467      * Find out whether the <code>IResource</code> excluded or not.
468      *
469      * @param resource the resource to be checked
470      * @param project the Java project
471      * @return <code>true</code> if the resource is excluded, <code>
472      * false</code> otherwise
473      * @throws JavaModelException
474      */

475     public static boolean isExcluded(IResource resource, IJavaProject project) throws JavaModelException {
476         IPackageFragmentRoot root= getFragmentRoot(resource, project, null);
477         if (root == null)
478             return false;
479         String JavaDoc fragmentName= getName(resource.getFullPath(), root.getPath());
480         fragmentName= completeName(fragmentName);
481         IClasspathEntry entry= root.getRawClasspathEntry();
482         return entry != null && contains(new Path(fragmentName), entry.getExclusionPatterns(), null);
483     }
484
485     /**
486      * Find out whether one of the <code>IResource</code>'s parents
487      * is excluded.
488      *
489      * @param resource check the resources parents whether they are
490      * excluded or not
491      * @param project the Java project
492      * @return <code>true</code> if there is an excluded parent,
493      * <code>false</code> otherwise
494      * @throws JavaModelException
495      */

496     public static boolean parentExcluded(IResource resource, IJavaProject project) throws JavaModelException {
497         if (resource.getFullPath().equals(project.getPath()))
498             return false;
499         IPackageFragmentRoot root= getFragmentRoot(resource, project, null);
500         if (root == null) {
501             return true;
502         }
503         IPath path= resource.getFullPath().removeFirstSegments(root.getPath().segmentCount());
504         IClasspathEntry entry= root.getRawClasspathEntry();
505         if (entry == null)
506             return true; // there is no build path entry, this is equal to the fact that the parent is excluded
507
while (path.segmentCount() > 0) {
508             if (contains(path, entry.getExclusionPatterns(), null))
509                 return true;
510             path= path.removeLastSegments(1);
511         }
512         return false;
513     }
514
515     /**
516      * Check wheter the output location of the <code>IPackageFragmentRoot</code>
517      * is <code>null</code>. If this holds, then the root
518      * does use the default output folder.
519      *
520      * @param root the root to examine the output location for
521      * @return <code>true</code> if the root uses the default output folder, <code>false
522      * </code> otherwise.
523      * @throws JavaModelException
524      */

525     public static boolean hasDefaultOutputFolder(IPackageFragmentRoot root) throws JavaModelException {
526         return root.getRawClasspathEntry().getOutputLocation() == null;
527     }
528
529     /**
530      * Check whether at least one source folder of the given
531      * Java project has an output folder set.
532      *
533      * @param project the Java project
534      * @param monitor progress monitor, can be <code>null</code>
535      * @return <code>true</code> if at least one outputfolder
536      * is set, <code>false</code> otherwise
537      * @throws JavaModelException
538      */

539     public static boolean hasOutputFolders(IJavaProject project, IProgressMonitor monitor) throws JavaModelException {
540         if (monitor == null)
541             monitor= new NullProgressMonitor();
542         try {
543             IPackageFragmentRoot[] roots= project.getPackageFragmentRoots();
544             monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_CheckOutputFolders, roots.length);
545             for (int i= 0; i < roots.length; i++) {
546                 if (roots[i].getRawClasspathEntry().getOutputLocation() != null)
547                     return true;
548                 monitor.worked(1);
549             }
550         } finally {
551             monitor.done();
552         }
553         return false;
554     }
555     
556     public static String JavaDoc escapeSpecialChars(String JavaDoc value) {
557         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
558         for (int i = 0; i < value.length(); i++) {
559             char c = value.charAt(i);
560
561             switch (c) {
562             case '&':
563                 buf.append("&amp;"); //$NON-NLS-1$
564
break;
565             case '<':
566                 buf.append("&lt;"); //$NON-NLS-1$
567
break;
568             case '>':
569                 buf.append("&gt;"); //$NON-NLS-1$
570
break;
571             case '\'':
572                 buf.append("&apos;"); //$NON-NLS-1$
573
break;
574             case '\"':
575                 buf.append("&quot;"); //$NON-NLS-1$
576
break;
577             case 160:
578                 buf.append(" "); //$NON-NLS-1$
579
break;
580             default:
581                 buf.append(c);
582                 break;
583             }
584         }
585         return buf.toString();
586     }
587     
588
589     /**
590      * Check whether the <code>IJavaProject</code>
591      * is a source folder
592      *
593      * @param project the project to test
594      * @return <code>true</code> if <code>project</code> is a source folder
595      * <code>false</code> otherwise.
596      */

597     public static boolean isSourceFolder(IJavaProject project) throws JavaModelException {
598         return ClasspathModifier.getClasspathEntryFor(project.getPath(), project, IClasspathEntry.CPE_SOURCE) != null;
599     }
600     
601     /**
602      * Check whether the <code>IPackageFragment</code>
603      * corresponds to the project's default fragment.
604      *
605      * @param fragment the package fragment to be checked
606      * @return <code>true</code> if is the default package fragment,
607      * <code>false</code> otherwise.
608      */

609     public static boolean isDefaultFragment(IPackageFragment fragment) {
610         return fragment.getElementName().length() == 0;
611     }
612
613     /**
614      * Determines whether the inclusion filter of the element's source folder is empty
615      * or not
616      * @return <code>true</code> if the inclusion filter is empty,
617      * <code>false</code> otherwise.
618      * @throws JavaModelException
619      */

620     public static boolean includeFiltersEmpty(IResource resource, IJavaProject project, IProgressMonitor monitor) throws JavaModelException {
621         if (monitor == null)
622             monitor= new NullProgressMonitor();
623         try {
624             monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_ExamineInputFilters, 4);
625             IPackageFragmentRoot root= getFragmentRoot(resource, project, new SubProgressMonitor(monitor, 4));
626             if (root != null) {
627                 IClasspathEntry entry= root.getRawClasspathEntry();
628                 return entry.getInclusionPatterns().length == 0;
629             }
630             return true;
631         } finally {
632             monitor.done();
633         }
634     }
635
636     /**
637      * Check whether the input paramenter of type <code>
638      * IPackageFragmentRoot</code> has either it's inclusion or
639      * exclusion filter or both set (that means they are
640      * not empty).
641      *
642      * @param root the fragment root to be inspected
643      * @return <code>true</code> inclusion or exclusion filter set,
644      * <code>false</code> otherwise.
645      */

646     public static boolean filtersSet(IPackageFragmentRoot root) throws JavaModelException {
647         if (root == null)
648             return false;
649         IClasspathEntry entry= root.getRawClasspathEntry();
650         IPath[] inclusions= entry.getInclusionPatterns();
651         IPath[] exclusions= entry.getExclusionPatterns();
652         if (inclusions != null && inclusions.length > 0)
653             return true;
654         if (exclusions != null && exclusions.length > 0)
655             return true;
656         return false;
657     }
658
659     /**
660      * Add a resource to the build path.
661      *
662      * @param resource the resource to be added to the build path
663      * @param project the Java project
664      * @param monitor progress monitor, can be <code>null</code>
665      * @return returns the new element of type <code>IPackageFragmentRoot</code> that has been added to the build path
666      * @throws CoreException
667      * @throws OperationCanceledException
668      */

669     public static CPListElement addToClasspath(IResource resource, List JavaDoc existingEntries, List JavaDoc newEntries, IJavaProject project, IProgressMonitor monitor) throws OperationCanceledException, CoreException {
670         if (monitor == null)
671             monitor= new NullProgressMonitor();
672         try {
673             monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_AddToBuildpath, 2);
674             exclude(resource.getFullPath(), existingEntries, newEntries, project, new SubProgressMonitor(monitor, 1));
675             CPListElement entry= new CPListElement(project, IClasspathEntry.CPE_SOURCE, resource.getFullPath(), resource);
676             return entry;
677         } finally {
678             monitor.done();
679         }
680     }
681
682     /**
683      * Check whether the provided file is an archive (.jar or .zip).
684      *
685      * @param file the file to be checked
686      * @param project the Java project
687      * @return <code>true</code> if the file is an archive, <code>false</code>
688      * otherwise
689      * @throws JavaModelException
690      */

691     public static boolean isArchive(IFile file, IJavaProject project) throws JavaModelException {
692         if (!ArchiveFileFilter.isArchivePath(file.getFullPath()))
693             return false;
694         if (project != null && project.exists() && (project.findPackageFragmentRoot(file.getFullPath()) == null))
695             return true;
696         return false;
697     }
698
699     /**
700      * Add a Java element to the build path.
701      *
702      * @param javaElement element to be added to the build path
703      * @param project the Java project
704      * @param monitor progress monitor, can be <code>null</code>
705      * @return returns the new element of type <code>IPackageFragmentRoot</code> that has been added to the build path
706      * @throws CoreException
707      * @throws OperationCanceledException
708      */

709     public static CPListElement addToClasspath(IJavaElement javaElement, List JavaDoc existingEntries, List JavaDoc newEntries, IJavaProject project, IProgressMonitor monitor) throws OperationCanceledException, CoreException {
710         if (monitor == null)
711             monitor= new NullProgressMonitor();
712         try {
713             monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_AddToBuildpath, 10);
714             CPListElement entry= new CPListElement(project, IClasspathEntry.CPE_SOURCE, javaElement.getPath(), javaElement.getResource());
715             return entry;
716         } finally {
717             monitor.done();
718         }
719     }
720
721     /**
722      * Remove the Java project from the build path
723      *
724      * @param project the project to be removed
725      * @param existingEntries a list of existing <code>CPListElement</code>. This list
726      * will be traversed and the entry for the project will be removed.
727      * @param monitor progress monitor, can be <code>null</code>
728      * @return returns the Java project
729      */

730     public static IJavaProject removeFromClasspath(IJavaProject project, List JavaDoc existingEntries, IProgressMonitor monitor) {
731         CPListElement elem= getListElement(project.getPath(), existingEntries);
732         if (elem != null) {
733             existingEntries.remove(elem);
734         }
735         return project;
736     }
737     
738     /**
739      * Remove <code>path</code> from inclusion/exlusion filters in all <code>existingEntries</code>
740      *
741      * @param path the path to remove
742      * @param project the Java project
743      * @param existingEntries a list of <code>CPListElement</code> representing the build path
744      * entries of the project.
745      * @return returns a <code>List</code> of <code>CPListElement</code> of modified elements, not null.
746      */

747     public static List JavaDoc removeFilters(IPath path, IJavaProject project, List JavaDoc existingEntries) {
748         if (path == null)
749             return Collections.EMPTY_LIST;
750         
751         IPath projPath= project.getPath();
752         if (projPath.isPrefixOf(path)) {
753             path= path.removeFirstSegments(projPath.segmentCount()).addTrailingSeparator();
754         }
755         
756         List JavaDoc result= new ArrayList JavaDoc();
757         for (Iterator JavaDoc iter= existingEntries.iterator(); iter.hasNext();) {
758             CPListElement element= (CPListElement)iter.next();
759             boolean hasChange= false;
760             IPath[] exlusions= (IPath[])element.getAttribute(CPListElement.EXCLUSION);
761             if (exlusions != null) {
762                 List JavaDoc exlusionList= new ArrayList JavaDoc(exlusions.length);
763                 for (int i= 0; i < exlusions.length; i++) {
764                     if (!exlusions[i].equals(path)) {
765                         exlusionList.add(exlusions[i]);
766                     } else {
767                         hasChange= true;
768                     }
769                 }
770                 element.setAttribute(CPListElement.EXCLUSION, exlusionList.toArray(new IPath[exlusionList.size()]));
771             }
772             
773             IPath[] inclusion= (IPath[])element.getAttribute(CPListElement.INCLUSION);
774             if (inclusion != null) {
775                 List JavaDoc inclusionList= new ArrayList JavaDoc(inclusion.length);
776                 for (int i= 0; i < inclusion.length; i++) {
777                     if (!inclusion[i].equals(path)) {
778                         inclusionList.add(inclusion[i]);
779                     } else {
780                         hasChange= true;
781                     }
782                 }
783                 element.setAttribute(CPListElement.INCLUSION, inclusionList.toArray(new IPath[inclusionList.size()]));
784             }
785             if (hasChange) {
786                 result.add(element);
787             }
788         }
789         return result;
790     }
791
792     /**
793      * Exclude an element with a given name and absolute path
794      * from the build path.
795      *
796      * @param name the name of the element to be excluded
797      * @param fullPath the absolute path of the element
798      * @param entry the build path entry to be modified
799      * @param project the Java project
800      * @param monitor progress monitor, can be <code>null</code>
801      * @return a <code>IResource</code> corresponding to the excluded element
802      * @throws JavaModelException
803      */

804     private static IResource exclude(String JavaDoc name, IPath fullPath, CPListElement entry, IJavaProject project, IProgressMonitor monitor) throws JavaModelException {
805         if (monitor == null)
806             monitor= new NullProgressMonitor();
807         IResource result;
808         try {
809             monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_Excluding, 6);
810             IPath[] excludedPath= (IPath[]) entry.getAttribute(CPListElement.EXCLUSION);
811             IPath[] newExcludedPath= new IPath[excludedPath.length + 1];
812             name= completeName(name);
813             IPath path= new Path(name);
814             if (!contains(path, excludedPath, new SubProgressMonitor(monitor, 2))) {
815                 System.arraycopy(excludedPath, 0, newExcludedPath, 0, excludedPath.length);
816                 newExcludedPath[excludedPath.length]= path;
817                 entry.setAttribute(CPListElement.EXCLUSION, newExcludedPath);
818                 entry.setAttribute(CPListElement.INCLUSION, remove(path, (IPath[]) entry.getAttribute(CPListElement.INCLUSION), new SubProgressMonitor(monitor, 4)));
819             }
820             result= fullPath == null ? null : getResource(fullPath, project);
821         } finally {
822             monitor.done();
823         }
824         return result;
825     }
826
827     /**
828      * Exclude an object at a given path.
829      * This means that the exclusion filter for the
830      * corresponding <code>IPackageFragmentRoot</code> needs to be modified.
831      *
832      * First, the fragment root needs to be found. To do so, the new entries
833      * are and the existing entries are traversed for a match and the entry
834      * with the path is removed from one of those lists.
835      *
836      * Note: the <code>IJavaElement</code>'s fragment (if there is one)
837      * is not allowed to be excluded! However, inclusion (or simply no
838      * filter) on the parent fragment is allowed.
839      *
840      * @param path absolute path of an object to be excluded
841      * @param existingEntries a list of existing build path entries
842      * @param newEntries a list of new build path entries
843      * @param project the Java project
844      * @param monitor progress monitor, can be <code>null</code>
845      */

846     public static void exclude(IPath path, List JavaDoc existingEntries, List JavaDoc newEntries, IJavaProject project, IProgressMonitor monitor) throws JavaModelException {
847         if (monitor == null)
848             monitor= new NullProgressMonitor();
849         try {
850             monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_Excluding, 1);
851             CPListElement elem= null;
852             CPListElement existingElem= null;
853             int i= 0;
854             do {
855                 i++;
856                 IPath rootPath= path.removeLastSegments(i);
857
858                 if (rootPath.segmentCount() == 0)
859                     return;
860
861                 elem= getListElement(rootPath, newEntries);
862                 existingElem= getListElement(rootPath, existingEntries);
863             } while (existingElem == null && elem == null);
864             if (elem == null) {
865                 elem= existingElem;
866             }
867             exclude(path.removeFirstSegments(path.segmentCount() - i).toString(), null, elem, project, new SubProgressMonitor(monitor, 1));
868         } finally {
869             monitor.done();
870         }
871     }
872
873     /**
874      * Exclude a <code>IJavaElement</code>. This means that the exclusion filter for the
875      * corresponding <code>IPackageFragmentRoot</code>s need to be modified.
876      *
877      * Note: the <code>IJavaElement</code>'s fragment (if there is one)
878      * is not allowed to be excluded! However, inclusion (or simply no
879      * filter) on the parent fragment is allowed.
880      *
881      * @param javaElement the Java element to be excluded
882      * @param entry the <code>CPListElement</code> representing the
883      * <code>IClasspathEntry</code> of the Java element's root.
884      * @param project the Java project
885      * @param monitor progress monitor, can be <code>null</code>
886      *
887      * @return the resulting <code>IResource<code>
888      * @throws JavaModelException
889      */

890     public static IResource exclude(IJavaElement javaElement, CPListElement entry, IJavaProject project, IProgressMonitor monitor) throws JavaModelException {
891         if (monitor == null)
892             monitor= new NullProgressMonitor();
893         try {
894             String JavaDoc name= getName(javaElement.getPath(), entry.getPath());
895             return exclude(name, javaElement.getPath(), entry, project, new SubProgressMonitor(monitor, 1));
896         } finally {
897             monitor.done();
898         }
899     }
900
901     /**
902      * Inverse operation to <code>exclude</code>.
903      * The resource removed from it's fragment roots exlusion filter.
904      *
905      * Note: the <code>IJavaElement</code>'s fragment (if there is one)
906      * is not allowed to be excluded! However, inclusion (or simply no
907      * filter) on the parent fragment is allowed.
908      *
909      * @param resource the resource to be unexcluded
910      * @param entry the <code>CPListElement</code> representing the
911      * <code>IClasspathEntry</code> of the resource's root.
912      * @param project the Java project
913      * @param monitor progress monitor, can be <code>null</code>
914      * @throws JavaModelException
915      *
916      */

917     public static void unExclude(IResource resource, CPListElement entry, IJavaProject project, IProgressMonitor monitor) throws JavaModelException {
918         if (monitor == null)
919             monitor= new NullProgressMonitor();
920         try {
921             monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_RemoveExclusion, 10);
922             String JavaDoc name= getName(resource.getFullPath(), entry.getPath());
923             IPath[] excludedPath= (IPath[]) entry.getAttribute(CPListElement.EXCLUSION);
924             IPath[] newExcludedPath= remove(new Path(completeName(name)), excludedPath, new SubProgressMonitor(monitor, 3));
925             entry.setAttribute(CPListElement.EXCLUSION, newExcludedPath);
926         } finally {
927             monitor.done();
928         }
929     }
930
931     /**
932      * Resets inclusion and exclusion filters for the given
933      * <code>IJavaElement</code>
934      *
935      * @param element element to reset it's filters
936      * @param entry the <code>CPListElement</code> to reset its filters for
937      * @param project the Java project
938      * @param monitor progress monitor, can be <code>null</code>
939      * @throws JavaModelException
940      */

941     public static void resetFilters(IJavaElement element, CPListElement entry, IJavaProject project, IProgressMonitor monitor) throws JavaModelException {
942         if (monitor == null)
943             monitor= new NullProgressMonitor();
944         try {
945             monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_ResetFilters, 3);
946
947             List JavaDoc exclusionList= getFoldersOnCP(element.getPath(), project, new SubProgressMonitor(monitor, 2));
948             IPath outputLocation= (IPath) entry.getAttribute(CPListElement.OUTPUT);
949             if (outputLocation != null) {
950                 IPath[] exclusionPatterns= (IPath[]) entry.getAttribute(CPListElement.EXCLUSION);
951                 if (contains(new Path(completeName(outputLocation.lastSegment())), exclusionPatterns, null)) {
952                     exclusionList.add(new Path(completeName(outputLocation.lastSegment())));
953                 }
954             }
955             IPath[] exclusions= (IPath[]) exclusionList.toArray(new IPath[exclusionList.size()]);
956
957             entry.setAttribute(CPListElement.INCLUSION, new IPath[0]);
958             entry.setAttribute(CPListElement.EXCLUSION, exclusions);
959         } finally {
960             monitor.done();
961         }
962     }
963
964     /**
965      * Reset the output folder for the given entry to the default output folder
966      *
967      * @param entry the <code>CPListElement</code> to be edited
968      * @param project the Java project
969      * @return an attribute representing the modified output folder
970      * @throws JavaModelException
971      */

972     public static CPListElementAttribute resetOutputFolder(CPListElement entry, IJavaProject project) throws JavaModelException {
973         entry.setAttribute(CPListElement.OUTPUT, null);
974         CPListElementAttribute outputFolder= new CPListElementAttribute(entry, CPListElement.OUTPUT, entry.getAttribute(CPListElement.OUTPUT), true);
975         return outputFolder;
976     }
977
978     /**
979      * Try to find the corresponding and modified <code>CPListElement</code> for the provided
980      * <code>CPListElement</code> in the list of elements and return it.
981      * If no one can be found, the provided <code>CPListElement</code> is returned.
982      *
983      * @param elements a list of <code>CPListElements</code>
984      * @param cpElement the <code>CPListElement</code> to find the corresponding entry in
985      * the list
986      * @return the <code>CPListElement</code> found in the list (matching by using the path) or
987      * the second <code>CPListElement</code> parameter itself if there is no match.
988      */

989     public static CPListElement getClasspathEntry(List JavaDoc elements, CPListElement cpElement) {
990         for (int i= 0; i < elements.size(); i++) {
991             if (((CPListElement) elements.get(i)).getPath().equals(cpElement.getPath()))
992                 return (CPListElement) elements.get(i);
993         }
994         elements.add(cpElement);
995         return cpElement;
996     }
997
998     /**
999      * For a given path, find the corresponding element in the list.
1000     *
1001     * @param path the path to found an entry for
1002     * @param elements a list of <code>CPListElement</code>s
1003     * @return the mathed <code>CPListElement</code> or <code>null</code> if
1004     * no match could be found
1005     */

1006    public static CPListElement getListElement(IPath path, List JavaDoc elements) {
1007        for (int i= 0; i < elements.size(); i++) {
1008            CPListElement element= (CPListElement) elements.get(i);
1009            if (element.getEntryKind() == IClasspathEntry.CPE_SOURCE && element.getPath().equals(path)) {
1010                return element;
1011            }
1012        }
1013        return null;
1014    }
1015    
1016    public static void commitClassPath(List JavaDoc newEntries, IJavaProject project, IProgressMonitor monitor) throws JavaModelException {
1017        if (monitor == null)
1018            monitor= new NullProgressMonitor();
1019        
1020        monitor.beginTask("", 2); //$NON-NLS-1$
1021

1022        try {
1023            IClasspathEntry[] entries= convert(newEntries);
1024            IPath outputLocation= project.getOutputLocation();
1025
1026            IJavaModelStatus status= JavaConventions.validateClasspath(project, entries, outputLocation);
1027            if (!status.isOK())
1028                throw new JavaModelException(status);
1029
1030            project.setRawClasspath(entries, outputLocation, new SubProgressMonitor(monitor, 2));
1031        } finally {
1032            monitor.done();
1033        }
1034    }
1035    
1036    public static void commitClassPath(CPJavaProject cpProject, IProgressMonitor monitor) throws JavaModelException {
1037        if (monitor == null)
1038            monitor= new NullProgressMonitor();
1039        
1040        monitor.beginTask("", 2); //$NON-NLS-1$
1041

1042        try {
1043            IClasspathEntry[] entries= convert(cpProject.getCPListElements());
1044            IPath outputLocation= cpProject.getDefaultOutputLocation();
1045
1046            IJavaModelStatus status= JavaConventions.validateClasspath(cpProject.getJavaProject(), entries, outputLocation);
1047            if (!status.isOK())
1048                throw new JavaModelException(status);
1049
1050            cpProject.getJavaProject().setRawClasspath(entries, outputLocation, new SubProgressMonitor(monitor, 2));
1051        } finally {
1052            monitor.done();
1053        }
1054    }
1055
1056    /**
1057     * For a given list of entries, find out what representation they
1058     * will have in the project and return a list with corresponding
1059     * elements.
1060     *
1061     * @param entries a list of entries to find an appropriate representation
1062     * for. The list can contain elements of two types:
1063     * <li><code>IResource</code></li>
1064     * <li><code>IJavaElement</code></li>
1065     * @param project the Java project
1066     * @return a list of elements corresponding to the passed entries.
1067     */

1068    public static List JavaDoc getCorrespondingElements(List JavaDoc entries, IJavaProject project) {
1069        List JavaDoc result= new ArrayList JavaDoc();
1070        for (int i= 0; i < entries.size(); i++) {
1071            Object JavaDoc element= entries.get(i);
1072            IPath path;
1073            if (element instanceof IResource)
1074                path= ((IResource) element).getFullPath();
1075            else
1076                path= ((IJavaElement) element).getPath();
1077            IResource resource= getResource(path, project);
1078            if (resource != null) {
1079                IJavaElement elem= JavaCore.create(resource);
1080                if (elem != null && project.isOnClasspath(elem))
1081                    result.add(elem);
1082                else
1083                    result.add(resource);
1084            }
1085
1086        }
1087        return result;
1088    }
1089
1090    /**
1091     * Returns for the given absolute path the corresponding
1092     * resource, this is either element of type <code>IFile</code>
1093     * or <code>IFolder</code>.
1094     *
1095     * @param path an absolute path to a resource
1096     * @param project the Java project
1097     * @return the resource matching to the path. Can be
1098     * either an <code>IFile</code> or an <code>IFolder</code>.
1099     */

1100    private static IResource getResource(IPath path, IJavaProject project) {
1101        return project.getProject().getWorkspace().getRoot().findMember(path);
1102    }
1103
1104    /**
1105     * Find out whether the provided path equals to one
1106     * in the array.
1107     *
1108     * @param path path to find an equivalent for
1109     * @param paths set of paths to compare with
1110     * @param monitor progress monitor, can be <code>null</code>
1111     * @return <code>true</code> if there is an occurrence, <code>
1112     * false</code> otherwise
1113     */

1114    private static boolean contains(IPath path, IPath[] paths, IProgressMonitor monitor) {
1115        if (monitor == null)
1116            monitor= new NullProgressMonitor();
1117        if (path == null)
1118            return false;
1119        try {
1120            monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_ComparePaths, paths.length);
1121            if (path.getFileExtension() == null)
1122                path= new Path(completeName(path.toString()));
1123            for (int i= 0; i < paths.length; i++) {
1124                if (paths[i].equals(path))
1125                    return true;
1126                monitor.worked(1);
1127            }
1128        } finally {
1129            monitor.done();
1130        }
1131        return false;
1132    }
1133
1134    /**
1135     * Add a '/' at the end of the name if
1136     * it does not end with '.java', or other Java-like extension.
1137     *
1138     * @param name append '/' at the end if
1139     * necessary
1140     * @return modified string
1141     */

1142    private static String JavaDoc completeName(String JavaDoc name) {
1143        if (!JavaCore.isJavaLikeFileName(name)) {
1144            name= name + "/"; //$NON-NLS-1$
1145
name= name.replace('.', '/');
1146            return name;
1147        }
1148        return name;
1149    }
1150
1151    /**
1152     * Removes <code>path</code> out of the set of given <code>
1153     * paths</code>. If the path is not contained, then the
1154     * initially provided array of paths is returned.
1155     *
1156     * Only the first occurrence will be removed.
1157     *
1158     * @param path path to be removed
1159     * @param paths array of path to apply the removal on
1160     * @param monitor progress monitor, can be <code>null</code>
1161     * @return array which does not contain <code>path</code>
1162     */

1163    private static IPath[] remove(IPath path, IPath[] paths, IProgressMonitor monitor) {
1164        if (monitor == null)
1165            monitor= new NullProgressMonitor();
1166        try {
1167            monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_RemovePath, paths.length + 5);
1168            if (!contains(path, paths, new SubProgressMonitor(monitor, 5)))
1169                return paths;
1170
1171            ArrayList JavaDoc newPaths= new ArrayList JavaDoc();
1172            for (int i= 0; i < paths.length; i++) {
1173                monitor.worked(1);
1174                if (!paths[i].equals(path))
1175                    newPaths.add(paths[i]);
1176            }
1177            
1178            return (IPath[]) newPaths.toArray(new IPath[newPaths.size()]);
1179        } finally {
1180            monitor.done();
1181        }
1182
1183    }
1184
1185    /**
1186     * Find all folders that are on the build path and
1187     * <code>path</code> is a prefix of those folders
1188     * path entry, that is, all folders which are a
1189     * subfolder of <code>path</code>.
1190     *
1191     * For example, if <code>path</code>=/MyProject/src
1192     * then all folders having a path like /MyProject/src/*,
1193     * where * can be any valid string are returned if
1194     * they are also on the project's build path.
1195     *
1196     * @param path absolute path
1197     * @param project the Java project
1198     * @param monitor progress monitor, can be <code>null</code>
1199     * @return an array of paths which belong to subfolders
1200     * of <code>path</code> and which are on the build path
1201     * @throws JavaModelException
1202     */

1203    private static List JavaDoc getFoldersOnCP(IPath path, IJavaProject project, IProgressMonitor monitor) throws JavaModelException {
1204        if (monitor == null)
1205            monitor= new NullProgressMonitor();
1206        List JavaDoc srcFolders= new ArrayList JavaDoc();
1207        IClasspathEntry[] cpEntries= project.getRawClasspath();
1208        for (int i= 0; i < cpEntries.length; i++) {
1209            IPath cpPath= cpEntries[i].getPath();
1210            if (path.isPrefixOf(cpPath) && path.segmentCount() + 1 == cpPath.segmentCount())
1211                srcFolders.add(new Path(completeName(cpPath.lastSegment())));
1212        }
1213        return srcFolders;
1214    }
1215
1216    /**
1217     * Returns a string corresponding to the <code>path</code>
1218     * with the <code>rootPath<code>'s number of segments
1219     * removed
1220     *
1221     * @param path path to remove segments
1222     * @param rootPath provides the number of segments to
1223     * be removed
1224     * @return a string corresponding to the mentioned
1225     * action
1226     */

1227    private static String JavaDoc getName(IPath path, IPath rootPath) {
1228        return path.removeFirstSegments(rootPath.segmentCount()).toString();
1229    }
1230
1231    /**
1232     * Sets and validates the new entries. Note that the elments of
1233     * the list containing the new entries will be added to the list of
1234     * existing entries (therefore, there is no return list for this method).
1235     *
1236     * @param existingEntries a list of existing classpath entries
1237     * @param newEntries a list of entries to be added to the existing ones
1238     * @param project the Java project
1239     * @param monitor a progress monitor, can be <code>null</code>
1240     * @throws CoreException in case that validation on one of the new entries fails
1241     */

1242    public static void setNewEntry(List JavaDoc existingEntries, List JavaDoc newEntries, IJavaProject project, IProgressMonitor monitor) throws CoreException {
1243        try {
1244            monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_SetNewEntry, existingEntries.size());
1245            for (int i= 0; i < newEntries.size(); i++) {
1246                CPListElement entry= (CPListElement) newEntries.get(i);
1247                validateAndAddEntry(entry, existingEntries, project);
1248                monitor.worked(1);
1249            }
1250        } finally {
1251            monitor.done();
1252        }
1253    }
1254
1255    /**
1256     * Convert a list of <code>CPListElement</code>s to
1257     * an array of <code>IClasspathEntry</code>.
1258     *
1259     * @param list the list to be converted
1260     * @return an array containing build path entries
1261     * corresponding to the list
1262     */

1263    private static IClasspathEntry[] convert(List JavaDoc list) {
1264        IClasspathEntry[] entries= new IClasspathEntry[list.size()];
1265        for (int i= 0; i < list.size(); i++) {
1266            CPListElement element= (CPListElement) list.get(i);
1267            entries[i]= element.getClasspathEntry();
1268        }
1269        return entries;
1270    }
1271
1272    /**
1273     * Validate the new entry in the context of the existing entries. Furthermore,
1274     * check if exclusion filters need to be applied and do so if necessary.
1275     *
1276     * If validation was successfull, add the new entry to the list of existing entries.
1277     *
1278     * @param entry the entry to be validated and added to the list of existing entries.
1279     * @param existingEntries a list of existing entries representing the build path
1280     * @param project the Java project
1281     * @throws CoreException in case that validation fails
1282     */

1283    private static void validateAndAddEntry(CPListElement entry, List JavaDoc existingEntries, IJavaProject project) throws CoreException {
1284        IPath path= entry.getPath();
1285        IPath projPath= project.getProject().getFullPath();
1286        IWorkspaceRoot workspaceRoot= ResourcesPlugin.getWorkspace().getRoot();
1287        IStatus validate= workspaceRoot.getWorkspace().validatePath(path.toString(), IResource.FOLDER);
1288        StatusInfo rootStatus= new StatusInfo();
1289        rootStatus.setOK();
1290        boolean isExternal= isExternalArchiveOrLibrary(entry, project);
1291        if (!isExternal && validate.matches(IStatus.ERROR) && !project.getPath().equals(path)) {
1292            rootStatus.setError(Messages.format(NewWizardMessages.NewSourceFolderWizardPage_error_InvalidRootName, validate.getMessage()));
1293            throw new CoreException(rootStatus);
1294        } else {
1295            if (!isExternal && !project.getPath().equals(path)) {
1296                IResource res= workspaceRoot.findMember(path);
1297                if (res != null) {
1298                    if (res.getType() != IResource.FOLDER && res.getType() != IResource.FILE) {
1299                        rootStatus.setError(NewWizardMessages.NewSourceFolderWizardPage_error_NotAFolder);
1300                        throw new CoreException(rootStatus);
1301                    }
1302                } else {
1303                    URI JavaDoc projLocation= project.getProject().getLocationURI();
1304                    if (projLocation != null) {
1305                        IFileStore store= EFS.getStore(projLocation).getChild(path);
1306                        if (store.fetchInfo().exists()) {
1307                            rootStatus.setError(NewWizardMessages.NewSourceFolderWizardPage_error_AlreadyExistingDifferentCase);
1308                            throw new CoreException(rootStatus);
1309                        }
1310                    }
1311                }
1312            }
1313
1314            for (int i= 0; i < existingEntries.size(); i++) {
1315                CPListElement curr= (CPListElement) existingEntries.get(i);
1316                if (curr.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
1317                    if (path.equals(curr.getPath()) && !project.getPath().equals(path)) {
1318                        rootStatus.setError(NewWizardMessages.NewSourceFolderWizardPage_error_AlreadyExisting);
1319                        throw new CoreException(rootStatus);
1320                    }
1321                }
1322            }
1323
1324            if (!isExternal && !entry.getPath().equals(project.getPath()))
1325                exclude(entry.getPath(), existingEntries, new ArrayList JavaDoc(), project, null);
1326
1327            IPath outputLocation= project.getOutputLocation();
1328            insertAtEndOfCategory(entry, existingEntries);
1329
1330            IClasspathEntry[] entries= convert(existingEntries);
1331
1332            IJavaModelStatus status= JavaConventions.validateClasspath(project, entries, outputLocation);
1333            if (!status.isOK()) {
1334                if (outputLocation.equals(projPath)) {
1335                    IStatus status2= JavaConventions.validateClasspath(project, entries, outputLocation);
1336                    if (status2.isOK()) {
1337                        if (project.isOnClasspath(project)) {
1338                            rootStatus.setInfo(Messages.format(NewWizardMessages.NewSourceFolderWizardPage_warning_ReplaceSFandOL, outputLocation.makeRelative().toString()));
1339                        } else {
1340                            rootStatus.setInfo(Messages.format(NewWizardMessages.NewSourceFolderWizardPage_warning_ReplaceOL, outputLocation.makeRelative().toString()));
1341                        }
1342                        return;
1343                    }
1344                }
1345                rootStatus.setError(status.getMessage());
1346                throw new CoreException(rootStatus);
1347            }
1348
1349            if (isSourceFolder(project) || project.getPath().equals(path)) {
1350                rootStatus.setWarning(NewWizardMessages.NewSourceFolderWizardPage_warning_ReplaceSF);
1351                return;
1352            }
1353
1354            rootStatus.setOK();
1355            return;
1356        }
1357    }
1358
1359    private static void insertAtEndOfCategory(CPListElement entry, List JavaDoc existingEntries) {
1360        int length= existingEntries.size();
1361        CPListElement[] elements= (CPListElement[])existingEntries.toArray(new CPListElement[length]);
1362        int i= 0;
1363        while (i < length && elements[i].getClasspathEntry().getEntryKind() != entry.getClasspathEntry().getEntryKind()) {
1364            i++;
1365        }
1366        if (i < length) {
1367            i++;
1368            while (i < length && elements[i].getClasspathEntry().getEntryKind() == entry.getClasspathEntry().getEntryKind()) {
1369                i++;
1370            }
1371            existingEntries.add(i, entry);
1372            return;
1373        }
1374        
1375        switch (entry.getClasspathEntry().getEntryKind()) {
1376        case IClasspathEntry.CPE_SOURCE:
1377            existingEntries.add(0, entry);
1378            break;
1379        case IClasspathEntry.CPE_CONTAINER:
1380        case IClasspathEntry.CPE_LIBRARY:
1381        case IClasspathEntry.CPE_PROJECT:
1382        case IClasspathEntry.CPE_VARIABLE:
1383        default:
1384            existingEntries.add(entry);
1385            break;
1386        }
1387    }
1388
1389    private static boolean isExternalArchiveOrLibrary(CPListElement entry, IJavaProject project) {
1390        if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY || entry.getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
1391            if (entry.getResource() instanceof IFolder) {
1392                return false;
1393            }
1394            return true;
1395        }
1396        return false;
1397    }
1398
1399    /**
1400     * Test if the provided kind is of type
1401     * <code>IClasspathEntry.CPE_SOURCE</code>
1402     *
1403     * @param entry the classpath entry to be compared with the provided type
1404     * @param kind the kind to be checked
1405     * @return <code>true</code> if kind equals
1406     * <code>IClasspathEntry.CPE_SOURCE</code>,
1407     * <code>false</code> otherwise
1408     */

1409    private static boolean equalEntryKind(IClasspathEntry entry, int kind) {
1410        return entry.getEntryKind() == kind;
1411    }
1412
1413    public static OutputFolderValidator getValidator(final List JavaDoc newElements, final IJavaProject project) throws JavaModelException {
1414        return new OutputFolderValidator(newElements, project) {
1415
1416            public boolean validate(IPath outputLocation) {
1417                for (int i= 0; i < newElements.size(); i++) {
1418                    if (isInvalid(newElements.get(i), outputLocation))
1419                        return false;
1420                }
1421
1422                for (int i= 0; i < fEntries.length; i++) {
1423                    if (isInvalid(fEntries[i], outputLocation))
1424                        return false;
1425                }
1426                return true;
1427            }
1428
1429            /**
1430             * Check if the output location for the given object is valid
1431             *
1432             * @param object the object to retrieve its path from and compare it
1433             * to the output location
1434             * @param outputLocation the output location
1435             * @return <code>true</code> if the output location is invalid, that is,
1436             * if it is a subfolder of the provided object.
1437             */

1438            private boolean isInvalid(Object JavaDoc object, IPath outputLocation) {
1439                IPath path= null;
1440                if (object instanceof IFolder)
1441                    path= getFolderPath(object);
1442                else
1443                    if (object instanceof IJavaElement)
1444                        path= getJavaElementPath(object);
1445                    else
1446                        if (object instanceof IClasspathEntry)
1447                            path= getCPEntryPath(object);
1448                return isSubFolderOf(path, outputLocation);
1449            }
1450
1451            /**
1452             * Get an <code>IFolder</code>'s path
1453             *
1454             * @param element an element which is of type <code>IFolder</code>
1455             * @return the path of the folder
1456             */

1457            private IPath getFolderPath(Object JavaDoc element) {
1458                return ((IFolder) element).getFullPath();
1459            }
1460
1461            /**
1462             * Get an <code>IJavaElement</code>'s path
1463             *
1464             * @param element an element which is of type <code>IJavaElement</code>
1465             * @return the path of the Java element
1466             */

1467            private IPath getJavaElementPath(Object JavaDoc element) {
1468                return ((IJavaElement) element).getPath();
1469            }
1470
1471            /**
1472             * Get an <code>IClasspathEntry</code>'s path
1473             *
1474             * @param entry an element which is of type <code>IClasspathEntry</code>
1475             * @return the path of the classpath entry
1476             */

1477            private IPath getCPEntryPath(Object JavaDoc entry) {
1478                return ((IClasspathEntry) entry).getPath();
1479            }
1480
1481            /**
1482             *
1483             * @param path1 the first path
1484             * @param path2 the second path
1485             * @return <code>true</code> if path1 is a subfolder of
1486             * path2, <code>false</code> otherwise
1487             */

1488            private boolean isSubFolderOf(IPath path1, IPath path2) {
1489                if (path1 == null || path2 == null) {
1490                    if (path1 == null && path2 == null)
1491                        return true;
1492                    return false;
1493                }
1494                return path2.matchingFirstSegments(path1) == path2.segmentCount();
1495            }
1496
1497        };
1498    }
1499
1500}
1501
Popular Tags