View | Details | Raw Unified | Return to bug 57732
Collapse All | Expand All

(-)model/org/eclipse/jdt/internal/core/JavaProject.java (-23 / +8 lines)
Lines 267-290 Link Here
267
		if (externalPath == null)
267
		if (externalPath == null)
268
			return null;
268
			return null;
269
269
270
//		if (JavaModelManager.VERBOSE) {
271
//			System.out.println("JAVA MODEL - Canonicalizing " + externalPath.toString());
272
//		}
273
274
		if (IS_CASE_SENSITIVE) {
270
		if (IS_CASE_SENSITIVE) {
275
//			if (JavaModelManager.VERBOSE) {
276
//				System.out.println("JAVA MODEL - Canonical path is original path (file system is case sensitive)");
277
//			}
278
			return externalPath;
271
			return externalPath;
279
		}
272
		}
280
273
		
281
		// if not external path, return original path
274
		// if not external path, return original path
282
		IWorkspace workspace = ResourcesPlugin.getWorkspace();
275
		IWorkspace workspace = ResourcesPlugin.getWorkspace();
283
		if (workspace == null) return externalPath; // protection during shutdown (30487)
276
		if (workspace == null) return externalPath; // protection during shutdown (30487)
284
		if (workspace.getRoot().findMember(externalPath) != null) {
277
		if (workspace.getRoot().findMember(externalPath) != null) {
285
//			if (JavaModelManager.VERBOSE) {
286
//				System.out.println("JAVA MODEL - Canonical path is original path (member of workspace)");
287
//			}
288
			return externalPath;
278
			return externalPath;
289
		}
279
		}
290
280
Lines 294-302 Link Here
294
				new Path(new File(externalPath.toOSString()).getCanonicalPath());
284
				new Path(new File(externalPath.toOSString()).getCanonicalPath());
295
		} catch (IOException e) {
285
		} catch (IOException e) {
296
			// default to original path
286
			// default to original path
297
//			if (JavaModelManager.VERBOSE) {
298
//				System.out.println("JAVA MODEL - Canonical path is original path (IOException)");
299
//			}
300
			return externalPath;
287
			return externalPath;
301
		}
288
		}
302
289
Lines 304-312 Link Here
304
		int canonicalLength = canonicalPath.segmentCount();
291
		int canonicalLength = canonicalPath.segmentCount();
305
		if (canonicalLength == 0) {
292
		if (canonicalLength == 0) {
306
			// the java.io.File canonicalization failed
293
			// the java.io.File canonicalization failed
307
//			if (JavaModelManager.VERBOSE) {
308
//				System.out.println("JAVA MODEL - Canonical path is original path (canonical path is empty)");
309
//			}
310
			return externalPath;
294
			return externalPath;
311
		} else if (externalPath.isAbsolute()) {
295
		} else if (externalPath.isAbsolute()) {
312
			result = canonicalPath;
296
			result = canonicalPath;
Lines 317-325 Link Here
317
			if (canonicalLength >= externalLength) {
301
			if (canonicalLength >= externalLength) {
318
				result = canonicalPath.removeFirstSegments(canonicalLength - externalLength);
302
				result = canonicalPath.removeFirstSegments(canonicalLength - externalLength);
319
			} else {
303
			} else {
320
//				if (JavaModelManager.VERBOSE) {
321
//					System.out.println("JAVA MODEL - Canonical path is original path (canonical path is " + canonicalPath.toString() + ")");
322
//				}
323
				return externalPath;
304
				return externalPath;
324
			}
305
			}
325
		}
306
		}
Lines 332-340 Link Here
332
		if (externalPath.hasTrailingSeparator()) {
313
		if (externalPath.hasTrailingSeparator()) {
333
			result = result.addTrailingSeparator();
314
			result = result.addTrailingSeparator();
334
		}
315
		}
335
//		if (JavaModelManager.VERBOSE) {
336
//			System.out.println("JAVA MODEL - Canonical path is " + result.toString());
337
//		}
338
		return result;
316
		return result;
339
	}
317
	}
340
318
Lines 2569-2574 Link Here
2569
						}
2547
						}
2570
						// if container is exported or restricted, then its nested entries must in turn be exported  (21749) and/or propagate restrictions
2548
						// if container is exported or restricted, then its nested entries must in turn be exported  (21749) and/or propagate restrictions
2571
						cEntry = cEntry.combineWith((ClasspathEntry) rawEntry);
2549
						cEntry = cEntry.combineWith((ClasspathEntry) rawEntry);
2550
						// resolve ".." in library path
2551
						if (cEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
2552
							cEntry = cEntry.resolvedDotDot();
2553
						}
2572
						if (result.rawReverseMap.get(resolvedPath = cEntry.getPath()) == null) {
2554
						if (result.rawReverseMap.get(resolvedPath = cEntry.getPath()) == null) {
2573
							result.rawReverseMap.put(resolvedPath , rawEntry);
2555
							result.rawReverseMap.put(resolvedPath , rawEntry);
2574
							result.rootPathToResolvedEntries.put(resolvedPath, cEntry);
2556
							result.rootPathToResolvedEntries.put(resolvedPath, cEntry);
Lines 2580-2585 Link Here
2580
					}
2562
					}
2581
					break;
2563
					break;
2582
2564
2565
				case IClasspathEntry.CPE_LIBRARY:
