1 /*******************************************************************************
2 * Copyright (c) 2000, 2003 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpdt.internal.core;
13 import java.util.HashMap;
14 import java.util.HashSet;
16 import net.sourceforge.phpdt.core.IClasspathEntry;
17 import net.sourceforge.phpdt.core.IJavaModelStatus;
18 import net.sourceforge.phpdt.core.IJavaModelStatusConstants;
19 import net.sourceforge.phpdt.core.IJavaProject;
20 import net.sourceforge.phpdt.core.IPackageFragmentRoot;
21 import net.sourceforge.phpdt.core.JavaCore;
22 import net.sourceforge.phpdt.core.JavaModelException;
23 import net.sourceforge.phpdt.core.compiler.CharOperation;
24 import net.sourceforge.phpdt.internal.core.util.Util;
26 //import net.sourceforge.phpdt.internal.corext.Assert;
27 //import org.eclipse.core.runtime.Assert;
28 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
30 import org.eclipse.core.resources.IProject;
31 import org.eclipse.core.resources.IWorkspaceRoot;
32 import org.eclipse.core.resources.ResourcesPlugin;
33 import org.eclipse.core.runtime.AssertionFailedException;
34 import org.eclipse.core.runtime.CoreException;
35 import org.eclipse.core.runtime.IPath;
36 import org.eclipse.core.runtime.Path;
37 import org.w3c.dom.Document;
38 import org.w3c.dom.Element;
41 * @see IClasspathEntry
43 public class ClasspathEntry implements IClasspathEntry {
46 * Describes the kind of classpath entry - one of CPE_PROJECT, CPE_LIBRARY,
47 * CPE_SOURCE, CPE_VARIABLE or CPE_CONTAINER
52 * Describes the kind of package fragment roots found on this classpath
53 * entry - either K_BINARY or K_SOURCE or K_OUTPUT.
55 public int contentKind;
58 * The meaning of the path of a classpath entry depends on its entry kind:
60 * <li>Source code in the current project (<code>CPE_SOURCE</code>) -
61 * The path associated with this entry is the absolute path to the root
63 * <li>A binary library in the current project (<code>CPE_LIBRARY</code>) -
64 * the path associated with this entry is the absolute path to the JAR (or
65 * root folder), and in case it refers to an external JAR, then there is no
66 * associated resource in the workbench.
67 * <li>A required project (<code>CPE_PROJECT</code>) - the path of the
68 * entry denotes the path to the corresponding project resource.</li>
69 * <li>A variable entry (<code>CPE_VARIABLE</code>) - the first segment
70 * of the path is the name of a classpath variable. If this classpath
71 * variable is bound to the path <it>P</it>, the path of the corresponding
72 * classpath entry is computed by appending to <it>P</it> the segments of
73 * the returned path without the variable.</li>
74 * <li> A container entry (<code>CPE_CONTAINER</code>) - the first
75 * segment of the path is denoting the unique container identifier (for
76 * which a <code>ClasspathContainerInitializer</code> could be
77 * registered), and the remaining segments are used as additional hints for
78 * resolving the container entry to an actual
79 * <code>IClasspathContainer</code>.</li>
84 * Patterns allowing to include/exclude portions of the resource tree
85 * denoted by this entry path.
87 public IPath[] inclusionPatterns;
89 private char[][] fullCharInclusionPatterns;
91 public IPath[] exclusionPatterns;
93 private char[][] fullCharExclusionPatterns;
95 private final static char[][] UNINIT_PATTERNS = new char[][] { "Non-initialized yet".toCharArray() }; //$NON-NLS-1$
97 private String rootID;
100 * Default inclusion pattern set
102 public final static IPath[] INCLUDE_ALL = {};
105 * Default exclusion pattern set
107 public final static IPath[] EXCLUDE_NONE = {};
110 * Default exclusion pattern set
112 public final static IPath[] NO_EXCLUSION_PATTERNS = {};
115 * Describes the path to the source archive associated with this classpath
116 * entry, or <code>null</code> if this classpath entry has no source
119 * Only library and variable classpath entries may have source attachments.
120 * For library classpath entries, the result path (if present) locates a
121 * source archive. For variable classpath entries, the result path (if
122 * present) has an analogous form and meaning as the variable path, namely
123 * the first segment is the name of a classpath variable.
125 public IPath sourceAttachmentPath;
128 * Describes the path within the source archive where package fragments are
129 * located. An empty path indicates that packages are located at the root of
130 * the source archive. Returns a non-<code>null</code> value if and only
131 * if <code>getSourceAttachmentPath</code> returns a non-<code>null</code>
134 public IPath sourceAttachmentRootPath;
137 * Specific output location (for this source entry)
139 public IPath specificOutputLocation;
142 * A constant indicating an output location.
144 public static final int K_OUTPUT = 10;
149 public boolean isExported;
152 * Creates a class path entry of the specified kind with the given path.
154 public ClasspathEntry(int contentKind, int entryKind, IPath path,
155 IPath[] inclusionPatterns, IPath[] exclusionPatterns,
156 IPath sourceAttachmentPath, IPath sourceAttachmentRootPath,
157 IPath specificOutputLocation, boolean isExported) {
159 this.contentKind = contentKind;
160 this.entryKind = entryKind;
162 this.inclusionPatterns = inclusionPatterns;
163 if (inclusionPatterns != INCLUDE_ALL && inclusionPatterns.length > 0) {
164 this.fullCharInclusionPatterns = UNINIT_PATTERNS;
166 this.fullCharInclusionPatterns = null; // empty inclusion pattern
167 // means everything is
170 this.exclusionPatterns = exclusionPatterns;
171 if (exclusionPatterns.length > 0) {
172 this.fullCharExclusionPatterns = UNINIT_PATTERNS;
174 this.sourceAttachmentPath = sourceAttachmentPath;
175 this.sourceAttachmentRootPath = sourceAttachmentRootPath;
176 this.specificOutputLocation = specificOutputLocation;
177 this.isExported = isExported;
181 * Returns a char based representation of the exclusions patterns full path.
183 public char[][] fullExclusionPatternChars() {
185 if (this.fullCharExclusionPatterns == UNINIT_PATTERNS) {
186 int length = this.exclusionPatterns.length;
187 this.fullCharExclusionPatterns = new char[length][];
188 IPath prefixPath = this.path.removeTrailingSeparator();
189 for (int i = 0; i < length; i++) {
190 this.fullCharExclusionPatterns[i] = prefixPath.append(
191 this.exclusionPatterns[i]).toString().toCharArray();
194 return this.fullCharExclusionPatterns;
198 * Returns a char based representation of the exclusions patterns full path.
200 public char[][] fullInclusionPatternChars() {
202 if (this.fullCharInclusionPatterns == UNINIT_PATTERNS) {
203 int length = this.inclusionPatterns.length;
204 this.fullCharInclusionPatterns = new char[length][];
205 IPath prefixPath = this.path.removeTrailingSeparator();
206 for (int i = 0; i < length; i++) {
207 this.fullCharInclusionPatterns[i] = prefixPath.append(
208 this.inclusionPatterns[i]).toString().toCharArray();
211 return this.fullCharInclusionPatterns;
215 * Returns the XML encoding of the class path.
217 public Element elementEncode(Document document, IPath projectPath)
218 throws JavaModelException {
220 Element element = document.createElement("classpathentry"); //$NON-NLS-1$
221 element.setAttribute("kind", kindToString(this.entryKind)); //$NON-NLS-1$
222 IPath xmlPath = this.path;
223 if (this.entryKind != IClasspathEntry.CPE_VARIABLE
224 && this.entryKind != IClasspathEntry.CPE_CONTAINER) {
225 // translate to project relative from absolute (unless a device
227 if (xmlPath.isAbsolute()) {
228 if (projectPath != null && projectPath.isPrefixOf(xmlPath)) {
229 if (xmlPath.segment(0).equals(projectPath.segment(0))) {
230 xmlPath = xmlPath.removeFirstSegments(1);
231 xmlPath = xmlPath.makeRelative();
233 xmlPath = xmlPath.makeAbsolute();
238 element.setAttribute("path", xmlPath.toString()); //$NON-NLS-1$
239 if (this.sourceAttachmentPath != null) {
240 element.setAttribute(
241 "sourcepath", this.sourceAttachmentPath.toString()); //$NON-NLS-1$
243 if (this.sourceAttachmentRootPath != null) {
244 element.setAttribute(
245 "rootpath", this.sourceAttachmentRootPath.toString()); //$NON-NLS-1$
247 if (this.isExported) {
248 element.setAttribute("exported", "true"); //$NON-NLS-1$ //$NON-NLS-2$
251 if (this.exclusionPatterns.length > 0) {
252 StringBuffer excludeRule = new StringBuffer(10);
253 for (int i = 0, max = this.exclusionPatterns.length; i < max; i++) {
255 excludeRule.append('|');
256 excludeRule.append(this.exclusionPatterns[i]);
258 element.setAttribute("excluding", excludeRule.toString()); //$NON-NLS-1$
261 if (this.specificOutputLocation != null) {
262 IPath outputLocation = this.specificOutputLocation
263 .removeFirstSegments(1);
264 outputLocation = outputLocation.makeRelative();
265 element.setAttribute("output", outputLocation.toString()); //$NON-NLS-1$
270 public static IClasspathEntry elementDecode(Element element,
271 IJavaProject project) {
273 IPath projectPath = project.getProject().getFullPath();
274 String kindAttr = element.getAttribute("kind"); //$NON-NLS-1$
275 String pathAttr = element.getAttribute("path"); //$NON-NLS-1$
277 // ensure path is absolute
278 IPath path = new Path(pathAttr);
279 int kind = kindFromString(kindAttr);
280 if (kind != IClasspathEntry.CPE_VARIABLE
281 && kind != IClasspathEntry.CPE_CONTAINER && !path.isAbsolute()) {
282 path = projectPath.append(path);
284 // source attachment info (optional)
285 // IPath sourceAttachmentPath = element.hasAttribute("sourcepath") //$NON-NLS-1$
286 // ? new Path(element.getAttribute("sourcepath")) //$NON-NLS-1$
288 // IPath sourceAttachmentRootPath = element.hasAttribute("rootpath") //$NON-NLS-1$
289 // ? new Path(element.getAttribute("rootpath")) //$NON-NLS-1$
292 // exported flag (optional)
293 boolean isExported = element.getAttribute("exported").equals("true"); //$NON-NLS-1$ //$NON-NLS-2$
295 // exclusion patterns (optional)
296 String exclusion = element.getAttribute("excluding"); //$NON-NLS-1$
297 IPath[] exclusionPatterns = ClasspathEntry.NO_EXCLUSION_PATTERNS;
298 if (!exclusion.equals("")) { //$NON-NLS-1$
299 char[][] patterns = CharOperation.splitOn('|', exclusion
302 if ((patternCount = patterns.length) > 0) {
303 exclusionPatterns = new IPath[patternCount];
304 for (int j = 0; j < patterns.length; j++) {
305 exclusionPatterns[j] = new Path(new String(patterns[j]));
310 // custom output location
311 IPath outputLocation = element.hasAttribute("output") ? projectPath.append(element.getAttribute("output")) : null; //$NON-NLS-1$ //$NON-NLS-2$
313 // recreate the CP entry
316 case IClasspathEntry.CPE_PROJECT:
317 return JavaCore.newProjectEntry(path, isExported);
319 // case IClasspathEntry.CPE_LIBRARY :
320 // return JavaCore.newLibraryEntry(
322 // sourceAttachmentPath,
323 // sourceAttachmentRootPath,
326 case IClasspathEntry.CPE_SOURCE:
327 // must be an entry in this project or specify another project
328 String projSegment = path.segment(0);
329 if (projSegment != null
330 && projSegment.equals(project.getElementName())) { // this
332 return JavaCore.newSourceEntry(path, exclusionPatterns,
334 } else { // another project
335 return JavaCore.newProjectEntry(path, isExported);
338 // case IClasspathEntry.CPE_VARIABLE :
339 // return PHPCore.newVariableEntry(
341 // sourceAttachmentPath,
342 // sourceAttachmentRootPath,
345 case IClasspathEntry.CPE_CONTAINER:
346 return JavaCore.newContainerEntry(path, isExported);
348 case ClasspathEntry.K_OUTPUT:
349 if (!path.isAbsolute())
351 return new ClasspathEntry(ClasspathEntry.K_OUTPUT,
352 IClasspathEntry.CPE_LIBRARY, path,
353 ClasspathEntry.INCLUDE_ALL, ClasspathEntry.EXCLUDE_NONE,
354 null, // source attachment
355 null, // source attachment root
356 null, // custom output location
360 throw new /*Assert.*/AssertionFailedException(Util.bind(
361 "classpath.unknownKind", kindAttr)); //$NON-NLS-1$
366 * Returns true if the given object is a classpath entry with equivalent
369 public boolean equals(Object object) {
372 if (object instanceof IClasspathEntry) {
373 IClasspathEntry otherEntry = (IClasspathEntry) object;
375 if (this.contentKind != otherEntry.getContentKind())
378 if (this.entryKind != otherEntry.getEntryKind())
381 if (this.isExported != otherEntry.isExported())
384 if (!this.path.equals(otherEntry.getPath()))
387 IPath otherPath = otherEntry.getSourceAttachmentPath();
388 if (this.sourceAttachmentPath == null) {
389 if (otherPath != null)
392 if (!this.sourceAttachmentPath.equals(otherPath))
396 otherPath = otherEntry.getSourceAttachmentRootPath();
397 if (this.sourceAttachmentRootPath == null) {
398 if (otherPath != null)
401 if (!this.sourceAttachmentRootPath.equals(otherPath))
405 IPath[] otherIncludes = otherEntry.getInclusionPatterns();
406 if (this.inclusionPatterns != otherIncludes) {
407 if (this.inclusionPatterns == null)
409 int includeLength = this.inclusionPatterns.length;
410 if (otherIncludes == null
411 || otherIncludes.length != includeLength)
413 for (int i = 0; i < includeLength; i++) {
414 // compare toStrings instead of IPaths
415 // since IPath.equals is specified to ignore trailing
417 if (!this.inclusionPatterns[i].toString().equals(
418 otherIncludes[i].toString()))
423 IPath[] otherExcludes = otherEntry.getExclusionPatterns();
424 if (this.exclusionPatterns != otherExcludes) {
425 int excludeLength = this.exclusionPatterns.length;
426 if (otherExcludes.length != excludeLength)
428 for (int i = 0; i < excludeLength; i++) {
429 // compare toStrings instead of IPaths
430 // since IPath.equals is specified to ignore trailing
432 if (!this.exclusionPatterns[i].toString().equals(
433 otherExcludes[i].toString()))
438 otherPath = otherEntry.getOutputLocation();
439 if (this.specificOutputLocation == null) {
440 if (otherPath != null)
443 if (!this.specificOutputLocation.equals(otherPath))
453 * @see IClasspathEntry
455 public int getContentKind() {
456 return this.contentKind;
460 * @see IClasspathEntry
462 public int getEntryKind() {
463 return this.entryKind;
467 * @see IClasspathEntry#getExclusionPatterns()
469 public IPath[] getExclusionPatterns() {
470 return this.exclusionPatterns;
474 * @see IClasspathEntry#getExclusionPatterns()
476 public IPath[] getInclusionPatterns() {
477 return this.inclusionPatterns;
481 * @see IClasspathEntry#getOutputLocation()
483 public IPath getOutputLocation() {
484 return this.specificOutputLocation;
488 * @see IClasspathEntry
490 public IPath getPath() {
495 * @see IClasspathEntry
497 public IPath getSourceAttachmentPath() {
498 return this.sourceAttachmentPath;
502 * @see IClasspathEntry
504 public IPath getSourceAttachmentRootPath() {
505 return this.sourceAttachmentRootPath;
509 * Returns the hash code for this classpath entry
511 public int hashCode() {
512 return this.path.hashCode();
516 * @see IClasspathEntry#isExported()
518 public boolean isExported() {
519 return this.isExported;
523 * Returns the kind of a <code>PackageFragmentRoot</code> from its
524 * <code>String</code> form.
526 static int kindFromString(String kindStr) {
528 if (kindStr.equalsIgnoreCase("prj")) //$NON-NLS-1$
529 return IClasspathEntry.CPE_PROJECT;
530 if (kindStr.equalsIgnoreCase("var")) //$NON-NLS-1$
531 return IClasspathEntry.CPE_VARIABLE;
532 if (kindStr.equalsIgnoreCase("con")) //$NON-NLS-1$
533 return IClasspathEntry.CPE_CONTAINER;
534 if (kindStr.equalsIgnoreCase("src")) //$NON-NLS-1$
535 return IClasspathEntry.CPE_SOURCE;
536 if (kindStr.equalsIgnoreCase("lib")) //$NON-NLS-1$
537 return IClasspathEntry.CPE_LIBRARY;
538 if (kindStr.equalsIgnoreCase("output")) //$NON-NLS-1$
539 return ClasspathEntry.K_OUTPUT;
544 * Returns a <code>String</code> for the kind of a class path entry.
546 static String kindToString(int kind) {
549 case IClasspathEntry.CPE_PROJECT:
550 return "src"; // backward compatibility //$NON-NLS-1$
551 case IClasspathEntry.CPE_SOURCE:
552 return "src"; //$NON-NLS-1$
553 case IClasspathEntry.CPE_LIBRARY:
554 return "lib"; //$NON-NLS-1$
555 case IClasspathEntry.CPE_VARIABLE:
556 return "var"; //$NON-NLS-1$
557 case IClasspathEntry.CPE_CONTAINER:
558 return "con"; //$NON-NLS-1$
559 case ClasspathEntry.K_OUTPUT:
560 return "output"; //$NON-NLS-1$
562 return "unknown"; //$NON-NLS-1$
567 * Returns a printable representation of this classpath entry.
569 public String toString() {
570 StringBuffer buffer = new StringBuffer();
571 buffer.append(getPath().toString());
573 switch (getEntryKind()) {
574 case IClasspathEntry.CPE_LIBRARY:
575 buffer.append("CPE_LIBRARY"); //$NON-NLS-1$
577 case IClasspathEntry.CPE_PROJECT:
578 buffer.append("CPE_PROJECT"); //$NON-NLS-1$
580 case IClasspathEntry.CPE_SOURCE:
581 buffer.append("CPE_SOURCE"); //$NON-NLS-1$
583 case IClasspathEntry.CPE_VARIABLE:
584 buffer.append("CPE_VARIABLE"); //$NON-NLS-1$
586 case IClasspathEntry.CPE_CONTAINER:
587 buffer.append("CPE_CONTAINER"); //$NON-NLS-1$
590 buffer.append("]["); //$NON-NLS-1$
591 switch (getContentKind()) {
592 case IPackageFragmentRoot.K_BINARY:
593 buffer.append("K_BINARY"); //$NON-NLS-1$
595 case IPackageFragmentRoot.K_SOURCE:
596 buffer.append("K_SOURCE"); //$NON-NLS-1$
598 case ClasspathEntry.K_OUTPUT:
599 buffer.append("K_OUTPUT"); //$NON-NLS-1$
603 if (getSourceAttachmentPath() != null) {
604 buffer.append("[sourcePath:"); //$NON-NLS-1$
605 buffer.append(getSourceAttachmentPath());
608 if (getSourceAttachmentRootPath() != null) {
609 buffer.append("[rootPath:"); //$NON-NLS-1$
610 buffer.append(getSourceAttachmentRootPath());
613 buffer.append("[isExported:"); //$NON-NLS-1$
614 buffer.append(this.isExported);
616 IPath[] patterns = getExclusionPatterns();
618 if ((length = patterns.length) > 0) {
619 buffer.append("[excluding:"); //$NON-NLS-1$
620 for (int i = 0; i < length; i++) {
621 buffer.append(patterns[i]);
622 if (i != length - 1) {
628 if (getOutputLocation() != null) {
629 buffer.append("[output:"); //$NON-NLS-1$
630 buffer.append(getOutputLocation());
633 return buffer.toString();
637 * Answers an ID which is used to distinguish entries during package
638 * fragment root computations
640 public String rootID() {
642 if (this.rootID == null) {
643 switch (this.entryKind) {
644 case IClasspathEntry.CPE_LIBRARY:
645 this.rootID = "[LIB]" + this.path; //$NON-NLS-1$
647 case IClasspathEntry.CPE_PROJECT:
648 this.rootID = "[PRJ]" + this.path; //$NON-NLS-1$
650 case IClasspathEntry.CPE_SOURCE:
651 this.rootID = "[SRC]" + this.path; //$NON-NLS-1$
653 case IClasspathEntry.CPE_VARIABLE:
654 this.rootID = "[VAR]" + this.path; //$NON-NLS-1$
656 case IClasspathEntry.CPE_CONTAINER:
657 this.rootID = "[CON]" + this.path; //$NON-NLS-1$
660 this.rootID = ""; //$NON-NLS-1$
668 * @see IClasspathEntry
671 public IClasspathEntry getResolvedEntry() {
673 return JavaCore.getResolvedClasspathEntry(this);
677 * Returns the XML encoding of the class path.
679 public void elementEncode(XMLWriter writer, IPath projectPath,
680 boolean indent, boolean newLine) {
681 HashMap parameters = new HashMap();
683 parameters.put("kind", ClasspathEntry.kindToString(this.entryKind));//$NON-NLS-1$
685 IPath xmlPath = this.path;
686 if (this.entryKind != IClasspathEntry.CPE_VARIABLE
687 && this.entryKind != IClasspathEntry.CPE_CONTAINER) {
688 // translate to project relative from absolute (unless a device
690 if (xmlPath.isAbsolute()) {
691 if (projectPath != null && projectPath.isPrefixOf(xmlPath)) {
692 if (xmlPath.segment(0).equals(projectPath.segment(0))) {
693 xmlPath = xmlPath.removeFirstSegments(1);
694 xmlPath = xmlPath.makeRelative();
696 xmlPath = xmlPath.makeAbsolute();
701 parameters.put("path", String.valueOf(xmlPath));//$NON-NLS-1$
703 if (this.sourceAttachmentPath != null) {
704 xmlPath = this.sourceAttachmentPath;
705 // translate to project relative from absolute
706 if (this.entryKind != IClasspathEntry.CPE_VARIABLE
707 && projectPath != null && projectPath.isPrefixOf(xmlPath)) {
708 if (xmlPath.segment(0).equals(projectPath.segment(0))) {
709 xmlPath = xmlPath.removeFirstSegments(1);
710 xmlPath = xmlPath.makeRelative();
713 parameters.put("sourcepath", String.valueOf(xmlPath));//$NON-NLS-1$
715 if (this.sourceAttachmentRootPath != null) {
717 "rootpath", String.valueOf(this.sourceAttachmentRootPath));//$NON-NLS-1$
719 if (this.isExported) {
720 parameters.put("exported", "true");//$NON-NLS-1$//$NON-NLS-2$
722 // if (this.inclusionPatterns != null && this.inclusionPatterns.length >
724 // StringBuffer includeRule = new StringBuffer(10);
725 // for (int i = 0, max = this.inclusionPatterns.length; i < max; i++){
726 // if (i > 0) includeRule.append('|');
727 // includeRule.append(this.inclusionPatterns[i]);
729 // parameters.put("including",
730 // String.valueOf(includeRule));//$NON-NLS-1$
732 if (this.exclusionPatterns != null && this.exclusionPatterns.length > 0) {
733 StringBuffer excludeRule = new StringBuffer(10);
734 for (int i = 0, max = this.exclusionPatterns.length; i < max; i++) {
736 excludeRule.append('|');
737 excludeRule.append(this.exclusionPatterns[i]);
739 parameters.put("excluding", String.valueOf(excludeRule));//$NON-NLS-1$
742 if (this.specificOutputLocation != null) {
743 IPath outputLocation = this.specificOutputLocation
744 .removeFirstSegments(1);
745 outputLocation = outputLocation.makeRelative();
746 parameters.put("output", String.valueOf(outputLocation));//$NON-NLS-1$
749 writer.printTag("classpathentry", parameters, indent, newLine, true);//$NON-NLS-1$
753 * Validate a given classpath and output location for a project, using the
756 * <li> Classpath entries cannot collide with each other; that is, all entry
757 * paths must be unique.
758 * <li> The project output location path cannot be null, must be absolute
759 * and located inside the project.
760 * <li> Specific output locations (specified on source entries) can be null,
761 * if not they must be located inside the project,
762 * <li> A project entry cannot refer to itself directly (that is, a project
763 * cannot prerequisite itself).
764 * <li> Classpath entries or output locations cannot coincidate or be nested
765 * in each other, except for the following scenarii listed below:
767 * <li> A source folder can coincidate with its own output location, in
768 * which case this output can then contain library archives. However, a
769 * specific output location cannot coincidate with any library or a distinct
770 * source folder than the one referring to it. </li>
771 * <li> A source/library folder can be nested in any source folder as long
772 * as the nested folder is excluded from the enclosing one. </li>
773 * <li> An output location can be nested in a source folder, if the source
774 * folder coincidates with the project itself, or if the output location is
775 * excluded from the source folder. </li>
779 * Note that the classpath entries are not validated automatically. Only
780 * bound variables or containers are considered in the checking process
781 * (this allows to perform a consistency check on a classpath which has
782 * references to yet non existing projects, folders, ...).
784 * This validation is intended to anticipate classpath issues prior to
785 * assigning it to a project. In particular, it will automatically be
786 * performed during the classpath setting operation (if validation fails,
787 * the classpath setting will not complete).
791 * the given java project
792 * @param rawClasspath
794 * @param projectOutputLocation
795 * a given output location
796 * @return a status object with code <code>IStatus.OK</code> if the given
797 * classpath and output location are compatible, otherwise a status
798 * object indicating what is wrong with the classpath or output
801 public static IJavaModelStatus validateClasspath(IJavaProject javaProject,
802 IClasspathEntry[] rawClasspath, IPath projectOutputLocation) {
804 IProject project = javaProject.getProject();
805 IPath projectPath = project.getFullPath();
806 String projectName = javaProject.getElementName();
808 /* validate output location */
809 if (projectOutputLocation == null) {
810 return new JavaModelStatus(IJavaModelStatusConstants.NULL_PATH);
812 if (projectOutputLocation.isAbsolute()) {
813 if (!projectPath.isPrefixOf(projectOutputLocation)) {
814 return new JavaModelStatus(
815 IJavaModelStatusConstants.PATH_OUTSIDE_PROJECT,
816 javaProject, projectOutputLocation.toString());
819 return new JavaModelStatus(IJavaModelStatusConstants.RELATIVE_PATH,
820 projectOutputLocation);
823 boolean hasSource = false;
824 boolean hasLibFolder = false;
826 // tolerate null path, it will be reset to default
827 if (rawClasspath == null)
828 return JavaModelStatus.VERIFIED_OK;
830 // retrieve resolved classpath
831 IClasspathEntry[] classpath;
833 classpath = ((JavaProject) javaProject).getResolvedClasspath(
834 rawClasspath, null /* output */, true/* ignore pb */,
835 false/* no marker */, null /* no reverse map */);
836 } catch (JavaModelException e) {
837 return e.getJavaModelStatus();
839 int length = classpath.length;
842 IPath[] outputLocations = new IPath[length + 1];
843 boolean[] allowNestingInOutputLocations = new boolean[length + 1];
844 outputLocations[0] = projectOutputLocation;
846 // retrieve and check output locations
847 IPath potentialNestedOutput = null; // for error reporting purpose
848 int sourceEntryCount = 0;
849 boolean disableExclusionPatterns = JavaCore.DISABLED.equals(javaProject
850 .getOption(JavaCore.CORE_ENABLE_CLASSPATH_EXCLUSION_PATTERNS,
852 boolean disableCustomOutputLocations = JavaCore.DISABLED
855 JavaCore.CORE_ENABLE_CLASSPATH_MULTIPLE_OUTPUT_LOCATIONS,
858 for (int i = 0; i < length; i++) {
859 IClasspathEntry resolvedEntry = classpath[i];
860 switch (resolvedEntry.getEntryKind()) {
861 case IClasspathEntry.CPE_SOURCE:
864 if (disableExclusionPatterns
865 && ((resolvedEntry.getInclusionPatterns() != null && resolvedEntry
866 .getInclusionPatterns().length > 0) || (resolvedEntry
867 .getExclusionPatterns() != null && resolvedEntry
868 .getExclusionPatterns().length > 0))) {
869 return new JavaModelStatus(
870 IJavaModelStatusConstants.DISABLED_CP_EXCLUSION_PATTERNS,
871 javaProject, resolvedEntry.getPath());
874 if ((customOutput = resolvedEntry.getOutputLocation()) != null) {
876 if (disableCustomOutputLocations) {
877 return new JavaModelStatus(
878 IJavaModelStatusConstants.DISABLED_CP_MULTIPLE_OUTPUT_LOCATIONS,
879 javaProject, resolvedEntry.getPath());
881 // ensure custom output is in project
882 if (customOutput.isAbsolute()) {
883 if (!javaProject.getPath().isPrefixOf(customOutput)) {
884 return new JavaModelStatus(
885 IJavaModelStatusConstants.PATH_OUTSIDE_PROJECT,
886 javaProject, customOutput.toString());
889 return new JavaModelStatus(
890 IJavaModelStatusConstants.RELATIVE_PATH,
894 // ensure custom output doesn't conflict with other outputs
896 if (Util.indexOfMatchingPath(customOutput, outputLocations,
897 outputCount) != -1) {
898 continue; // already found
900 // accumulate all outputs, will check nesting once all
901 // available (to handle ordering issues)
902 outputLocations[outputCount++] = customOutput;
906 // check nesting across output locations
907 for (int i = 1 /* no check for default output */; i < outputCount; i++) {
908 IPath customOutput = outputLocations[i];
911 if ((index = Util.indexOfEnclosingPath(customOutput,
912 outputLocations, outputCount)) != -1
915 // custom output is nested in project's output: need to
916 // check if all source entries have a custom
917 // output before complaining
918 if (potentialNestedOutput == null)
919 potentialNestedOutput = customOutput;
921 return new JavaModelStatus(
922 IJavaModelStatusConstants.INVALID_CLASSPATH,
925 "classpath.cannotNestOutputInOutput", customOutput.makeRelative().toString(), outputLocations[index].makeRelative().toString())); //$NON-NLS-1$
929 // allow custom output nesting in project's output if all source entries
930 // have a custom output
931 if (sourceEntryCount <= outputCount - 1) {
932 allowNestingInOutputLocations[0] = true;
933 } else if (potentialNestedOutput != null) {
934 return new JavaModelStatus(
935 IJavaModelStatusConstants.INVALID_CLASSPATH,
938 "classpath.cannotNestOutputInOutput", potentialNestedOutput.makeRelative().toString(), outputLocations[0].makeRelative().toString())); //$NON-NLS-1$
941 for (int i = 0; i < length; i++) {
942 IClasspathEntry resolvedEntry = classpath[i];
943 IPath path = resolvedEntry.getPath();
945 switch (resolvedEntry.getEntryKind()) {
947 case IClasspathEntry.CPE_SOURCE:
949 if ((index = Util.indexOfMatchingPath(path, outputLocations,
950 outputCount)) != -1) {
951 allowNestingInOutputLocations[index] = true;
955 // case IClasspathEntry.CPE_LIBRARY:
957 // !org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(path.lastSegment());
958 // if ((index = Util.indexOfMatchingPath(path, outputLocations,
959 // outputCount)) != -1){
960 // allowNestingInOutputLocations[index] = true;
965 if (!hasSource && !hasLibFolder) { // if no source and no lib folder,
967 for (int i = 0; i < outputCount; i++)
968 allowNestingInOutputLocations[i] = true;
971 HashSet pathes = new HashSet(length);
974 for (int i = 0; i < length; i++) {
975 IClasspathEntry entry = classpath[i];
978 IPath entryPath = entry.getPath();
979 int kind = entry.getEntryKind();
981 // Build some common strings for status message
982 boolean isProjectRelative = entryPath.segment(0).toString().equals(
984 String entryPathMsg = isProjectRelative ? entryPath
985 .removeFirstSegments(1).toString() : entryPath
986 .makeRelative().toString();
988 // complain if duplicate path
989 if (!pathes.add(entryPath)) {
990 return new JavaModelStatus(
991 IJavaModelStatusConstants.NAME_COLLISION,
994 "classpath.duplicateEntryPath", entryPathMsg, projectName)); //$NON-NLS-1$
996 // no further check if entry coincidates with project or output
998 if (entryPath.equals(projectPath)) {
999 // complain if self-referring project entry
1000 if (kind == IClasspathEntry.CPE_PROJECT) {
1001 return new JavaModelStatus(
1002 IJavaModelStatusConstants.INVALID_PATH,
1005 "classpath.cannotReferToItself", entryPath.makeRelative().toString()));//$NON-NLS-1$
1007 // tolerate nesting output in src if src==prj
1011 // allow nesting source entries in each other as long as the outer
1012 // entry excludes the inner one
1013 if (kind == IClasspathEntry.CPE_SOURCE) {
1014 // || (kind == IClasspathEntry.CPE_LIBRARY &&
1015 // !org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(entryPath.lastSegment()))){
1016 for (int j = 0; j < classpath.length; j++) {
1017 IClasspathEntry otherEntry = classpath[j];
1018 if (otherEntry == null)
1020 int otherKind = otherEntry.getEntryKind();
1021 IPath otherPath = otherEntry.getPath();
1022 if (entry != otherEntry
1023 && (otherKind == IClasspathEntry.CPE_SOURCE)) {
1024 // || (otherKind == IClasspathEntry.CPE_LIBRARY
1026 // !org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(otherPath.lastSegment())))){
1027 char[][] inclusionPatterns, exclusionPatterns;
1028 if (otherPath.isPrefixOf(entryPath)
1029 && !otherPath.equals(entryPath)
1032 entryPath.append("*"), inclusionPatterns = ((ClasspathEntry) otherEntry).fullInclusionPatternChars(), exclusionPatterns = ((ClasspathEntry) otherEntry).fullExclusionPatternChars(), false)) { //$NON-NLS-1$
1033 String exclusionPattern = entryPath
1034 .removeFirstSegments(
1035 otherPath.segmentCount())
1037 if (Util.isExcluded(entryPath, inclusionPatterns,
1038 exclusionPatterns, false)) {
1039 return new JavaModelStatus(
1040 IJavaModelStatusConstants.INVALID_CLASSPATH,
1043 "classpath.mustEndWithSlash", exclusionPattern, entryPath.makeRelative().toString())); //$NON-NLS-1$
1045 if (otherKind == IClasspathEntry.CPE_SOURCE) {
1046 exclusionPattern += '/';
1047 return new JavaModelStatus(
1048 IJavaModelStatusConstants.INVALID_CLASSPATH,
1051 "classpath.cannotNestEntryInEntry", new String[] { entryPath.makeRelative().toString(), otherEntry.getPath().makeRelative().toString(), exclusionPattern })); //$NON-NLS-1$
1053 return new JavaModelStatus(
1054 IJavaModelStatusConstants.INVALID_CLASSPATH,
1057 "classpath.cannotNestEntryInLibrary", entryPath.makeRelative().toString(), otherEntry.getPath().makeRelative().toString())); //$NON-NLS-1$
1065 // prevent nesting output location inside entry unless enclosing is
1066 // a source entry which explicitly exclude the output location
1067 char[][] inclusionPatterns = ((ClasspathEntry) entry)
1068 .fullInclusionPatternChars();
1069 char[][] exclusionPatterns = ((ClasspathEntry) entry)
1070 .fullExclusionPatternChars();
1071 for (int j = 0; j < outputCount; j++) {
1072 IPath currentOutput = outputLocations[j];
1073 if (entryPath.equals(currentOutput))
1075 if (entryPath.isPrefixOf(currentOutput)) {
1076 if (kind != IClasspathEntry.CPE_SOURCE
1077 || !Util.isExcluded(currentOutput,
1078 inclusionPatterns, exclusionPatterns, true)) {
1079 return new JavaModelStatus(
1080 IJavaModelStatusConstants.INVALID_CLASSPATH,
1083 "classpath.cannotNestOutputInEntry", currentOutput.makeRelative().toString(), entryPath.makeRelative().toString())); //$NON-NLS-1$
1088 // prevent nesting entry inside output location - when distinct from
1089 // project or a source folder
1090 for (int j = 0; j < outputCount; j++) {
1091 if (allowNestingInOutputLocations[j])
1093 IPath currentOutput = outputLocations[j];
1094 if (currentOutput.isPrefixOf(entryPath)) {
1095 return new JavaModelStatus(
1096 IJavaModelStatusConstants.INVALID_CLASSPATH,
1099 "classpath.cannotNestEntryInOutput", entryPath.makeRelative().toString(), currentOutput.makeRelative().toString())); //$NON-NLS-1$
1103 // ensure that no specific output is coincidating with another source
1104 // folder (only allowed if matching current source folder)
1105 // 36465 - for 2.0 backward compatibility, only check specific output
1106 // locations (the default can still coincidate)
1107 // perform one separate iteration so as to not take precedence over
1108 // previously checked scenarii (in particular should
1109 // diagnose nesting source folder issue before this one, for example,
1110 // [src]"Project/", [src]"Project/source/" and output="Project/" should
1111 // first complain about missing exclusion pattern
1112 for (int i = 0; i < length; i++) {
1113 IClasspathEntry entry = classpath[i];
1116 IPath entryPath = entry.getPath();
1117 int kind = entry.getEntryKind();
1119 // Build some common strings for status message
1120 boolean isProjectRelative = entryPath.segment(0).toString().equals(
1122 String entryPathMsg = isProjectRelative ? entryPath
1123 .removeFirstSegments(1).toString() : entryPath
1124 .makeRelative().toString();
1126 if (kind == IClasspathEntry.CPE_SOURCE) {
1127 IPath output = entry.getOutputLocation();
1129 continue; // 36465 - for 2.0 backward compatibility, only
1130 // check specific output locations (the default
1131 // can still coincidate)
1132 // if (output == null) output = projectOutputLocation; // if no
1133 // specific output, still need to check using default output
1134 // (this line would check default output)
1135 for (int j = 0; j < length; j++) {
1136 IClasspathEntry otherEntry = classpath[j];
1137 if (otherEntry == entry)
1140 // Build some common strings for status message
1141 boolean opStartsWithProject = otherEntry.getPath().segment(
1142 0).toString().equals(projectName);
1143 String otherPathMsg = opStartsWithProject ? otherEntry
1144 .getPath().removeFirstSegments(1).toString()
1145 : otherEntry.getPath().makeRelative().toString();
1147 switch (otherEntry.getEntryKind()) {
1148 case IClasspathEntry.CPE_SOURCE:
1149 if (otherEntry.getPath().equals(output)) {
1150 return new JavaModelStatus(
1151 IJavaModelStatusConstants.INVALID_CLASSPATH,
1154 "classpath.cannotUseDistinctSourceFolderAsOutput", new String[] { entryPathMsg, otherPathMsg, projectName })); //$NON-NLS-1$
1157 case IClasspathEntry.CPE_LIBRARY:
1158 if (otherEntry.getPath().equals(output)) {
1159 return new JavaModelStatus(
1160 IJavaModelStatusConstants.INVALID_CLASSPATH,
1163 "classpath.cannotUseLibraryAsOutput", new String[] { entryPathMsg, otherPathMsg, projectName })); //$NON-NLS-1$
1169 return JavaModelStatus.VERIFIED_OK;
1173 * Returns a Java model status describing the problem related to this
1174 * classpath entry if any, a status object with code <code>IStatus.OK</code>
1175 * if the entry is fine (that is, if the given classpath entry denotes a
1176 * valid element to be referenced onto a classpath).
1179 * the given java project
1181 * the given classpath entry
1182 * @param checkSourceAttachment
1183 * a flag to determine if source attachement should be checked
1184 * @param recurseInContainers
1185 * flag indicating whether validation should be applied to
1186 * container entries recursively
1187 * @return a java model status describing the problem related to this
1188 * classpath entry if any, a status object with code
1189 * <code>IStatus.OK</code> if the entry is fine
1191 public static IJavaModelStatus validateClasspathEntry(IJavaProject project,
1192 IClasspathEntry entry, boolean checkSourceAttachment,
1193 boolean recurseInContainers) {
1195 IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
1196 IPath path = entry.getPath();
1198 // Build some common strings for status message
1199 String projectName = project.getElementName();
1200 boolean pathStartsWithProject = path.segment(0).toString().equals(
1202 String entryPathMsg = pathStartsWithProject ? path.removeFirstSegments(
1203 1).toString() : path.makeRelative().toString();
1205 switch (entry.getEntryKind()) {
1207 // container entry check
1208 // case IClasspathEntry.CPE_CONTAINER :
1209 // if (path != null && path.segmentCount() >= 1){
1211 // IClasspathContainer container =
1212 // JavaModelManager.getJavaModelManager().getClasspathContainer(path,
1214 // // container retrieval is performing validation check on container
1216 // if (container == null){
1218 // JavaModelStatus(IJavaModelStatusConstants.CP_CONTAINER_PATH_UNBOUND,
1220 // } else if (container ==
1221 // JavaModelManager.CONTAINER_INITIALIZATION_IN_PROGRESS) {
1222 // // don't create a marker if initialization is in progress (case of cp
1223 // initialization batching)
1224 // return JavaModelStatus.VERIFIED_OK;
1226 // IClasspathEntry[] containerEntries = container.getClasspathEntries();
1227 // if (containerEntries != null){
1228 // for (int i = 0, length = containerEntries.length; i < length; i++){
1229 // IClasspathEntry containerEntry = containerEntries[i];
1230 // int kind = containerEntry == null ? 0 :
1231 // containerEntry.getEntryKind();
1232 // if (containerEntry == null
1233 // || kind == IClasspathEntry.CPE_SOURCE
1234 // || kind == IClasspathEntry.CPE_VARIABLE
1235 // || kind == IClasspathEntry.CPE_CONTAINER){
1236 // String description = container.getDescription();
1237 // if (description == null) description =
1238 // path.makeRelative().toString();
1240 // JavaModelStatus(IJavaModelStatusConstants.INVALID_CP_CONTAINER_ENTRY,
1243 // if (recurseInContainers) {
1244 // IJavaModelStatus containerEntryStatus =
1245 // validateClasspathEntry(project, containerEntry,
1246 // checkSourceAttachment, recurseInContainers);
1247 // if (!containerEntryStatus.isOK()){
1248 // return containerEntryStatus;
1253 // } catch(JavaModelException e){
1254 // return new JavaModelStatus(e);
1258 // JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH,
1259 // Util.bind("classpath.illegalContainerPath", entryPathMsg,
1260 // projectName)); //$NON-NLS-1$
1264 // variable entry check
1265 case IClasspathEntry.CPE_VARIABLE:
1266 if (path != null && path.segmentCount() >= 1) {
1268 entry = JavaCore.getResolvedClasspathEntry(entry);
1269 } catch (/*Assert.*/AssertionFailedException e) {
1270 // Catch the assertion failure and throw java model
1271 // exception instead
1273 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=55992
1274 return new JavaModelStatus(
1275 IJavaModelStatusConstants.INVALID_PATH, e
1278 if (entry == null) {
1279 return new JavaModelStatus(
1280 IJavaModelStatusConstants.CP_VARIABLE_PATH_UNBOUND,
1283 return validateClasspathEntry(project, entry,
1284 checkSourceAttachment, recurseInContainers);
1286 return new JavaModelStatus(
1287 IJavaModelStatusConstants.INVALID_CLASSPATH,
1290 "classpath.illegalVariablePath", path.makeRelative().toString(), projectName)); //$NON-NLS-1$
1293 // library entry check
1294 // case IClasspathEntry.CPE_LIBRARY :
1295 // if (path != null && path.isAbsolute() && !path.isEmpty()) {
1296 // IPath sourceAttachment = entry.getSourceAttachmentPath();
1297 // Object target = JavaModel.getTarget(workspaceRoot, path, true);
1298 // if (target != null &&
1299 // project.getOption(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL, true) !=
1300 // JavaCore.IGNORE) {
1301 // long projectTargetJDK =
1302 // CompilerOptions.versionToJdkLevel(project.getOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM,
1304 // long libraryJDK = Util.getJdkLevel(target);
1305 // if (libraryJDK != 0 && libraryJDK > projectTargetJDK) {
1307 // JavaModelStatus(IJavaModelStatusConstants.INCOMPATIBLE_JDK_LEVEL,
1308 // project, path, CompilerOptions.versionFromJdkLevel(libraryJDK));
1311 // if (target instanceof IResource){
1312 // IResource resolvedResource = (IResource) target;
1313 // switch(resolvedResource.getType()){
1314 // case IResource.FILE :
1316 // (org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(resolvedResource.getName()))
1318 // if (checkSourceAttachment
1319 // && sourceAttachment != null
1320 // && !sourceAttachment.isEmpty()
1321 // && JavaModel.getTarget(workspaceRoot, sourceAttachment, true) ==
1324 // JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH,
1325 // Util.bind("classpath.unboundSourceAttachment", new String []
1326 // {sourceAttachment.makeRelative().toString(),
1327 // path.makeRelative().toString(), projectName})); //$NON-NLS-1$
1331 // JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH,
1332 // Util.bind("classpath.illegalLibraryArchive", entryPathMsg,
1333 // projectName)); //$NON-NLS-1$
1336 // case IResource.FOLDER : // internal binary folder
1337 // if (checkSourceAttachment
1338 // && sourceAttachment != null
1339 // && !sourceAttachment.isEmpty()
1340 // && JavaModel.getTarget(workspaceRoot, sourceAttachment, true) ==
1343 // JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH,
1344 // Util.bind("classpath.unboundSourceAttachment", new String []
1345 // {sourceAttachment.makeRelative().toString(),
1346 // path.makeRelative().toString(), projectName})); //$NON-NLS-1$
1349 // } else if (target instanceof File){
1350 // File file = (File) target;
1351 // if (!file.isFile()) {
1353 // JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH,
1354 // Util.bind("classpath.illegalExternalFolder", path.toOSString(),
1355 // projectName)); //$NON-NLS-1$
1357 // (!org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(file.getName()))
1360 // JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH,
1361 // Util.bind("classpath.illegalLibraryArchive", path.toOSString(),
1362 // projectName)); //$NON-NLS-1$
1363 // } else if (checkSourceAttachment
1364 // && sourceAttachment != null
1365 // && !sourceAttachment.isEmpty()
1366 // && JavaModel.getTarget(workspaceRoot, sourceAttachment, true) ==
1369 // JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH,
1370 // Util.bind("classpath.unboundSourceAttachment", new String []
1371 // {sourceAttachment.toString(), path.makeRelative().toString(),
1372 // projectName})); //$NON-NLS-1$
1376 // JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH,
1377 // Util.bind("classpath.unboundLibrary",
1378 // path.makeRelative().toString(), projectName)); //$NON-NLS-1$
1382 // JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH,
1383 // Util.bind("classpath.illegalLibraryPath",
1384 // path.makeRelative().toString(), projectName)); //$NON-NLS-1$
1388 // project entry check
1389 case IClasspathEntry.CPE_PROJECT:
1390 if (path != null && path.isAbsolute() && !path.isEmpty()) {
1391 IProject prereqProjectRsc = workspaceRoot.getProject(path
1393 //IJavaProject prereqProject = JavaCore.create(prereqProjectRsc);
1395 if (!prereqProjectRsc.exists()
1396 || !prereqProjectRsc
1397 .hasNature(PHPeclipsePlugin.PHP_NATURE_ID)) {
1398 return new JavaModelStatus(
1399 IJavaModelStatusConstants.INVALID_CLASSPATH,
1402 "classpath.unboundProject", path.makeRelative().segment(0).toString(), projectName)); //$NON-NLS-1$
1404 if (!prereqProjectRsc.isOpen()) {
1405 return new JavaModelStatus(
1406 IJavaModelStatusConstants.INVALID_CLASSPATH,
1409 "classpath.closedProject", path.segment(0).toString())); //$NON-NLS-1$
1412 // (project.getOption(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL,
1413 // true) != JavaCore.IGNORE) {
1414 // long projectTargetJDK =
1415 // CompilerOptions.versionToJdkLevel(project.getOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM,
1417 // long prereqProjectTargetJDK =
1418 // CompilerOptions.versionToJdkLevel(prereqProject.getOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM,
1420 // if (prereqProjectTargetJDK > projectTargetJDK) {
1422 // JavaModelStatus(IJavaModelStatusConstants.INCOMPATIBLE_JDK_LEVEL,
1424 // CompilerOptions.versionFromJdkLevel(prereqProjectTargetJDK));
1427 } catch (CoreException e) {
1428 return new JavaModelStatus(
1429 IJavaModelStatusConstants.INVALID_CLASSPATH,
1432 "classpath.unboundProject", path.segment(0).toString(), projectName)); //$NON-NLS-1$
1435 return new JavaModelStatus(
1436 IJavaModelStatusConstants.INVALID_CLASSPATH,
1439 "classpath.illegalProjectPath", path.segment(0).toString(), projectName)); //$NON-NLS-1$
1443 // project source folder
1444 case IClasspathEntry.CPE_SOURCE:
1445 if (((entry.getInclusionPatterns() != null && entry
1446 .getInclusionPatterns().length > 0) || (entry
1447 .getExclusionPatterns() != null && entry
1448 .getExclusionPatterns().length > 0))
1449 && JavaCore.DISABLED.equals(project.getOption(
1450 JavaCore.CORE_ENABLE_CLASSPATH_EXCLUSION_PATTERNS,
1452 return new JavaModelStatus(
1453 IJavaModelStatusConstants.DISABLED_CP_EXCLUSION_PATTERNS,
1456 if (entry.getOutputLocation() != null
1457 && JavaCore.DISABLED
1460 JavaCore.CORE_ENABLE_CLASSPATH_MULTIPLE_OUTPUT_LOCATIONS,
1462 return new JavaModelStatus(
1463 IJavaModelStatusConstants.DISABLED_CP_MULTIPLE_OUTPUT_LOCATIONS,
1466 if (path != null && path.isAbsolute() && !path.isEmpty()) {
1467 IPath projectPath = project.getProject().getFullPath();
1468 if (!projectPath.isPrefixOf(path)
1469 || JavaModel.getTarget(workspaceRoot, path, true) == null) {
1470 return new JavaModelStatus(
1471 IJavaModelStatusConstants.INVALID_CLASSPATH,
1474 "classpath.unboundSourceFolder", entryPathMsg, projectName)); //$NON-NLS-1$
1477 return new JavaModelStatus(
1478 IJavaModelStatusConstants.INVALID_CLASSPATH,
1481 "classpath.illegalSourceFolderPath", entryPathMsg, projectName)); //$NON-NLS-1$
1485 return JavaModelStatus.VERIFIED_OK;