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;
25 import net.sourceforge.phpdt.internal.corext.Assert;
26 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
28 import org.eclipse.core.resources.IProject;
29 import org.eclipse.core.resources.IWorkspaceRoot;
30 import org.eclipse.core.resources.ResourcesPlugin;
31 import org.eclipse.core.runtime.CoreException;
32 import org.eclipse.core.runtime.IPath;
33 import org.eclipse.core.runtime.Path;
34 import org.w3c.dom.Document;
35 import org.w3c.dom.Element;
38 * @see IClasspathEntry
40 public class ClasspathEntry implements IClasspathEntry {
43 * Describes the kind of classpath entry - one of CPE_PROJECT, CPE_LIBRARY,
44 * CPE_SOURCE, CPE_VARIABLE or CPE_CONTAINER
49 * Describes the kind of package fragment roots found on this classpath
50 * entry - either K_BINARY or K_SOURCE or K_OUTPUT.
52 public int contentKind;
55 * The meaning of the path of a classpath entry depends on its entry kind:
57 * <li>Source code in the current project (<code>CPE_SOURCE</code>) -
58 * The path associated with this entry is the absolute path to the root
60 * <li>A binary library in the current project (<code>CPE_LIBRARY</code>) -
61 * the path associated with this entry is the absolute path to the JAR (or
62 * root folder), and in case it refers to an external JAR, then there is no
63 * associated resource in the workbench.
64 * <li>A required project (<code>CPE_PROJECT</code>) - the path of the
65 * entry denotes the path to the corresponding project resource.</li>
66 * <li>A variable entry (<code>CPE_VARIABLE</code>) - the first segment
67 * of the path is the name of a classpath variable. If this classpath
68 * variable is bound to the path <it>P</it>, the path of the corresponding
69 * classpath entry is computed by appending to <it>P</it> the segments of
70 * the returned path without the variable.</li>
71 * <li> A container entry (<code>CPE_CONTAINER</code>) - the first
72 * segment of the path is denoting the unique container identifier (for
73 * which a <code>ClasspathContainerInitializer</code> could be
74 * registered), and the remaining segments are used as additional hints for
75 * resolving the container entry to an actual
76 * <code>IClasspathContainer</code>.</li>
81 * Patterns allowing to include/exclude portions of the resource tree
82 * denoted by this entry path.
84 public IPath[] inclusionPatterns;
86 private char[][] fullCharInclusionPatterns;
88 public IPath[] exclusionPatterns;
90 private char[][] fullCharExclusionPatterns;
92 private final static char[][] UNINIT_PATTERNS = new char[][] { "Non-initialized yet".toCharArray() }; //$NON-NLS-1$
94 private String rootID;
97 * Default inclusion pattern set
99 public final static IPath[] INCLUDE_ALL = {};
102 * Default exclusion pattern set
104 public final static IPath[] EXCLUDE_NONE = {};
107 * Default exclusion pattern set
109 public final static IPath[] NO_EXCLUSION_PATTERNS = {};
112 * Describes the path to the source archive associated with this classpath
113 * entry, or <code>null</code> if this classpath entry has no source
116 * Only library and variable classpath entries may have source attachments.
117 * For library classpath entries, the result path (if present) locates a
118 * source archive. For variable classpath entries, the result path (if
119 * present) has an analogous form and meaning as the variable path, namely
120 * the first segment is the name of a classpath variable.
122 public IPath sourceAttachmentPath;
125 * Describes the path within the source archive where package fragments are
126 * located. An empty path indicates that packages are located at the root of
127 * the source archive. Returns a non-<code>null</code> value if and only
128 * if <code>getSourceAttachmentPath</code> returns a non-<code>null</code>
131 public IPath sourceAttachmentRootPath;
134 * Specific output location (for this source entry)
136 public IPath specificOutputLocation;
139 * A constant indicating an output location.
141 public static final int K_OUTPUT = 10;
146 public boolean isExported;
149 * Creates a class path entry of the specified kind with the given path.
151 public ClasspathEntry(int contentKind, int entryKind, IPath path,
152 IPath[] inclusionPatterns, IPath[] exclusionPatterns,
153 IPath sourceAttachmentPath, IPath sourceAttachmentRootPath,
154 IPath specificOutputLocation, boolean isExported) {
156 this.contentKind = contentKind;
157 this.entryKind = entryKind;
159 this.inclusionPatterns = inclusionPatterns;
160 if (inclusionPatterns != INCLUDE_ALL && inclusionPatterns.length > 0) {
161 this.fullCharInclusionPatterns = UNINIT_PATTERNS;
163 this.fullCharInclusionPatterns = null; // empty inclusion pattern
164 // means everything is
167 this.exclusionPatterns = exclusionPatterns;
168 if (exclusionPatterns.length > 0) {
169 this.fullCharExclusionPatterns = UNINIT_PATTERNS;
171 this.sourceAttachmentPath = sourceAttachmentPath;
172 this.sourceAttachmentRootPath = sourceAttachmentRootPath;
173 this.specificOutputLocation = specificOutputLocation;
174 this.isExported = isExported;
178 * Returns a char based representation of the exclusions patterns full path.
180 public char[][] fullExclusionPatternChars() {
182 if (this.fullCharExclusionPatterns == UNINIT_PATTERNS) {
183 int length = this.exclusionPatterns.length;
184 this.fullCharExclusionPatterns = new char[length][];
185 IPath prefixPath = this.path.removeTrailingSeparator();
186 for (int i = 0; i < length; i++) {
187 this.fullCharExclusionPatterns[i] = prefixPath.append(
188 this.exclusionPatterns[i]).toString().toCharArray();
191 return this.fullCharExclusionPatterns;
195 * Returns a char based representation of the exclusions patterns full path.
197 public char[][] fullInclusionPatternChars() {
199 if (this.fullCharInclusionPatterns == UNINIT_PATTERNS) {
200 int length = this.inclusionPatterns.length;
201 this.fullCharInclusionPatterns = new char[length][];
202 IPath prefixPath = this.path.removeTrailingSeparator();
203 for (int i = 0; i < length; i++) {
204 this.fullCharInclusionPatterns[i] = prefixPath.append(
205 this.inclusionPatterns[i]).toString().toCharArray();
208 return this.fullCharInclusionPatterns;
212 * Returns the XML encoding of the class path.
214 public Element elementEncode(Document document, IPath projectPath)
215 throws JavaModelException {
217 Element element = document.createElement("classpathentry"); //$NON-NLS-1$
218 element.setAttribute("kind", kindToString(this.entryKind)); //$NON-NLS-1$
219 IPath xmlPath = this.path;
220 if (this.entryKind != IClasspathEntry.CPE_VARIABLE
221 && this.entryKind != IClasspathEntry.CPE_CONTAINER) {
222 // translate to project relative from absolute (unless a device
224 if (xmlPath.isAbsolute()) {
225 if (projectPath != null && projectPath.isPrefixOf(xmlPath)) {
226 if (xmlPath.segment(0).equals(projectPath.segment(0))) {
227 xmlPath = xmlPath.removeFirstSegments(1);
228 xmlPath = xmlPath.makeRelative();
230 xmlPath = xmlPath.makeAbsolute();
235 element.setAttribute("path", xmlPath.toString()); //$NON-NLS-1$
236 if (this.sourceAttachmentPath != null) {
237 element.setAttribute(
238 "sourcepath", this.sourceAttachmentPath.toString()); //$NON-NLS-1$
240 if (this.sourceAttachmentRootPath != null) {
241 element.setAttribute(
242 "rootpath", this.sourceAttachmentRootPath.toString()); //$NON-NLS-1$
244 if (this.isExported) {
245 element.setAttribute("exported", "true"); //$NON-NLS-1$ //$NON-NLS-2$
248 if (this.exclusionPatterns.length > 0) {
249 StringBuffer excludeRule = new StringBuffer(10);
250 for (int i = 0, max = this.exclusionPatterns.length; i < max; i++) {
252 excludeRule.append('|');
253 excludeRule.append(this.exclusionPatterns[i]);
255 element.setAttribute("excluding", excludeRule.toString()); //$NON-NLS-1$
258 if (this.specificOutputLocation != null) {
259 IPath outputLocation = this.specificOutputLocation
260 .removeFirstSegments(1);
261 outputLocation = outputLocation.makeRelative();
262 element.setAttribute("output", outputLocation.toString()); //$NON-NLS-1$
267 public static IClasspathEntry elementDecode(Element element,
268 IJavaProject project) {
270 IPath projectPath = project.getProject().getFullPath();
271 String kindAttr = element.getAttribute("kind"); //$NON-NLS-1$
272 String pathAttr = element.getAttribute("path"); //$NON-NLS-1$
274 // ensure path is absolute
275 IPath path = new Path(pathAttr);
276 int kind = kindFromString(kindAttr);
277 if (kind != IClasspathEntry.CPE_VARIABLE
278 && kind != IClasspathEntry.CPE_CONTAINER && !path.isAbsolute()) {
279 path = projectPath.append(path);
281 // source attachment info (optional)
282 // IPath sourceAttachmentPath = element.hasAttribute("sourcepath") //$NON-NLS-1$
283 // ? new Path(element.getAttribute("sourcepath")) //$NON-NLS-1$
285 // IPath sourceAttachmentRootPath = element.hasAttribute("rootpath") //$NON-NLS-1$
286 // ? new Path(element.getAttribute("rootpath")) //$NON-NLS-1$
289 // exported flag (optional)
290 boolean isExported = element.getAttribute("exported").equals("true"); //$NON-NLS-1$ //$NON-NLS-2$
292 // exclusion patterns (optional)
293 String exclusion = element.getAttribute("excluding"); //$NON-NLS-1$
294 IPath[] exclusionPatterns = ClasspathEntry.NO_EXCLUSION_PATTERNS;
295 if (!exclusion.equals("")) { //$NON-NLS-1$
296 char[][] patterns = CharOperation.splitOn('|', exclusion
299 if ((patternCount = patterns.length) > 0) {
300 exclusionPatterns = new IPath[patternCount];
301 for (int j = 0; j < patterns.length; j++) {
302 exclusionPatterns[j] = new Path(new String(patterns[j]));
307 // custom output location
308 IPath outputLocation = element.hasAttribute("output") ? projectPath.append(element.getAttribute("output")) : null; //$NON-NLS-1$ //$NON-NLS-2$
310 // recreate the CP entry
313 case IClasspathEntry.CPE_PROJECT:
314 return JavaCore.newProjectEntry(path, isExported);
316 // case IClasspathEntry.CPE_LIBRARY :
317 // return JavaCore.newLibraryEntry(
319 // sourceAttachmentPath,
320 // sourceAttachmentRootPath,
323 case IClasspathEntry.CPE_SOURCE:
324 // must be an entry in this project or specify another project
325 String projSegment = path.segment(0);
326 if (projSegment != null
327 && projSegment.equals(project.getElementName())) { // this
329 return JavaCore.newSourceEntry(path, exclusionPatterns,
331 } else { // another project
332 return JavaCore.newProjectEntry(path, isExported);
335 // case IClasspathEntry.CPE_VARIABLE :
336 // return PHPCore.newVariableEntry(
338 // sourceAttachmentPath,
339 // sourceAttachmentRootPath,
342 case IClasspathEntry.CPE_CONTAINER:
343 return JavaCore.newContainerEntry(path, isExported);
345 case ClasspathEntry.K_OUTPUT:
346 if (!path.isAbsolute())
348 return new ClasspathEntry(ClasspathEntry.K_OUTPUT,
349 IClasspathEntry.CPE_LIBRARY, path,
350 ClasspathEntry.INCLUDE_ALL, ClasspathEntry.EXCLUDE_NONE,
351 null, // source attachment
352 null, // source attachment root
353 null, // custom output location
357 throw new Assert.AssertionFailedException(Util.bind(
358 "classpath.unknownKind", kindAttr)); //$NON-NLS-1$
363 * Returns true if the given object is a classpath entry with equivalent
366 public boolean equals(Object object) {
369 if (object instanceof IClasspathEntry) {
370 IClasspathEntry otherEntry = (IClasspathEntry) object;
372 if (this.contentKind != otherEntry.getContentKind())
375 if (this.entryKind != otherEntry.getEntryKind())
378 if (this.isExported != otherEntry.isExported())
381 if (!this.path.equals(otherEntry.getPath()))
384 IPath otherPath = otherEntry.getSourceAttachmentPath();
385 if (this.sourceAttachmentPath == null) {
386 if (otherPath != null)
389 if (!this.sourceAttachmentPath.equals(otherPath))
393 otherPath = otherEntry.getSourceAttachmentRootPath();
394 if (this.sourceAttachmentRootPath == null) {
395 if (otherPath != null)
398 if (!this.sourceAttachmentRootPath.equals(otherPath))
402 IPath[] otherIncludes = otherEntry.getInclusionPatterns();
403 if (this.inclusionPatterns != otherIncludes) {
404 if (this.inclusionPatterns == null)
406 int includeLength = this.inclusionPatterns.length;
407 if (otherIncludes == null
408 || otherIncludes.length != includeLength)
410 for (int i = 0; i < includeLength; i++) {
411 // compare toStrings instead of IPaths
412 // since IPath.equals is specified to ignore trailing
414 if (!this.inclusionPatterns[i].toString().equals(
415 otherIncludes[i].toString()))
420 IPath[] otherExcludes = otherEntry.getExclusionPatterns();
421 if (this.exclusionPatterns != otherExcludes) {
422 int excludeLength = this.exclusionPatterns.length;
423 if (otherExcludes.length != excludeLength)
425 for (int i = 0; i < excludeLength; i++) {
426 // compare toStrings instead of IPaths
427 // since IPath.equals is specified to ignore trailing
429 if (!this.exclusionPatterns[i].toString().equals(
430 otherExcludes[i].toString()))
435 otherPath = otherEntry.getOutputLocation();
436 if (this.specificOutputLocation == null) {
437 if (otherPath != null)
440 if (!this.specificOutputLocation.equals(otherPath))
450 * @see IClasspathEntry
452 public int getContentKind() {
453 return this.contentKind;
457 * @see IClasspathEntry
459 public int getEntryKind() {
460 return this.entryKind;
464 * @see IClasspathEntry#getExclusionPatterns()
466 public IPath[] getExclusionPatterns() {
467 return this.exclusionPatterns;
471 * @see IClasspathEntry#getExclusionPatterns()
473 public IPath[] getInclusionPatterns() {
474 return this.inclusionPatterns;
478 * @see IClasspathEntry#getOutputLocation()
480 public IPath getOutputLocation() {
481 return this.specificOutputLocation;
485 * @see IClasspathEntry
487 public IPath getPath() {
492 * @see IClasspathEntry
494 public IPath getSourceAttachmentPath() {
495 return this.sourceAttachmentPath;
499 * @see IClasspathEntry
501 public IPath getSourceAttachmentRootPath() {
502 return this.sourceAttachmentRootPath;
506 * Returns the hash code for this classpath entry
508 public int hashCode() {
509 return this.path.hashCode();
513 * @see IClasspathEntry#isExported()
515 public boolean isExported() {
516 return this.isExported;
520 * Returns the kind of a <code>PackageFragmentRoot</code> from its
521 * <code>String</code> form.
523 static int kindFromString(String kindStr) {
525 if (kindStr.equalsIgnoreCase("prj")) //$NON-NLS-1$
526 return IClasspathEntry.CPE_PROJECT;
527 if (kindStr.equalsIgnoreCase("var")) //$NON-NLS-1$
528 return IClasspathEntry.CPE_VARIABLE;
529 if (kindStr.equalsIgnoreCase("con")) //$NON-NLS-1$
530 return IClasspathEntry.CPE_CONTAINER;
531 if (kindStr.equalsIgnoreCase("src")) //$NON-NLS-1$
532 return IClasspathEntry.CPE_SOURCE;
533 if (kindStr.equalsIgnoreCase("lib")) //$NON-NLS-1$
534 return IClasspathEntry.CPE_LIBRARY;
535 if (kindStr.equalsIgnoreCase("output")) //$NON-NLS-1$
536 return ClasspathEntry.K_OUTPUT;
541 * Returns a <code>String</code> for the kind of a class path entry.
543 static String kindToString(int kind) {
546 case IClasspathEntry.CPE_PROJECT:
547 return "src"; // backward compatibility //$NON-NLS-1$
548 case IClasspathEntry.CPE_SOURCE:
549 return "src"; //$NON-NLS-1$
550 case IClasspathEntry.CPE_LIBRARY:
551 return "lib"; //$NON-NLS-1$
552 case IClasspathEntry.CPE_VARIABLE:
553 return "var"; //$NON-NLS-1$
554 case IClasspathEntry.CPE_CONTAINER:
555 return "con"; //$NON-NLS-1$
556 case ClasspathEntry.K_OUTPUT:
557 return "output"; //$NON-NLS-1$
559 return "unknown"; //$NON-NLS-1$
564 * Returns a printable representation of this classpath entry.
566 public String toString() {
567 StringBuffer buffer = new StringBuffer();
568 buffer.append(getPath().toString());
570 switch (getEntryKind()) {
571 case IClasspathEntry.CPE_LIBRARY:
572 buffer.append("CPE_LIBRARY"); //$NON-NLS-1$
574 case IClasspathEntry.CPE_PROJECT:
575 buffer.append("CPE_PROJECT"); //$NON-NLS-1$
577 case IClasspathEntry.CPE_SOURCE:
578 buffer.append("CPE_SOURCE"); //$NON-NLS-1$
580 case IClasspathEntry.CPE_VARIABLE:
581 buffer.append("CPE_VARIABLE"); //$NON-NLS-1$
583 case IClasspathEntry.CPE_CONTAINER:
584 buffer.append("CPE_CONTAINER"); //$NON-NLS-1$
587 buffer.append("]["); //$NON-NLS-1$
588 switch (getContentKind()) {
589 case IPackageFragmentRoot.K_BINARY:
590 buffer.append("K_BINARY"); //$NON-NLS-1$
592 case IPackageFragmentRoot.K_SOURCE:
593 buffer.append("K_SOURCE"); //$NON-NLS-1$
595 case ClasspathEntry.K_OUTPUT:
596 buffer.append("K_OUTPUT"); //$NON-NLS-1$
600 if (getSourceAttachmentPath() != null) {
601 buffer.append("[sourcePath:"); //$NON-NLS-1$
602 buffer.append(getSourceAttachmentPath());
605 if (getSourceAttachmentRootPath() != null) {
606 buffer.append("[rootPath:"); //$NON-NLS-1$
607 buffer.append(getSourceAttachmentRootPath());
610 buffer.append("[isExported:"); //$NON-NLS-1$
611 buffer.append(this.isExported);
613 IPath[] patterns = getExclusionPatterns();
615 if ((length = patterns.length) > 0) {
616 buffer.append("[excluding:"); //$NON-NLS-1$
617 for (int i = 0; i < length; i++) {
618 buffer.append(patterns[i]);
619 if (i != length - 1) {
625 if (getOutputLocation() != null) {
626 buffer.append("[output:"); //$NON-NLS-1$
627 buffer.append(getOutputLocation());
630 return buffer.toString();
634 * Answers an ID which is used to distinguish entries during package
635 * fragment root computations
637 public String rootID() {
639 if (this.rootID == null) {
640 switch (this.entryKind) {
641 case IClasspathEntry.CPE_LIBRARY:
642 this.rootID = "[LIB]" + this.path; //$NON-NLS-1$
644 case IClasspathEntry.CPE_PROJECT:
645 this.rootID = "[PRJ]" + this.path; //$NON-NLS-1$
647 case IClasspathEntry.CPE_SOURCE:
648 this.rootID = "[SRC]" + this.path; //$NON-NLS-1$
650 case IClasspathEntry.CPE_VARIABLE:
651 this.rootID = "[VAR]" + this.path; //$NON-NLS-1$
653 case IClasspathEntry.CPE_CONTAINER:
654 this.rootID = "[CON]" + this.path; //$NON-NLS-1$
657 this.rootID = ""; //$NON-NLS-1$
665 * @see IClasspathEntry
668 public IClasspathEntry getResolvedEntry() {
670 return JavaCore.getResolvedClasspathEntry(this);
674 * Returns the XML encoding of the class path.
676 public void elementEncode(XMLWriter writer, IPath projectPath,
677 boolean indent, boolean newLine) {
678 HashMap parameters = new HashMap();
680 parameters.put("kind", ClasspathEntry.kindToString(this.entryKind));//$NON-NLS-1$
682 IPath xmlPath = this.path;
683 if (this.entryKind != IClasspathEntry.CPE_VARIABLE
684 && this.entryKind != IClasspathEntry.CPE_CONTAINER) {
685 // translate to project relative from absolute (unless a device
687 if (xmlPath.isAbsolute()) {
688 if (projectPath != null && projectPath.isPrefixOf(xmlPath)) {
689 if (xmlPath.segment(0).equals(projectPath.segment(0))) {
690 xmlPath = xmlPath.removeFirstSegments(1);
691 xmlPath = xmlPath.makeRelative();
693 xmlPath = xmlPath.makeAbsolute();
698 parameters.put("path", String.valueOf(xmlPath));//$NON-NLS-1$
700 if (this.sourceAttachmentPath != null) {
701 xmlPath = this.sourceAttachmentPath;
702 // translate to project relative from absolute
703 if (this.entryKind != IClasspathEntry.CPE_VARIABLE
704 && projectPath != null && projectPath.isPrefixOf(xmlPath)) {
705 if (xmlPath.segment(0).equals(projectPath.segment(0))) {
706 xmlPath = xmlPath.removeFirstSegments(1);
707 xmlPath = xmlPath.makeRelative();
710 parameters.put("sourcepath", String.valueOf(xmlPath));//$NON-NLS-1$
712 if (this.sourceAttachmentRootPath != null) {
714 "rootpath", String.valueOf(this.sourceAttachmentRootPath));//$NON-NLS-1$
716 if (this.isExported) {
717 parameters.put("exported", "true");//$NON-NLS-1$//$NON-NLS-2$
719 // if (this.inclusionPatterns != null && this.inclusionPatterns.length >
721 // StringBuffer includeRule = new StringBuffer(10);
722 // for (int i = 0, max = this.inclusionPatterns.length; i < max; i++){
723 // if (i > 0) includeRule.append('|');
724 // includeRule.append(this.inclusionPatterns[i]);
726 // parameters.put("including",
727 // String.valueOf(includeRule));//$NON-NLS-1$
729 if (this.exclusionPatterns != null && this.exclusionPatterns.length > 0) {
730 StringBuffer excludeRule = new StringBuffer(10);
731 for (int i = 0, max = this.exclusionPatterns.length; i < max; i++) {
733 excludeRule.append('|');
734 excludeRule.append(this.exclusionPatterns[i]);
736 parameters.put("excluding", String.valueOf(excludeRule));//$NON-NLS-1$
739 if (this.specificOutputLocation != null) {
740 IPath outputLocation = this.specificOutputLocation
741 .removeFirstSegments(1);
742 outputLocation = outputLocation.makeRelative();
743 parameters.put("output", String.valueOf(outputLocation));//$NON-NLS-1$
746 writer.printTag("classpathentry", parameters, indent, newLine, true);//$NON-NLS-1$
750 * Validate a given classpath and output location for a project, using the
753 * <li> Classpath entries cannot collide with each other; that is, all entry
754 * paths must be unique.
755 * <li> The project output location path cannot be null, must be absolute
756 * and located inside the project.
757 * <li> Specific output locations (specified on source entries) can be null,
758 * if not they must be located inside the project,
759 * <li> A project entry cannot refer to itself directly (that is, a project
760 * cannot prerequisite itself).
761 * <li> Classpath entries or output locations cannot coincidate or be nested
762 * in each other, except for the following scenarii listed below:
764 * <li> A source folder can coincidate with its own output location, in
765 * which case this output can then contain library archives. However, a
766 * specific output location cannot coincidate with any library or a distinct
767 * source folder than the one referring to it. </li>
768 * <li> A source/library folder can be nested in any source folder as long
769 * as the nested folder is excluded from the enclosing one. </li>
770 * <li> An output location can be nested in a source folder, if the source
771 * folder coincidates with the project itself, or if the output location is
772 * excluded from the source folder. </li>
776 * Note that the classpath entries are not validated automatically. Only
777 * bound variables or containers are considered in the checking process
778 * (this allows to perform a consistency check on a classpath which has
779 * references to yet non existing projects, folders, ...).
781 * This validation is intended to anticipate classpath issues prior to
782 * assigning it to a project. In particular, it will automatically be
783 * performed during the classpath setting operation (if validation fails,
784 * the classpath setting will not complete).
788 * the given java project
789 * @param rawClasspath
791 * @param projectOutputLocation
792 * a given output location
793 * @return a status object with code <code>IStatus.OK</code> if the given
794 * classpath and output location are compatible, otherwise a status
795 * object indicating what is wrong with the classpath or output
798 public static IJavaModelStatus validateClasspath(IJavaProject javaProject,
799 IClasspathEntry[] rawClasspath, IPath projectOutputLocation) {
801 IProject project = javaProject.getProject();
802 IPath projectPath = project.getFullPath();
803 String projectName = javaProject.getElementName();
805 /* validate output location */
806 if (projectOutputLocation == null) {
807 return new JavaModelStatus(IJavaModelStatusConstants.NULL_PATH);
809 if (projectOutputLocation.isAbsolute()) {
810 if (!projectPath.isPrefixOf(projectOutputLocation)) {
811 return new JavaModelStatus(
812 IJavaModelStatusConstants.PATH_OUTSIDE_PROJECT,
813 javaProject, projectOutputLocation.toString());
816 return new JavaModelStatus(IJavaModelStatusConstants.RELATIVE_PATH,
817 projectOutputLocation);
820 boolean hasSource = false;
821 boolean hasLibFolder = false;
823 // tolerate null path, it will be reset to default
824 if (rawClasspath == null)
825 return JavaModelStatus.VERIFIED_OK;
827 // retrieve resolved classpath
828 IClasspathEntry[] classpath;
830 classpath = ((JavaProject) javaProject).getResolvedClasspath(
831 rawClasspath, null /* output */, true/* ignore pb */,
832 false/* no marker */, null /* no reverse map */);
833 } catch (JavaModelException e) {
834 return e.getJavaModelStatus();
836 int length = classpath.length;
839 IPath[] outputLocations = new IPath[length + 1];
840 boolean[] allowNestingInOutputLocations = new boolean[length + 1];
841 outputLocations[0] = projectOutputLocation;
843 // retrieve and check output locations
844 IPath potentialNestedOutput = null; // for error reporting purpose
845 int sourceEntryCount = 0;
846 boolean disableExclusionPatterns = JavaCore.DISABLED.equals(javaProject
847 .getOption(JavaCore.CORE_ENABLE_CLASSPATH_EXCLUSION_PATTERNS,
849 boolean disableCustomOutputLocations = JavaCore.DISABLED
852 JavaCore.CORE_ENABLE_CLASSPATH_MULTIPLE_OUTPUT_LOCATIONS,
855 for (int i = 0; i < length; i++) {
856 IClasspathEntry resolvedEntry = classpath[i];
857 switch (resolvedEntry.getEntryKind()) {
858 case IClasspathEntry.CPE_SOURCE:
861 if (disableExclusionPatterns
862 && ((resolvedEntry.getInclusionPatterns() != null && resolvedEntry
863 .getInclusionPatterns().length > 0) || (resolvedEntry
864 .getExclusionPatterns() != null && resolvedEntry
865 .getExclusionPatterns().length > 0))) {
866 return new JavaModelStatus(
867 IJavaModelStatusConstants.DISABLED_CP_EXCLUSION_PATTERNS,
868 javaProject, resolvedEntry.getPath());
871 if ((customOutput = resolvedEntry.getOutputLocation()) != null) {
873 if (disableCustomOutputLocations) {
874 return new JavaModelStatus(
875 IJavaModelStatusConstants.DISABLED_CP_MULTIPLE_OUTPUT_LOCATIONS,
876 javaProject, resolvedEntry.getPath());
878 // ensure custom output is in project
879 if (customOutput.isAbsolute()) {
880 if (!javaProject.getPath().isPrefixOf(customOutput)) {
881 return new JavaModelStatus(
882 IJavaModelStatusConstants.PATH_OUTSIDE_PROJECT,
883 javaProject, customOutput.toString());
886 return new JavaModelStatus(
887 IJavaModelStatusConstants.RELATIVE_PATH,
891 // ensure custom output doesn't conflict with other outputs
893 if (Util.indexOfMatchingPath(customOutput, outputLocations,
894 outputCount) != -1) {
895 continue; // already found
897 // accumulate all outputs, will check nesting once all
898 // available (to handle ordering issues)
899 outputLocations[outputCount++] = customOutput;
903 // check nesting across output locations
904 for (int i = 1 /* no check for default output */; i < outputCount; i++) {
905 IPath customOutput = outputLocations[i];
908 if ((index = Util.indexOfEnclosingPath(customOutput,
909 outputLocations, outputCount)) != -1
912 // custom output is nested in project's output: need to
913 // check if all source entries have a custom
914 // output before complaining
915 if (potentialNestedOutput == null)
916 potentialNestedOutput = customOutput;
918 return new JavaModelStatus(
919 IJavaModelStatusConstants.INVALID_CLASSPATH,
922 "classpath.cannotNestOutputInOutput", customOutput.makeRelative().toString(), outputLocations[index].makeRelative().toString())); //$NON-NLS-1$
926 // allow custom output nesting in project's output if all source entries
927 // have a custom output
928 if (sourceEntryCount <= outputCount - 1) {
929 allowNestingInOutputLocations[0] = true;
930 } else if (potentialNestedOutput != null) {
931 return new JavaModelStatus(
932 IJavaModelStatusConstants.INVALID_CLASSPATH,
935 "classpath.cannotNestOutputInOutput", potentialNestedOutput.makeRelative().toString(), outputLocations[0].makeRelative().toString())); //$NON-NLS-1$
938 for (int i = 0; i < length; i++) {
939 IClasspathEntry resolvedEntry = classpath[i];
940 IPath path = resolvedEntry.getPath();
942 switch (resolvedEntry.getEntryKind()) {
944 case IClasspathEntry.CPE_SOURCE:
946 if ((index = Util.indexOfMatchingPath(path, outputLocations,
947 outputCount)) != -1) {
948 allowNestingInOutputLocations[index] = true;
952 // case IClasspathEntry.CPE_LIBRARY:
954 // !org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(path.lastSegment());
955 // if ((index = Util.indexOfMatchingPath(path, outputLocations,
956 // outputCount)) != -1){
957 // allowNestingInOutputLocations[index] = true;
962 if (!hasSource && !hasLibFolder) { // if no source and no lib folder,
964 for (int i = 0; i < outputCount; i++)
965 allowNestingInOutputLocations[i] = true;
968 HashSet pathes = new HashSet(length);
971 for (int i = 0; i < length; i++) {
972 IClasspathEntry entry = classpath[i];
975 IPath entryPath = entry.getPath();
976 int kind = entry.getEntryKind();
978 // Build some common strings for status message
979 boolean isProjectRelative = entryPath.segment(0).toString().equals(
981 String entryPathMsg = isProjectRelative ? entryPath
982 .removeFirstSegments(1).toString() : entryPath
983 .makeRelative().toString();
985 // complain if duplicate path
986 if (!pathes.add(entryPath)) {
987 return new JavaModelStatus(
988 IJavaModelStatusConstants.NAME_COLLISION,
991 "classpath.duplicateEntryPath", entryPathMsg, projectName)); //$NON-NLS-1$
993 // no further check if entry coincidates with project or output
995 if (entryPath.equals(projectPath)) {
996 // complain if self-referring project entry
997 if (kind == IClasspathEntry.CPE_PROJECT) {
998 return new JavaModelStatus(
999 IJavaModelStatusConstants.INVALID_PATH,
1002 "classpath.cannotReferToItself", entryPath.makeRelative().toString()));//$NON-NLS-1$
1004 // tolerate nesting output in src if src==prj
1008 // allow nesting source entries in each other as long as the outer
1009 // entry excludes the inner one
1010 if (kind == IClasspathEntry.CPE_SOURCE) {
1011 // || (kind == IClasspathEntry.CPE_LIBRARY &&
1012 // !org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(entryPath.lastSegment()))){
1013 for (int j = 0; j < classpath.length; j++) {
1014 IClasspathEntry otherEntry = classpath[j];
1015 if (otherEntry == null)
1017 int otherKind = otherEntry.getEntryKind();
1018 IPath otherPath = otherEntry.getPath();
1019 if (entry != otherEntry
1020 && (otherKind == IClasspathEntry.CPE_SOURCE)) {
1021 // || (otherKind == IClasspathEntry.CPE_LIBRARY
1023 // !org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(otherPath.lastSegment())))){
1024 char[][] inclusionPatterns, exclusionPatterns;
1025 if (otherPath.isPrefixOf(entryPath)
1026 && !otherPath.equals(entryPath)
1029 entryPath.append("*"), inclusionPatterns = ((ClasspathEntry) otherEntry).fullInclusionPatternChars(), exclusionPatterns = ((ClasspathEntry) otherEntry).fullExclusionPatternChars(), false)) { //$NON-NLS-1$
1030 String exclusionPattern = entryPath
1031 .removeFirstSegments(
1032 otherPath.segmentCount())
1034 if (Util.isExcluded(entryPath, inclusionPatterns,
1035 exclusionPatterns, false)) {
1036 return new JavaModelStatus(
1037 IJavaModelStatusConstants.INVALID_CLASSPATH,
1040 "classpath.mustEndWithSlash", exclusionPattern, entryPath.makeRelative().toString())); //$NON-NLS-1$
1042 if (otherKind == IClasspathEntry.CPE_SOURCE) {
1043 exclusionPattern += '/';
1044 return new JavaModelStatus(
1045 IJavaModelStatusConstants.INVALID_CLASSPATH,
1048 "classpath.cannotNestEntryInEntry", new String[] { entryPath.makeRelative().toString(), otherEntry.getPath().makeRelative().toString(), exclusionPattern })); //$NON-NLS-1$
1050 return new JavaModelStatus(
1051 IJavaModelStatusConstants.INVALID_CLASSPATH,
1054 "classpath.cannotNestEntryInLibrary", entryPath.makeRelative().toString(), otherEntry.getPath().makeRelative().toString())); //$NON-NLS-1$
1062 // prevent nesting output location inside entry unless enclosing is
1063 // a source entry which explicitly exclude the output location
1064 char[][] inclusionPatterns = ((ClasspathEntry) entry)
1065 .fullInclusionPatternChars();
1066 char[][] exclusionPatterns = ((ClasspathEntry) entry)
1067 .fullExclusionPatternChars();
1068 for (int j = 0; j < outputCount; j++) {
1069 IPath currentOutput = outputLocations[j];
1070 if (entryPath.equals(currentOutput))
1072 if (entryPath.isPrefixOf(currentOutput)) {
1073 if (kind != IClasspathEntry.CPE_SOURCE
1074 || !Util.isExcluded(currentOutput,
1075 inclusionPatterns, exclusionPatterns, true)) {
1076 return new JavaModelStatus(
1077 IJavaModelStatusConstants.INVALID_CLASSPATH,
1080 "classpath.cannotNestOutputInEntry", currentOutput.makeRelative().toString(), entryPath.makeRelative().toString())); //$NON-NLS-1$
1085 // prevent nesting entry inside output location - when distinct from
1086 // project or a source folder
1087 for (int j = 0; j < outputCount; j++) {
1088 if (allowNestingInOutputLocations[j])
1090 IPath currentOutput = outputLocations[j];
1091 if (currentOutput.isPrefixOf(entryPath)) {
1092 return new JavaModelStatus(
1093 IJavaModelStatusConstants.INVALID_CLASSPATH,
1096 "classpath.cannotNestEntryInOutput", entryPath.makeRelative().toString(), currentOutput.makeRelative().toString())); //$NON-NLS-1$
1100 // ensure that no specific output is coincidating with another source
1101 // folder (only allowed if matching current source folder)
1102 // 36465 - for 2.0 backward compatibility, only check specific output
1103 // locations (the default can still coincidate)
1104 // perform one separate iteration so as to not take precedence over
1105 // previously checked scenarii (in particular should
1106 // diagnose nesting source folder issue before this one, for example,
1107 // [src]"Project/", [src]"Project/source/" and output="Project/" should
1108 // first complain about missing exclusion pattern
1109 for (int i = 0; i < length; i++) {
1110 IClasspathEntry entry = classpath[i];
1113 IPath entryPath = entry.getPath();
1114 int kind = entry.getEntryKind();
1116 // Build some common strings for status message
1117 boolean isProjectRelative = entryPath.segment(0).toString().equals(
1119 String entryPathMsg = isProjectRelative ? entryPath
1120 .removeFirstSegments(1).toString() : entryPath
1121 .makeRelative().toString();
1123 if (kind == IClasspathEntry.CPE_SOURCE) {
1124 IPath output = entry.getOutputLocation();
1126 continue; // 36465 - for 2.0 backward compatibility, only
1127 // check specific output locations (the default
1128 // can still coincidate)
1129 // if (output == null) output = projectOutputLocation; // if no
1130 // specific output, still need to check using default output
1131 // (this line would check default output)
1132 for (int j = 0; j < length; j++) {
1133 IClasspathEntry otherEntry = classpath[j];
1134 if (otherEntry == entry)
1137 // Build some common strings for status message
1138 boolean opStartsWithProject = otherEntry.getPath().segment(
1139 0).toString().equals(projectName);
1140 String otherPathMsg = opStartsWithProject ? otherEntry
1141 .getPath().removeFirstSegments(1).toString()
1142 : otherEntry.getPath().makeRelative().toString();
1144 switch (otherEntry.getEntryKind()) {
1145 case IClasspathEntry.CPE_SOURCE:
1146 if (otherEntry.getPath().equals(output)) {
1147 return new JavaModelStatus(
1148 IJavaModelStatusConstants.INVALID_CLASSPATH,
1151 "classpath.cannotUseDistinctSourceFolderAsOutput", new String[] { entryPathMsg, otherPathMsg, projectName })); //$NON-NLS-1$
1154 case IClasspathEntry.CPE_LIBRARY:
1155 if (otherEntry.getPath().equals(output)) {
1156 return new JavaModelStatus(
1157 IJavaModelStatusConstants.INVALID_CLASSPATH,
1160 "classpath.cannotUseLibraryAsOutput", new String[] { entryPathMsg, otherPathMsg, projectName })); //$NON-NLS-1$
1166 return JavaModelStatus.VERIFIED_OK;
1170 * Returns a Java model status describing the problem related to this
1171 * classpath entry if any, a status object with code <code>IStatus.OK</code>
1172 * if the entry is fine (that is, if the given classpath entry denotes a
1173 * valid element to be referenced onto a classpath).
1176 * the given java project
1178 * the given classpath entry
1179 * @param checkSourceAttachment
1180 * a flag to determine if source attachement should be checked
1181 * @param recurseInContainers
1182 * flag indicating whether validation should be applied to
1183 * container entries recursively
1184 * @return a java model status describing the problem related to this
1185 * classpath entry if any, a status object with code
1186 * <code>IStatus.OK</code> if the entry is fine
1188 public static IJavaModelStatus validateClasspathEntry(IJavaProject project,
1189 IClasspathEntry entry, boolean checkSourceAttachment,
1190 boolean recurseInContainers) {
1192 IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
1193 IPath path = entry.getPath();
1195 // Build some common strings for status message
1196 String projectName = project.getElementName();
1197 boolean pathStartsWithProject = path.segment(0).toString().equals(
1199 String entryPathMsg = pathStartsWithProject ? path.removeFirstSegments(
1200 1).toString() : path.makeRelative().toString();
1202 switch (entry.getEntryKind()) {
1204 // container entry check
1205 // case IClasspathEntry.CPE_CONTAINER :
1206 // if (path != null && path.segmentCount() >= 1){
1208 // IClasspathContainer container =
1209 // JavaModelManager.getJavaModelManager().getClasspathContainer(path,
1211 // // container retrieval is performing validation check on container
1213 // if (container == null){
1215 // JavaModelStatus(IJavaModelStatusConstants.CP_CONTAINER_PATH_UNBOUND,
1217 // } else if (container ==
1218 // JavaModelManager.CONTAINER_INITIALIZATION_IN_PROGRESS) {
1219 // // don't create a marker if initialization is in progress (case of cp
1220 // initialization batching)
1221 // return JavaModelStatus.VERIFIED_OK;
1223 // IClasspathEntry[] containerEntries = container.getClasspathEntries();
1224 // if (containerEntries != null){
1225 // for (int i = 0, length = containerEntries.length; i < length; i++){
1226 // IClasspathEntry containerEntry = containerEntries[i];
1227 // int kind = containerEntry == null ? 0 :
1228 // containerEntry.getEntryKind();
1229 // if (containerEntry == null
1230 // || kind == IClasspathEntry.CPE_SOURCE
1231 // || kind == IClasspathEntry.CPE_VARIABLE
1232 // || kind == IClasspathEntry.CPE_CONTAINER){
1233 // String description = container.getDescription();
1234 // if (description == null) description =
1235 // path.makeRelative().toString();
1237 // JavaModelStatus(IJavaModelStatusConstants.INVALID_CP_CONTAINER_ENTRY,
1240 // if (recurseInContainers) {
1241 // IJavaModelStatus containerEntryStatus =
1242 // validateClasspathEntry(project, containerEntry,
1243 // checkSourceAttachment, recurseInContainers);
1244 // if (!containerEntryStatus.isOK()){
1245 // return containerEntryStatus;
1250 // } catch(JavaModelException e){
1251 // return new JavaModelStatus(e);
1255 // JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH,
1256 // Util.bind("classpath.illegalContainerPath", entryPathMsg,
1257 // projectName)); //$NON-NLS-1$
1261 // variable entry check
1262 case IClasspathEntry.CPE_VARIABLE:
1263 if (path != null && path.segmentCount() >= 1) {
1265 entry = JavaCore.getResolvedClasspathEntry(entry);
1266 } catch (Assert.AssertionFailedException e) {
1267 // Catch the assertion failure and throw java model
1268 // exception instead
1270 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=55992
1271 return new JavaModelStatus(
1272 IJavaModelStatusConstants.INVALID_PATH, e
1275 if (entry == null) {
1276 return new JavaModelStatus(
1277 IJavaModelStatusConstants.CP_VARIABLE_PATH_UNBOUND,
1280 return validateClasspathEntry(project, entry,
1281 checkSourceAttachment, recurseInContainers);
1283 return new JavaModelStatus(
1284 IJavaModelStatusConstants.INVALID_CLASSPATH,
1287 "classpath.illegalVariablePath", path.makeRelative().toString(), projectName)); //$NON-NLS-1$
1290 // library entry check
1291 // case IClasspathEntry.CPE_LIBRARY :
1292 // if (path != null && path.isAbsolute() && !path.isEmpty()) {
1293 // IPath sourceAttachment = entry.getSourceAttachmentPath();
1294 // Object target = JavaModel.getTarget(workspaceRoot, path, true);
1295 // if (target != null &&
1296 // project.getOption(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL, true) !=
1297 // JavaCore.IGNORE) {
1298 // long projectTargetJDK =
1299 // CompilerOptions.versionToJdkLevel(project.getOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM,
1301 // long libraryJDK = Util.getJdkLevel(target);
1302 // if (libraryJDK != 0 && libraryJDK > projectTargetJDK) {
1304 // JavaModelStatus(IJavaModelStatusConstants.INCOMPATIBLE_JDK_LEVEL,
1305 // project, path, CompilerOptions.versionFromJdkLevel(libraryJDK));
1308 // if (target instanceof IResource){
1309 // IResource resolvedResource = (IResource) target;
1310 // switch(resolvedResource.getType()){
1311 // case IResource.FILE :
1313 // (org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(resolvedResource.getName()))
1315 // if (checkSourceAttachment
1316 // && sourceAttachment != null
1317 // && !sourceAttachment.isEmpty()
1318 // && JavaModel.getTarget(workspaceRoot, sourceAttachment, true) ==
1321 // JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH,
1322 // Util.bind("classpath.unboundSourceAttachment", new String []
1323 // {sourceAttachment.makeRelative().toString(),
1324 // path.makeRelative().toString(), projectName})); //$NON-NLS-1$
1328 // JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH,
1329 // Util.bind("classpath.illegalLibraryArchive", entryPathMsg,
1330 // projectName)); //$NON-NLS-1$
1333 // case IResource.FOLDER : // internal binary folder
1334 // if (checkSourceAttachment
1335 // && sourceAttachment != null
1336 // && !sourceAttachment.isEmpty()
1337 // && JavaModel.getTarget(workspaceRoot, sourceAttachment, true) ==
1340 // JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH,
1341 // Util.bind("classpath.unboundSourceAttachment", new String []
1342 // {sourceAttachment.makeRelative().toString(),
1343 // path.makeRelative().toString(), projectName})); //$NON-NLS-1$
1346 // } else if (target instanceof File){
1347 // File file = (File) target;
1348 // if (!file.isFile()) {
1350 // JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH,
1351 // Util.bind("classpath.illegalExternalFolder", path.toOSString(),
1352 // projectName)); //$NON-NLS-1$
1354 // (!org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(file.getName()))
1357 // JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH,
1358 // Util.bind("classpath.illegalLibraryArchive", path.toOSString(),
1359 // projectName)); //$NON-NLS-1$
1360 // } else if (checkSourceAttachment
1361 // && sourceAttachment != null
1362 // && !sourceAttachment.isEmpty()
1363 // && JavaModel.getTarget(workspaceRoot, sourceAttachment, true) ==
1366 // JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH,
1367 // Util.bind("classpath.unboundSourceAttachment", new String []
1368 // {sourceAttachment.toString(), path.makeRelative().toString(),
1369 // projectName})); //$NON-NLS-1$
1373 // JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH,
1374 // Util.bind("classpath.unboundLibrary",
1375 // path.makeRelative().toString(), projectName)); //$NON-NLS-1$
1379 // JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH,
1380 // Util.bind("classpath.illegalLibraryPath",
1381 // path.makeRelative().toString(), projectName)); //$NON-NLS-1$
1385 // project entry check
1386 case IClasspathEntry.CPE_PROJECT:
1387 if (path != null && path.isAbsolute() && !path.isEmpty()) {
1388 IProject prereqProjectRsc = workspaceRoot.getProject(path
1390 //IJavaProject prereqProject = JavaCore.create(prereqProjectRsc);
1392 if (!prereqProjectRsc.exists()
1393 || !prereqProjectRsc
1394 .hasNature(PHPeclipsePlugin.PHP_NATURE_ID)) {
1395 return new JavaModelStatus(
1396 IJavaModelStatusConstants.INVALID_CLASSPATH,
1399 "classpath.unboundProject", path.makeRelative().segment(0).toString(), projectName)); //$NON-NLS-1$
1401 if (!prereqProjectRsc.isOpen()) {
1402 return new JavaModelStatus(
1403 IJavaModelStatusConstants.INVALID_CLASSPATH,
1406 "classpath.closedProject", path.segment(0).toString())); //$NON-NLS-1$
1409 // (project.getOption(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL,
1410 // true) != JavaCore.IGNORE) {
1411 // long projectTargetJDK =
1412 // CompilerOptions.versionToJdkLevel(project.getOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM,
1414 // long prereqProjectTargetJDK =
1415 // CompilerOptions.versionToJdkLevel(prereqProject.getOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM,
1417 // if (prereqProjectTargetJDK > projectTargetJDK) {
1419 // JavaModelStatus(IJavaModelStatusConstants.INCOMPATIBLE_JDK_LEVEL,
1421 // CompilerOptions.versionFromJdkLevel(prereqProjectTargetJDK));
1424 } catch (CoreException e) {
1425 return new JavaModelStatus(
1426 IJavaModelStatusConstants.INVALID_CLASSPATH,
1429 "classpath.unboundProject", path.segment(0).toString(), projectName)); //$NON-NLS-1$
1432 return new JavaModelStatus(
1433 IJavaModelStatusConstants.INVALID_CLASSPATH,
1436 "classpath.illegalProjectPath", path.segment(0).toString(), projectName)); //$NON-NLS-1$
1440 // project source folder
1441 case IClasspathEntry.CPE_SOURCE:
1442 if (((entry.getInclusionPatterns() != null && entry
1443 .getInclusionPatterns().length > 0) || (entry
1444 .getExclusionPatterns() != null && entry
1445 .getExclusionPatterns().length > 0))
1446 && JavaCore.DISABLED.equals(project.getOption(
1447 JavaCore.CORE_ENABLE_CLASSPATH_EXCLUSION_PATTERNS,
1449 return new JavaModelStatus(
1450 IJavaModelStatusConstants.DISABLED_CP_EXCLUSION_PATTERNS,
1453 if (entry.getOutputLocation() != null
1454 && JavaCore.DISABLED
1457 JavaCore.CORE_ENABLE_CLASSPATH_MULTIPLE_OUTPUT_LOCATIONS,
1459 return new JavaModelStatus(
1460 IJavaModelStatusConstants.DISABLED_CP_MULTIPLE_OUTPUT_LOCATIONS,
1463 if (path != null && path.isAbsolute() && !path.isEmpty()) {
1464 IPath projectPath = project.getProject().getFullPath();
1465 if (!projectPath.isPrefixOf(path)
1466 || JavaModel.getTarget(workspaceRoot, path, true) == null) {
1467 return new JavaModelStatus(
1468 IJavaModelStatusConstants.INVALID_CLASSPATH,
1471 "classpath.unboundSourceFolder", entryPathMsg, projectName)); //$NON-NLS-1$
1474 return new JavaModelStatus(
1475 IJavaModelStatusConstants.INVALID_CLASSPATH,
1478 "classpath.illegalSourceFolderPath", entryPathMsg, projectName)); //$NON-NLS-1$
1482 return JavaModelStatus.VERIFIED_OK;