2566
					rawEntry = ((ClasspathEntry) rawEntry).resolvedDotDot();
2567
					// $FALL-THROUGH$ use the default code below
2583
				default :
2568
				default :
2584
					if (result.rawReverseMap.get(resolvedPath = rawEntry.getPath()) == null) {
2569
					if (result.rawReverseMap.get(resolvedPath = rawEntry.getPath()) == null) {
2585
						result.rawReverseMap.put(resolvedPath , rawEntry);
2570
						result.rawReverseMap.put(resolvedPath , rawEntry);
(-)model/org/eclipse/jdt/internal/core/ClasspathEntry.java (-38 / +121 lines)
Lines 196-201 Link Here
196
	 * A constant indicating an output location.
196
	 * A constant indicating an output location.
197
	 */
197
	 */
198
	public static final int K_OUTPUT = 10;
198
	public static final int K_OUTPUT = 10;
199
	
200
	public static final String DOT_DOT = ".."; //$NON-NLS-1$
199
201
200
	/**
202
	/**
201
	 * The export flag
203
	 * The export flag
Lines 625-631 Link Here
625
		IPath path = new Path(pathAttr);
627
		IPath path = new Path(pathAttr);
626
		int kind = kindFromString(kindAttr);
628
		int kind = kindFromString(kindAttr);
627
		if (kind != IClasspathEntry.CPE_VARIABLE && kind != IClasspathEntry.CPE_CONTAINER && !path.isAbsolute()) {
629
		if (kind != IClasspathEntry.CPE_VARIABLE && kind != IClasspathEntry.CPE_CONTAINER && !path.isAbsolute()) {
628
			path = projectPath.append(path);
630
			if (!(path.segmentCount() > 0 && path.segment(0).equals(ClasspathEntry.DOT_DOT))) {
631
				path = projectPath.append(path);
632
			}
629
		}
633
		}
630
		// source attachment info (optional)
634
		// source attachment info (optional)
631
		IPath sourceAttachmentPath =
635
		IPath sourceAttachmentPath =
Lines 705-722 Link Here
705
709
706
			case IClasspathEntry.CPE_PROJECT :
710
			case IClasspathEntry.CPE_PROJECT :
707
				entry = new ClasspathEntry(
711
				entry = new ClasspathEntry(
708
				IPackageFragmentRoot.K_SOURCE,
712
												IPackageFragmentRoot.K_SOURCE,
709
				IClasspathEntry.CPE_PROJECT,
713
												IClasspathEntry.CPE_PROJECT,
710
				path,
714
												path,
711
				ClasspathEntry.INCLUDE_ALL, // inclusion patterns
715
												ClasspathEntry.INCLUDE_ALL, // inclusion patterns
712
				ClasspathEntry.EXCLUDE_NONE, // exclusion patterns
716
												ClasspathEntry.EXCLUDE_NONE, // exclusion patterns
713
				null, // source attachment
717
												null, // source attachment
714
				null, // source attachment root
718
												null, // source attachment root
715
				null, // specific output folder
719
												null, // specific output folder
716
				isExported,
720
												isExported,
717
				accessRules,
721
												accessRules,
718
				combineAccessRestrictions,
722
												combineAccessRestrictions,
719
				extraAttributes);
723
												extraAttributes);
720
				break;
724
				break;
721
			case IClasspathEntry.CPE_LIBRARY :
725
			case IClasspathEntry.CPE_LIBRARY :
722
				entry = JavaCore.newLibraryEntry(
726
				entry = JavaCore.newLibraryEntry(
Lines 731-737 Link Here
731
				// must be an entry in this project or specify another project
735
				// must be an entry in this project or specify another project
732
				String projSegment = path.segment(0);
736
				String projSegment = path.segment(0);
733
				if (projSegment != null && projSegment.equals(project.getElementName())) { // this project
737
				if (projSegment != null && projSegment.equals(project.getElementName())) { // this project
734
					entry = JavaCore.newSourceEntry(path, inclusionPatterns, exclusionPatterns, outputLocation, extraAttributes);
738
					entry = JavaCore.newSourceEntry(
739
												path, 
740
												inclusionPatterns, 
741
												exclusionPatterns, 
742
												outputLocation, 
743
												extraAttributes);
735
				} else {
744
				} else {
736
					if (path.segmentCount() == 1) {
745
					if (path.segmentCount() == 1) {
737
						// another project
746
						// another project
Lines 743-783 Link Here
743
												isExported);
752
												isExported);
744
					} else {
753
					} else {
745
						// an invalid source folder
754
						// an invalid source folder
746
						entry = JavaCore.newSourceEntry(path, inclusionPatterns, exclusionPatterns, outputLocation, extraAttributes);
755
						entry = JavaCore.newSourceEntry(
756
												path, 
757
												inclusionPatterns, 
758
												exclusionPatterns, 
759
												outputLocation, 
760
												extraAttributes);
747
					}
761
					}
748
				}
762
				}
749
				break;
763
				break;
750
			case IClasspathEntry.CPE_VARIABLE :
764
			case IClasspathEntry.CPE_VARIABLE :
751
				entry = JavaCore.newVariableEntry(
765
				entry = JavaCore.newVariableEntry(
752
						path,
766
												path,
753
						sourceAttachmentPath,
767
												sourceAttachmentPath,
754
						sourceAttachmentRootPath,
768
												sourceAttachmentRootPath,
755
						accessRules,
769
												accessRules,
756
						extraAttributes,
770
												extraAttributes,
757
						isExported);
771
												isExported);
758
				break;
772
				break;
759
			case IClasspathEntry.CPE_CONTAINER :
773
			case IClasspathEntry.CPE_CONTAINER :
760
				entry = JavaCore.newContainerEntry(
774
				entry = JavaCore.newContainerEntry(
761
						path,
775
												path,
762
						accessRules,
776
												accessRules,
763
						extraAttributes,
777
												extraAttributes,
764
						isExported);
778
												isExported);
765
				break;
779
				break;
766
			case ClasspathEntry.K_OUTPUT :
780
			case ClasspathEntry.K_OUTPUT :
767
				if (!path.isAbsolute()) return null;
781
				if (!path.isAbsolute()) return null;
768
				entry = new ClasspathEntry(
782
				entry = new ClasspathEntry(
769
						ClasspathEntry.K_OUTPUT,
783
												ClasspathEntry.K_OUTPUT,
770
						IClasspathEntry.CPE_LIBRARY,
784
												IClasspathEntry.CPE_LIBRARY,
771
						path,
785
												path,
772
						INCLUDE_ALL,
786
												INCLUDE_ALL,
773
						EXCLUDE_NONE,
787
												EXCLUDE_NONE,
774
						null, // source attachment
788
												null, // source attachment
775
						null, // source attachment root
789
												null, // source attachment root
776
						null, // custom output location
790
												null, // custom output location
777
						false,
791
												false,
778
						null, // no access rules
792
												null, // no access rules
779
						false, // no accessible files to combine
793
												false, // no accessible files to combine
780
						NO_EXTRA_ATTRIBUTES);
794
												NO_EXTRA_ATTRIBUTES);
781
				break;
795
				break;
782
			default :
796
			default :
783
				throw new AssertionFailedException(Messages.bind(Messages.classpath_unknownKind, kindAttr));
797
				throw new AssertionFailedException(Messages.bind(Messages.classpath_unknownKind, kindAttr));
Lines 792-797 Link Here
792
806
793
		return entry;
807
		return entry;
794
	}
808
	}
809
	
810
	/*
811
	 * Returns whether the given path as a ".." segment
812
	 */
813
	public static boolean hasDotDot(IPath path) {
814
		for (int i = 0, length = path.segmentCount(); i < length; i++) {
815
			if (DOT_DOT.equals(path.segment(i)))
816
				return true;
817
		}
818
		return false;
819
	}
795
820
796
	public static NodeList getChildAttributes(String childName, NodeList children, boolean[] foundChildren) {
821
	public static NodeList getChildAttributes(String childName, NodeList children, boolean[] foundChildren) {
797
		for (int i = 0, length = foundChildren.length; i < length; i++) {
822
		for (int i = 0, length = foundChildren.length; i < length; i++) {
Lines 822-827 Link Here
822
		}
847
		}
823
	}
848
	}
824
849
850
	/*
851
	 * Resolves the ".." in the given path. Returns the given path if it contains no ".." segment.
852
	 */
853
	public static IPath resolveDotDot(IPath path) {
854
		IPath newPath = null;
855
		IWorkspaceRoot root = null;
856
		IPath workspaceLocation = null;
857
		for (int i = 0, length = path.segmentCount(); i < length; i++) {
858
			String segment = path.segment(i);
859
			if (DOT_DOT.equals(segment)) {
860
				if (newPath == null) {
861
					if (i == 0) {
862
						workspaceLocation = (root = ResourcesPlugin.getWorkspace().getRoot()).getLocation();
863
						newPath = workspaceLocation;
864
					} else {
865
						newPath = path.removeFirstSegments(i);
866
					}
867
				} else {
868
					if (newPath.segmentCount() > 0) {
869
						newPath = newPath.removeLastSegments(1);
870
					} else {
871
						workspaceLocation = (root = ResourcesPlugin.getWorkspace().getRoot()).getLocation();
872
						newPath = workspaceLocation;
873
					}
874
				}
875
			} else if (newPath != null) {
876
				if (newPath.equals(workspaceLocation) && root.getProject(segment).isAccessible()) {
877
					newPath = new Path(segment).makeAbsolute();
878
				} else {
879
					newPath = newPath.append(segment);
880
				}
881
			}
882
		}
883
		if (newPath == null)
884
			return path;
885
		return newPath;
886
	}
887
825
	/**
888
	/**
826
	 * Encode some patterns into XML parameter tag
889
	 * Encode some patterns into XML parameter tag
827
	 */
890
	 */
Lines 1195-1201 Link Here
1195
		}
1258
		}
1196
		return buffer.toString();
1259
		return buffer.toString();
1197
	}
1260
	}
1198
1261
	
1262
	public ClasspathEntry resolvedDotDot() {
1263
		IPath resolvedPath = resolveDotDot(this.path);
1264
		if (resolvedPath == this.path)
1265
			return this;
1266
		return new ClasspathEntry(
1267
							getContentKind(),
1268
							getEntryKind(),
1269
							resolvedPath,
1270
							this.inclusionPatterns,
1271
							this.exclusionPatterns,
1272
							getSourceAttachmentPath(),
1273
							getSourceAttachmentRootPath(),
1274
							getOutputLocation(),
1275
							this.isExported,
1276
							getAccessRules(),
1277
							this.combineAccessRules,
1278
							this.extraAttributes);
1279
	}
1280
	
1199
	/**
1281
	/**
1200
	 * Answers an ID which is used to distinguish entries during package
1282
	 * Answers an ID which is used to distinguish entries during package
1201
	 * fragment root computations
1283
	 * fragment root computations
Lines 1636-1641 Link Here
1636
1718
1637
			// library entry check
1719
			// library entry check
1638
			case IClasspathEntry.CPE_LIBRARY :
1720
			case IClasspathEntry.CPE_LIBRARY :
1721
				path = ClasspathEntry.resolveDotDot(path);
1639
				if (path.isAbsolute() && !path.isEmpty()) {
1722
				if (path.isAbsolute() && !path.isEmpty()) {
1640
					IPath sourceAttachment = entry.getSourceAttachmentPath();
1723
					IPath sourceAttachment = entry.getSourceAttachmentPath();
1641
					Object target = JavaModel.getTarget(path, true);
1724
					Object target = JavaModel.getTarget(path, true);
(-)model/org/eclipse/jdt/internal/core/JavaModelManager.java (+1 lines)
Lines 2186-2191 Link Here
2186
		IPath resolvedPath = getResolvedVariablePath(entry.getPath(), usePreviousSession);
2186
		IPath resolvedPath = getResolvedVariablePath(entry.getPath(), usePreviousSession);
2187
		if (resolvedPath == null)
2187
		if (resolvedPath == null)
2188
			return null;
2188
			return null;
2189
		resolvedPath = ClasspathEntry.resolveDotDot(resolvedPath);
2189
2190
2190
		Object target = JavaModel.getTarget(resolvedPath, false);
2191
		Object target = JavaModel.getTarget(resolvedPath, false);
2191
		if (target == null)
2192
		if (target == null)
(-)model/org/eclipse/jdt/core/JavaCore.java (-5 / +10 lines)
Lines 3825-3831 Link Here
3825
	 * {@link #newLibraryEntry(IPath, IPath, IPath, IAccessRule[], IClasspathAttribute[], boolean)
3825
	 * {@link #newLibraryEntry(IPath, IPath, IPath, IAccessRule[], IClasspathAttribute[], boolean)
3826
	 * newLibraryEntry(path, sourceAttachmentPath, sourceAttachmentRootPath, new IAccessRule[0], new IClasspathAttribute[0], false)}.
3826
	 * newLibraryEntry(path, sourceAttachmentPath, sourceAttachmentRootPath, new IAccessRule[0], new IClasspathAttribute[0], false)}.
3827
	 *
3827
	 *
3828
	 * @param path the absolute path of the binary archive
3828
	 * @param path the path to the library
3829
	 * @param sourceAttachmentPath the absolute path of the corresponding source archive or folder,
3829
	 * @param sourceAttachmentPath the absolute path of the corresponding source archive or folder,
3830
	 *    or <code>null</code> if none. Note, since 3.0, an empty path is allowed to denote no source attachment.
3830
	 *    or <code>null</code> if none. Note, since 3.0, an empty path is allowed to denote no source attachment.
3831
	 *    Since 3.4, this path can also denote a path external to the workspace.
3831
	 *    Since 3.4, this path can also denote a path external to the workspace.
Lines 3856-3862 Link Here
3856
	 * {@link #newLibraryEntry(IPath, IPath, IPath, IAccessRule[], IClasspathAttribute[], boolean)
3856
	 * {@link #newLibraryEntry(IPath, IPath, IPath, IAccessRule[], IClasspathAttribute[], boolean)
3857
	 * newLibraryEntry(path, sourceAttachmentPath, sourceAttachmentRootPath, new IAccessRule[0], new IClasspathAttribute[0], isExported)}.
3857
	 * newLibraryEntry(path, sourceAttachmentPath, sourceAttachmentRootPath, new IAccessRule[0], new IClasspathAttribute[0], isExported)}.
3858
	 *
3858
	 *
3859
	 * @param path the absolute path of the binary archive
3859
	 * @param path the path to the library
3860
	 * @param sourceAttachmentPath the absolute path of the corresponding source archive or folder,
3860
	 * @param sourceAttachmentPath the absolute path of the corresponding source archive or folder,
3861
	 *    or <code>null</code> if none. Note, since 3.0, an empty path is allowed to denote no source attachment.
3861
	 *    or <code>null</code> if none. Note, since 3.0, an empty path is allowed to denote no source attachment.
3862
	 *   and will be automatically converted to <code>null</code>. Since 3.4, this path can also denote a path external
3862
	 *   and will be automatically converted to <code>null</code>. Since 3.4, this path can also denote a path external
Lines 3893-3904 Link Here
3893
	 * to the workspace root), or externally to the workspace (absolute path in the file system).
3893
	 * to the workspace root), or externally to the workspace (absolute path in the file system).
3894
	 * The target root folder can also be defined internally to the workspace (absolute path relative
3894
	 * The target root folder can also be defined internally to the workspace (absolute path relative
3895
	 * to the workspace root), or - since 3.4 - externally to the workspace (absolute path in the file system).
3895
	 * to the workspace root), or - since 3.4 - externally to the workspace (absolute path in the file system).
3896
	 * Since 3.5, the path to the library can also be relative to the project using ".." as the first segment. 
3896
	 * <p>
3897
	 * <p>
3897
	 * e.g. Here are some examples of binary path usage<ul>
3898
	 * e.g. Here are some examples of binary path usage<ul>
3898
	 *	<li><code> "c:\jdk1.2.2\jre\lib\rt.jar" </code> - reference to an external JAR on Windows</li>
3899
	 *	<li><code> "c:\jdk1.2.2\jre\lib\rt.jar" </code> - reference to an external JAR on Windows</li>
3899
	 *	<li><code> "/Project/someLib.jar" </code> - reference to an internal JAR on Windows or Linux</li>
3900
	 *	<li><code> "/Project/someLib.jar" </code> - reference to an internal JAR on Windows or Linux</li>
3900
	 *	<li><code> "/Project/classes/" </code> - reference to an internal binary folder on Windows or Linux</li>
3901
	 *	<li><code> "/Project/classes/" </code> - reference to an internal binary folder on Windows or Linux</li>
3901
	 *	<li><code> "/home/usr/classes" </code> - reference to an external binary folder on Linux</li>
3902
	 *	<li><code> "/home/usr/classes" </code> - reference to an external binary folder on Linux</li>
3903
	 *	<li><code> "../../lib/someLib.jar" </code> - reference to an external JAR that is a sibbling of the workspace on either platform</li>
3902
	 * </ul>
3904
	 * </ul>
3903
	 * Note that on non-Windows platform, a path <code>"/some/lib.jar"</code> is ambiguous.
3905
	 * Note that on non-Windows platform, a path <code>"/some/lib.jar"</code> is ambiguous.
3904
	 * It can be a path to an external JAR (its file system path being <code>"/some/lib.jar"</code>)
3906
	 * It can be a path to an external JAR (its file system path being <code>"/some/lib.jar"</code>)
Lines 3928-3934 Link Here
3928
	 * with the non accessible files patterns of the project.
3930
	 * with the non accessible files patterns of the project.
3929
	 * </p>
3931
	 * </p>
3930
	 *
3932
	 *
3931
	 * @param path the absolute path of the binary archive
3933
	 * @param path the path to the library
3932
	 * @param sourceAttachmentPath the absolute path of the corresponding source archive or folder,
3934
	 * @param sourceAttachmentPath the absolute path of the corresponding source archive or folder,
3933
	 *    or <code>null</code> if none. Note, since 3.0, an empty path is allowed to denote no source attachment.
3935
	 *    or <code>null</code> if none. Note, since 3.0, an empty path is allowed to denote no source attachment.
3934
	 *   and will be automatically converted to <code>null</code>. Since 3.4, this path can also denote a path external
3936
	 *   and will be automatically converted to <code>null</code>. Since 3.4, this path can also denote a path external
Lines 3951-3957 Link Here
3951
			boolean isExported) {
3953
			boolean isExported) {
3952
3954
3953
		if (path == null) throw new ClasspathEntry.AssertionFailedException("Library path cannot be null"); //$NON-NLS-1$
3955
		if (path == null) throw new ClasspathEntry.AssertionFailedException("Library path cannot be null"); //$NON-NLS-1$
3954
		if (!path.isAbsolute()) throw new ClasspathEntry.AssertionFailedException("Path for IClasspathEntry must be absolute: " + path); //$NON-NLS-1$
3956
		boolean hasDotDot = ClasspathEntry.hasDotDot(path);
3957
		if (!hasDotDot && !path.isAbsolute()) throw new ClasspathEntry.AssertionFailedException("Path for IClasspathEntry must be absolute: " + path); //$NON-NLS-1$
3955
		if (sourceAttachmentPath != null) {
3958
		if (sourceAttachmentPath != null) {
3956
			if (sourceAttachmentPath.isEmpty()) {
3959
			if (sourceAttachmentPath.isEmpty()) {
3957
				sourceAttachmentPath = null; // treat empty path as none
3960
				sourceAttachmentPath = null; // treat empty path as none
Lines 3964-3970 Link Here
3964
		return new ClasspathEntry(
3967
		return new ClasspathEntry(
3965
			IPackageFragmentRoot.K_BINARY,
3968
			IPackageFragmentRoot.K_BINARY,
3966
			IClasspathEntry.CPE_LIBRARY,
3969
			IClasspathEntry.CPE_LIBRARY,
3967
			JavaProject.canonicalizedPath(path),
3970
			hasDotDot ? path : JavaProject.canonicalizedPath(path),
3968
			ClasspathEntry.INCLUDE_ALL, // inclusion patterns
3971
			ClasspathEntry.INCLUDE_ALL, // inclusion patterns
3969
			ClasspathEntry.EXCLUDE_NONE, // exclusion patterns
3972
			ClasspathEntry.EXCLUDE_NONE, // exclusion patterns
3970
			sourceAttachmentPath,
3973
			sourceAttachmentPath,
Lines 4668-4673 Link Here
4668
	/**
4671
	/**
4669
	 * Sets the value of the given classpath variable.
4672
	 * Sets the value of the given classpath variable.
4670
	 * The path must not be null.
4673
	 * The path must not be null.
4674
	 * Since 3.5, the path to a library can also be relative to the project using ".." as the first segment. 
4671
	 * <p>
4675
	 * <p>
4672
	 * This functionality cannot be used while the resource tree is locked.
4676
	 * This functionality cannot be used while the resource tree is locked.
4673
	 * <p>
4677
	 * <p>
Lines 4695-4700 Link Here
4695
	/**
4699
	/**
4696
	 * Sets the values of all the given classpath variables at once.
4700
	 * Sets the values of all the given classpath variables at once.
4697
	 * Null paths can be used to request corresponding variable removal.
4701
	 * Null paths can be used to request corresponding variable removal.
4702
	 * Since 3.5, the path to a library can also be relative to the project using ".." as the first segment.
4698
	 * <p>
4703
	 * <p>
4699
	 * A combined Java element delta will be notified to describe the corresponding
4704
	 * A combined Java element delta will be notified to describe the corresponding
4700
	 * classpath changes resulting from the variables update. This operation is batched,
4705
	 * classpath changes resulting from the variables update. This operation is batched,
(-)src/org/eclipse/jdt/core/tests/model/ClasspathTests.java (+255 lines)
Lines 2307-2312 Link Here
2307
	}
2307
	}
2308
}
2308
}
2309
2309
2310
/*
2311
 * Ensures that one can point at an external library using a ".." entry in a cp container
2312
 */
2313
public void testDotDotContainerEntry1() throws Exception {
2314
	String externalJarPath = getWorkspaceRoot().getLocation().removeLastSegments(1).append("external.jar").toOSString();
2315
	try {
2316
		IJavaProject p = createJavaProject("P");
2317
		Util.writeToFile("", externalJarPath);
2318
		ContainerInitializer.setInitializer(new DefaultContainerInitializer(new String[] {"P", "../../external.jar"}));
2319
		setClasspath(p, new IClasspathEntry[] {JavaCore.newContainerEntry(new Path("org.eclipse.jdt.core.tests.model.TEST_CONTAINER"))});
2320
		assertElementDescendants(
2321
			"Unexpected project content",
2322
			"P\n" + 
2323
			"  "+ getExternalPath() + "external.jar",
2324
			p
2325
		);
2326
	} finally {
2327
		deleteResource(new File(externalJarPath));
2328
		deleteProject("P");
2329
		ContainerInitializer.setInitializer(null);
2330
	}
2331
}
2332
2333
/*
2334
 * Ensures that a marker is created if one can point at a non-existing external library using a ".." entry in a cp container
2335
 */
2336
public void testDotDotContainerEntry2() throws Exception {
2337
	try {
2338
		IJavaProject p = createJavaProject("P");
2339
		ContainerInitializer.setInitializer(new DefaultContainerInitializer(new String[] {"P", "../../nonExisting.jar"}));
2340
		setClasspath(p, new IClasspathEntry[] {JavaCore.newContainerEntry(new Path("org.eclipse.jdt.core.tests.model.TEST_CONTAINER"))});
2341
		assertMarkers(
2342
			"Unexpected markers", 
2343
			"Project \'P\' is missing required library: \'"+ getExternalPath() + "nonExisting.jar\'",
2344
			p);
2345
	} finally {
2346
		deleteProject("P");
2347
		ContainerInitializer.setInitializer(null);
2348
	}
2349
}
2350
2351
/*
2352
 * Ensures that one can point at an external library using a ".." path
2353
 */
2354
public void testDotDotLibraryEntry1() throws Exception {
2355
	String externalJarPath = getWorkspaceRoot().getLocation().append("external.jar").toOSString();
2356
	try {
2357
		IJavaProject p = createJavaProject("P");
2358
		Util.writeToFile("", externalJarPath);
2359
		setClasspath(p, new IClasspathEntry[] {JavaCore.newLibraryEntry(new Path("../external.jar"), null, null)});
2360
		assertElementDescendants(
2361
			"Unexpected project content",
2362
			"P\n" + 
2363
			"  "+ getWorkspacePath() + "external.jar",
2364
			p
2365
		);
2366
	} finally {
2367
		deleteResource(new File(externalJarPath));
2368
		deleteProject("P");
2369
	}
2370
}
2371
2372
/*
2373
 * Ensures that one can point at an external library using a ".." path
2374
 */
2375
public void testDotDotLibraryEntry2() throws Exception {
2376
	String externalJarPath = getWorkspaceRoot().getLocation().removeLastSegments(1).append("external.jar").toOSString();
2377
	try {
2378
		IJavaProject p = createJavaProject("P");
2379
		Util.writeToFile("", externalJarPath);
2380
		setClasspath(p, new IClasspathEntry[] {JavaCore.newLibraryEntry(new Path("../../external.jar"), null, null)});
2381
		assertElementDescendants(
2382
			"Unexpected project content",
2383
			"P\n" + 
2384
			"  "+ getExternalPath() + "external.jar",
2385
			p
2386
		);
2387
	} finally {
2388
		deleteResource(new File(externalJarPath));
2389
		deleteProject("P");
2390
	}
2391
}
2392
2393
/*
2394
 * Ensures that one can point at an external library using a ".." path
2395
 */
2396
public void testDotDotLibraryEntry3() throws Exception {
2397
	String externalJarPath = getWorkspaceRoot().getLocation().removeLastSegments(1).append("external.jar").toOSString();
2398
	try {
2399
		IJavaProject p = createJavaProject("P");
2400
		Util.writeToFile("", externalJarPath);
2401
		setClasspath(p, new IClasspathEntry[] {JavaCore.newLibraryEntry(new Path("src/../../../external.jar"), null, null)});
2402
		assertElementDescendants(
2403
			"Unexpected project content",
2404
			"P\n" + 
2405
			"  "+ getExternalPath() + "external.jar",
2406
			p
2407
		);
2408
	} finally {
2409
		deleteResource(new File(externalJarPath));
2410
		deleteProject("P");
2411
	}
2412
}
2413
2414
/*
2415
 * Ensures that one can point at an internal library using a ".." path
2416
 */
2417
public void testDotDotLibraryEntry4() throws Exception {
2418
	try {
2419
		createProject("P1");
2420
		createFile("/P1/internal.jar", "");
2421
		IJavaProject p = createJavaProject("P2");
2422
		setClasspath(p, new IClasspathEntry[] {JavaCore.newLibraryEntry(new Path("../P1/internal.jar"), null, null)});
2423
		assertElementDescendants(
2424
			"Unexpected project content",
2425
			"P2\n" + 
2426
			"  /P1/internal.jar",
2427
			p
2428
		);
2429
	} finally {
2430
		deleteProject("P1");
2431
		deleteProject("P2");
2432
	}
2433
}
2434
2435
/*
2436
 * Ensures that no markers are created if one can point at an existing external library using a ".." path
2437
 */
2438
public void testDotDotLibraryEntry5() throws Exception {
2439
	String externalJarPath = getWorkspaceRoot().getLocation().append("external.jar").toOSString();
2440
	try {
2441
		IJavaProject p = createJavaProject("P");
2442
		Util.writeToFile("", externalJarPath);
2443
		setClasspath(p, new IClasspathEntry[] {JavaCore.newLibraryEntry(new Path("../external.jar"), null, null)});
2444
		assertMarkers(
2445
			"Unexpected markers", 
2446
			"", 
2447
			p);
2448
	} finally {
2449
		deleteResource(new File(externalJarPath));
2450
		deleteProject("P");
2451
	}
2452
}
2453
2454
/*
2455
 * Ensures that a marker is created if one can point at a non-existing external library using a ".." path
2456
 */
2457
public void testDotDotLibraryEntry6() throws Exception {
2458
	try {
2459
		IJavaProject p = createJavaProject("P");
2460
		setClasspath(p, new IClasspathEntry[] {JavaCore.newLibraryEntry(new Path("../external.jar"), null, null)});
2461
		assertMarkers(
2462
			"Unexpected markers", 
2463
			"Project \'P\' is missing required library: \'"+ getWorkspacePath() + "external.jar\'",
2464
			p);
2465
	} finally {
2466
		deleteProject("P");
2467
	}
2468
}
2469
2470
/*
2471
 * Ensures that one can point at an external library using a ".." path by editing the .classpath file
2472
 */
2473
public void testDotDotLibraryEntry7() throws Exception {
2474
	String externalJarPath = getWorkspaceRoot().getLocation().append("external.jar").toOSString();
2475
	try {
2476
		IJavaProject p = createJavaProject("P");
2477
		Util.writeToFile("", externalJarPath);
2478
		editFile(
2479
			"/P/.classpath",
2480
			"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + 
2481
			"<classpath>\n" + 
2482
			"	<classpathentry kind=\"src\" path=\"\"/>\n" + 
2483
			"	<classpathentry kind=\"lib\" path=\"../external.jar\"/>\n" + 
2484
			"	<classpathentry kind=\"output\" path=\"\"/>\n" + 
2485
			"</classpath>");
2486
		assertElementDescendants(
2487
			"Unexpected project content",
2488
			"P\n" + 
2489
			"  <project root>\n" + 
2490
			"    <default> (...)\n" + 
2491
			"  "+ getWorkspacePath() + "external.jar",
2492
			p
2493
		);
2494
	} finally {
2495
		deleteResource(new File(externalJarPath));
2496
		deleteProject("P");
2497
	}
2498
}
2499
2500
/*
2501
 * Ensures that the raw classpath is correct if pointing at an external library using a ".." path by editing the .classpath file
2502
 */
2503
public void testDotDotLibraryEntry8() throws Exception {
2504
	try {
2505
		IJavaProject p = createJavaProject("P");
2506
		editFile(
2507
			"/P/.classpath",
2508
			"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + 
2509
			"<classpath>\n" + 
2510
			"	<classpathentry kind=\"src\" path=\"\"/>\n" + 
2511
			"	<classpathentry kind=\"lib\" path=\"../external.jar\"/>\n" + 
2512
			"	<classpathentry kind=\"output\" path=\"\"/>\n" + 
2513
			"</classpath>");
2514
		assertClasspathEquals(
2515
			p.getRawClasspath(), 
2516
			"/P[CPE_SOURCE][K_SOURCE][isExported:false]\n" + 
2517
			"../external.jar[CPE_LIBRARY][K_BINARY][isExported:false]"
2518
		);
2519
	} finally {
2520
		deleteProject("P");
2521
	}
2522
}
2523
2524
/*
2525
 * Ensures that one can point at an external library using a ".." variable entry
2526
 */
2527
public void testDotDotVariableEntry1() throws Exception {
2528
	String externalJarPath = getWorkspaceRoot().getLocation().removeLastSegments(1).append("external.jar").toOSString();
2529
	try {
2530
		JavaCore.setClasspathVariable("TWO_UP", new Path("../.."), null);
2531
		IJavaProject p = createJavaProject("P");
2532
		Util.writeToFile("", externalJarPath);
2533
		setClasspath(p, new IClasspathEntry[] {JavaCore.newVariableEntry(new Path("TWO_UP/external.jar"), null, null)});
2534
		assertElementDescendants(
2535
			"Unexpected project content",
2536
			"P\n" + 
2537
			"  "+ getExternalPath() + "external.jar",
2538
			p
2539
		);
2540
	} finally {
2541
		deleteResource(new File(externalJarPath));
2542
		deleteProject("P");
2543
		JavaCore.removeClasspathVariable("TWO_UP", null);
2544
	}
2545
}
2546
2547
/*
2548
 * Ensures that a marker is created if one can point at a non-existing external library using a ".." variable entry
2549
 */
2550
public void testDotDotVariableEntry2() throws Exception {
2551
	try {
2552
		JavaCore.setClasspathVariable("TWO_UP", new Path("../.."), null);
2553
		IJavaProject p = createJavaProject("P");
2554
		setClasspath(p, new IClasspathEntry[] {JavaCore.newVariableEntry(new Path("TWO_UP/nonExisting.jar"), null, null)});
2555
		assertMarkers(
2556
			"Unexpected markers", 
2557
			"Project \'P\' is missing required library: \'"+ getExternalPath() + "nonExisting.jar\'",
2558
			p);
2559
	} finally {
2560
		deleteProject("P");
2561
		JavaCore.removeClasspathVariable("TWO_UP", null);
2562
	}
2563
}
2564
2310
/**
2565
/**
2311
 * Setting the classpath to empty should result in no entries,
2566
 * Setting the classpath to empty should result in no entries,
2312
 * and a delta with removed roots.
2567
 * and a delta with removed roots.
(-)src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java (-2 / +34 lines)
Lines 46-51 Link Here
46
	 */
46
	 */
47
	protected static String EXTERNAL_JAR_DIR_PATH;
47
	protected static String EXTERNAL_JAR_DIR_PATH;
48
48
49
	/**
50
	 * The java.io.File path to the workspace directory.
51
	 */
52
	protected static String WORKSPACE_DIR_PATH;
53
49
	// used java project
54
	// used java project
50
	protected IJavaProject currentProject;
55
	protected IJavaProject currentProject;
51
56
Lines 1813-1818 Link Here
1813
			}
1818
			}
1814
		return EXTERNAL_JAR_DIR_PATH;
1819
		return EXTERNAL_JAR_DIR_PATH;
1815
	}
1820
	}
1821
	/*
1822
	 * Returns the OS path to the workspace directory.
1823
	 * This path ends with a File.separatorChar.
1824
	 */
1825
	protected String getWorkspacePath() {
1826
		if (WORKSPACE_DIR_PATH == null)
1827
			try {
1828
				String path = getWorkspaceRoot().getLocation().toFile().getCanonicalPath();
1829
				if (path.charAt(path.length()-1) != File.separatorChar)
1830
					path += File.separatorChar;
1831
				WORKSPACE_DIR_PATH = path;
1832
			} catch (IOException e) {
1833
				e.printStackTrace();
1834
			}
1835
		return WORKSPACE_DIR_PATH;
1836
	}
1816
	protected IFile getFile(String path) {
1837
	protected IFile getFile(String path) {
1817
		return getWorkspaceRoot().getFile(new Path(path));
1838
		return getWorkspaceRoot().getFile(new Path(path));
1818
	}
1839
	}
Lines 2013-2021 Link Here
2013
	}
2034
	}
2014
2035
2015
	protected String displayString(String toPrint, int indent) {
2036
	protected String displayString(String toPrint, int indent) {
2016
    	char[] toDisplay =
2037
    	char[] toDisplay = toPrint.toCharArray();
2038
    	toDisplay =
2039
    		CharOperation.replace(
2040
    			toDisplay,
2041
    			getWorkspacePath().toCharArray(),
2042
    			"getWorkspacePath()".toCharArray());
2043
    	toDisplay =
2017
    		CharOperation.replace(
2044
    		CharOperation.replace(
2018
    			toPrint.toCharArray(),
2045
    			toDisplay,
2019
    			getExternalJCLPathString().toCharArray(),
2046
    			getExternalJCLPathString().toCharArray(),
2020
    			"getExternalJCLPathString()".toCharArray());
2047
    			"getExternalJCLPathString()".toCharArray());
2021
		toDisplay =
2048
		toDisplay =
Lines 2045-2050 Link Here
2045
    	toDisplay =
2072
    	toDisplay =
2046
    		CharOperation.replace(
2073
    		CharOperation.replace(
2047
    			toDisplay,
2074
    			toDisplay,
2075
    			"getWorkspacePath()".toCharArray(),
2076
    			("\"+ getWorkspacePath() + \"").toCharArray());
2077
    	toDisplay =
2078
    		CharOperation.replace(
2079
    			toDisplay,
2048
    			"getExternalJCLPathString()".toCharArray(),
2080
    			"getExternalJCLPathString()".toCharArray(),
2049
    			("\"+ getExternalJCLPathString() + \"").toCharArray());
2081
    			("\"+ getExternalJCLPathString() + \"").toCharArray());
2050
    	toDisplay =
2082
    	toDisplay =

Return to bug 57732