View | Details | Raw Unified | Return to bug 281551 | Differences between
and this patch

Collapse All | Expand All

(-)model/org/eclipse/jdt/core/IClasspathEntry.java (-1 / +23 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2008 IBM Corporation and others.
2
 * Copyright (c) 2000, 2010 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 418-423 Link Here
418
	 */
418
	 */
419
	IPath getSourceAttachmentRootPath();
419
	IPath getSourceAttachmentRootPath();
420
420
421
	
422
	/**
423
	 * Returns the classpath entry that is making a reference to this classpath entry. For entry kinds 
424
	 * {@link #CPE_LIBRARY}, the return value is the entry that is representing the JAR that includes 
425
	 * <code>this</code> in the MANIFEST.MF file's Class-Path section. For entry kinds other than 
426
	 * {@link #CPE_LIBRARY}, this returns null. For those entries that are on the raw classpath already, 
427
	 * this returns <code>null</code>  
428
	 * <p>
429
	 * It is possible that multiple library entries refer to the same entry
430
	 * via the MANIFEST.MF file. In those cases, this method returns the first classpath entry 
431
	 * that appears in the raw classpath. However, this does not mean that the other referencing 
432
	 * entries do not relate to their referenced entries. 
433
	 * See {@link JavaCore#getReferencedClasspathEntries(IClasspathEntry, IJavaProject)} for 
434
	 * more details.
435
	 * </p>
436
	 * 
437
	 * @return the classpath entry that is referencing this entry or <code>null</code> if 
438
	 * 		not applicable.
439
	 * @since 3.6
440
	 */
441
	IClasspathEntry getReferencingEntry();
442
421
	/**
443
	/**
422
	 * Returns whether this entry is exported to dependent projects.
444
	 * Returns whether this entry is exported to dependent projects.
423
	 * Always returns <code>false</code> for source entries (kind
445
	 * Always returns <code>false</code> for source entries (kind
(-)model/org/eclipse/jdt/core/IJavaProject.java (-1 / +49 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2008 IBM Corporation and others.
2
 * Copyright (c) 2000, 2010 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 1008-1013 Link Here
1008
	void setRawClasspath(IClasspathEntry[] entries, boolean canModifyResources, IProgressMonitor monitor) throws JavaModelException;
1008
	void setRawClasspath(IClasspathEntry[] entries, boolean canModifyResources, IProgressMonitor monitor) throws JavaModelException;
1009
1009
1010
	/**
1010
	/**
1011
	 * Works same as {@link #setRawClasspath(IClasspathEntry[], IPath, IProgressMonitor)} and 
1012
	 * additionally allows persisting the given array of referenced entries for this project.
1013
	 * The referenced entries and their attributes are stores in the .classpath file of this 
1014
	 * project. For details on  referenced entries, see 
1015
	 * {@link JavaCore#getReferencedClasspathEntries(IClasspathEntry, IJavaProject)}
1016
	 * and {@link IClasspathEntry#getReferencingEntry()}.
1017
	 * <p>
1018
	 * Since the referenced entries are stored in the .classpath file, clients can store additional 
1019
	 * information that belong to these entries and retrieve them across sessions, though the referenced
1020
	 * entries themselves may not be present in the raw classpath. By passing a <code>null</code>
1021
	 * referencedEntries, clients can choose not to modify the already persisted referenced entries,
1022
	 * which is fully equivalent to {@link #setRawClasspath(IClasspathEntry[], IPath, IProgressMonitor)}.
1023
	 * If an empty array is passed as referencedEntries, the already persisted referenced entries, 
1024
	 * if any, will be cleared. 
1025
	 * </p> <p>
1026
	 * If there are duplicates of a referenced entry or if any of the <code>referencedEntries</code> 
1027
	 * is already present in the raw classpath(<code>entries</code>) those referenced entries will 
1028
	 * be excluded and will not be persisted.
1029
	 *</p>
1030
	 * @param entries a list of classpath entries
1031
	 * @param referencedEntries the list of referenced classpath entries to be persisted
1032
	 * @param outputLocation the default output location
1033
	 * @param monitor the given progress monitor
1034
	 * @exception JavaModelException if the classpath could not be set. Reasons include:
1035
	 * <ul>
1036
	 * <li> This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
1037
	 * <li> The classpath is being modified during resource change event notification (CORE_EXCEPTION)
1038
	 * <li> The classpath failed the validation check as defined by {@link JavaConventions#validateClasspath(IJavaProject, IClasspathEntry[], IPath)}
1039
	 * </ul>
1040
	 * @see IClasspathEntry
1041
	 * @see #getReferencedClasspathEntries()
1042
	 * @since 3.6
1043
	 */
1044
	void setRawClasspath(IClasspathEntry[] entries, IClasspathEntry[] referencedEntries, IPath outputLocation,
1045
			IProgressMonitor monitor) throws JavaModelException;
1046
1047
	/**
1048
	 * Returns the list of referenced classpath entries stored in the .classpath file of <code>this</code> 
1049
	 * java project. Clients can store the referenced classpath entries using 
1050
	 * {@link #setRawClasspath(IClasspathEntry[], IClasspathEntry[], IPath, IProgressMonitor)}
1051
	 * 
1052
	 * @throws JavaModelException
1053
	 * @return an array of referenced classpath entries stored for this java project
1054
	 * @since 3.6
1055
	 */
1056
	IClasspathEntry[] getReferencedClasspathEntries() throws JavaModelException;
1057
	
1058
	/**
1011
	 * Sets the classpath of this project using a list of classpath entries. In particular such a classpath may contain
1059
	 * Sets the classpath of this project using a list of classpath entries. In particular such a classpath may contain
1012
	 * classpath variable entries. Classpath variable entries can be resolved individually ({@link JavaCore#getClasspathVariable(String)}),
1060
	 * classpath variable entries. Classpath variable entries can be resolved individually ({@link JavaCore#getClasspathVariable(String)}),
1013
	 * or the full classpath can be resolved at once using the helper method {@link #getResolvedClasspath(boolean)}.
1061
	 * or the full classpath can be resolved at once using the helper method {@link #getResolvedClasspath(boolean)}.
(-)model/org/eclipse/jdt/core/IPackageFragmentRoot.java (-1 / +13 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2008 IBM Corporation and others.
2
 * Copyright (c) 2000, 2010 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 311-316 Link Here
311
	 * @since 2.0
311
	 * @since 2.0
312
	 */
312
	 */
313
	IClasspathEntry getRawClasspathEntry() throws JavaModelException;
313
	IClasspathEntry getRawClasspathEntry() throws JavaModelException;
314
	
315
	/**
316
	 * Returns the first resolved classpath entry that corresponds to this package fragment root.
317
	 * A resolved classpath entry is said to correspond to a root if the path of the resolved
318
	 * entry is equal to the root's path.
319
	 * 
320
	 * @return the first resolved classpath entry that corresponds to this package fragment root
321
	 * @throws JavaModelException if this element does not exist or if an
322
	 *		exception occurs while accessing its corresponding resource. 
323
	 * @since 3.6
324
	 */
325
	IClasspathEntry getResolvedClasspathEntry() throws JavaModelException;
314
326
315
	/**
327
	/**
316
	 * Returns the absolute path to the source archive attached to
328
	 * Returns the absolute path to the source archive attached to
(-)model/org/eclipse/jdt/core/JavaCore.java (+27 lines)
Lines 4587-4592 Link Here
4587
			false, // no access rules to combine
4587
			false, // no access rules to combine
4588
			extraAttributes);
4588
			extraAttributes);
4589
	}
4589
	}
4590
	
4591
	/**
4592
	 * Returns an array of classpath entries that are referenced directly or indirectly 
4593
	 * by a given classpath entry. For the entry kind {@link IClasspathEntry#CPE_LIBRARY}, 
4594
	 * the method returns the libraries that are included in the Class-Path section of 
4595
	 * the MANIFEST.MF file. If a referenced JAR file has further references to other library 
4596
	 * entries, they are processed recursively and added to the list. For entry kinds other 
4597
	 * than {@link IClasspathEntry#CPE_LIBRARY}, this method returns an empty array.
4598
	 * <p> 
4599
	 * If a referenced entry has already been stored 
4600
	 * in the given project's .classpath, the stored attributes are populated in the corresponding
4601
	 * referenced entry. For more details on storing referenced entries see
4602
	 * see {@link IJavaProject#setRawClasspath(IClasspathEntry[], IClasspathEntry[], IPath, 
4603
	 * IProgressMonitor)}. 
4604
	 * </p>
4605
	 * 
4606
	 * @param libraryEntry the library entry whose referenced entries are sought 
4607
	 * @param project project where the persisted referenced entries to be retrieved from
4608
	 * @return an array of classpath entries that are referenced directly or indirectly by the given entry. 
4609
	 * 			If not applicable, returns an emptry array.
4610
	 * @since 3.6
4611
	 */
4612
	public static IClasspathEntry[] getReferencedClasspathEntries(IClasspathEntry libraryEntry, IJavaProject project) {
4613
		JavaModelManager manager = JavaModelManager.getJavaModelManager();
4614
		return manager.getReferencedClasspathEntries(libraryEntry, project);
4615
	}
4616
	
4590
	/**
4617
	/**
4591
	 * Removed the given classpath variable. Does nothing if no value was
4618
	 * Removed the given classpath variable. Does nothing if no value was
4592
	 * set for this classpath variable.
4619
	 * set for this classpath variable.
(-)model/org/eclipse/jdt/internal/core/ClasspathEntry.java (-20 / +68 lines)
Lines 77-82 Link Here
77
77
78
	public static final String TAG_CLASSPATH = "classpath"; //$NON-NLS-1$
78
	public static final String TAG_CLASSPATH = "classpath"; //$NON-NLS-1$
79
	public static final String TAG_CLASSPATHENTRY = "classpathentry"; //$NON-NLS-1$
79
	public static final String TAG_CLASSPATHENTRY = "classpathentry"; //$NON-NLS-1$
80
	public static final String TAG_REFERENCED_ENTRY = "referencedentry"; //$NON-NLS-1$
80
	public static final String TAG_OUTPUT = "output"; //$NON-NLS-1$
81
	public static final String TAG_OUTPUT = "output"; //$NON-NLS-1$
81
	public static final String TAG_KIND = "kind"; //$NON-NLS-1$
82
	public static final String TAG_KIND = "kind"; //$NON-NLS-1$
82
	public static final String TAG_PATH = "path"; //$NON-NLS-1$
83
	public static final String TAG_PATH = "path"; //$NON-NLS-1$
Lines 141-147 Link Here
141
	private IPath[] exclusionPatterns;
142
	private IPath[] exclusionPatterns;
142
	private char[][] fullExclusionPatternChars;
143
	private char[][] fullExclusionPatternChars;
143
	private final static char[][] UNINIT_PATTERNS = new char[][] { "Non-initialized yet".toCharArray() }; //$NON-NLS-1$
144
	private final static char[][] UNINIT_PATTERNS = new char[][] { "Non-initialized yet".toCharArray() }; //$NON-NLS-1$
144
	private final static ClasspathEntry[] NO_ENTRIES = new ClasspathEntry[0];
145
	public final static ClasspathEntry[] NO_ENTRIES = new ClasspathEntry[0];
145
	private final static IPath[] NO_PATHS = new IPath[0];
146
	private final static IPath[] NO_PATHS = new IPath[0];
146
	private final static IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
147
	private final static IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
147
148
Lines 197-202 Link Here
197
	 * a non-<code>null</code> value.
198
	 * a non-<code>null</code> value.
198
	 */
199
	 */
199
	public IPath sourceAttachmentRootPath;
200
	public IPath sourceAttachmentRootPath;
201
	
202
	/**
203
	 * See {@link IClasspathEntry#getReferencingEntry()}
204
	 */
205
	public IClasspathEntry referencingEntry;
200
206
201
	/**
207
	/**
202
	 * Specific output location (for this source entry)
208
	 * Specific output location (for this source entry)
Lines 215-225 Link Here
215
	 */
221
	 */
216
	public boolean isExported;
222
	public boolean isExported;
217
223
218
	/*
224
	/**
219
	 * The extra attributes
225
	 * The extra attributes
220
	 */
226
	 */
221
	IClasspathAttribute[] extraAttributes;
227
	public IClasspathAttribute[] extraAttributes;
222
228
229
	public ClasspathEntry(
230
			int contentKind,
231
			int entryKind,
232
			IPath path,
233
			IPath[] inclusionPatterns,
234
			IPath[] exclusionPatterns,
235
			IPath sourceAttachmentPath,
236
			IPath sourceAttachmentRootPath,
237
			IPath specificOutputLocation,
238
			boolean isExported,
239
			IAccessRule[] accessRules,
240
			boolean combineAccessRules,
241
			IClasspathAttribute[] extraAttributes) {
242
243
		this(	contentKind, 
244
				entryKind, 
245
				path, 
246
				inclusionPatterns, 
247
				exclusionPatterns, 
248
				sourceAttachmentPath, 
249
				sourceAttachmentRootPath, 
250
				specificOutputLocation,
251
				null,
252
				isExported,
253
				accessRules,
254
				combineAccessRules,
255
				extraAttributes);
256
	}
257
	
223
	/**
258
	/**
224
	 * Creates a class path entry of the specified kind with the given path.
259
	 * Creates a class path entry of the specified kind with the given path.
225
	 */
260
	 */
Lines 232-237 Link Here
232
		IPath sourceAttachmentPath,
267
		IPath sourceAttachmentPath,
233
		IPath sourceAttachmentRootPath,
268
		IPath sourceAttachmentRootPath,
234
		IPath specificOutputLocation,
269
		IPath specificOutputLocation,
270
		IClasspathEntry referencingEntry,
235
		boolean isExported,
271
		boolean isExported,
236
		IAccessRule[] accessRules,
272
		IAccessRule[] accessRules,
237
		boolean combineAccessRules,
273
		boolean combineAccessRules,
Lines 242-248 Link Here
242
		this.path = path;
278
		this.path = path;
243
		this.inclusionPatterns = inclusionPatterns;
279
		this.inclusionPatterns = inclusionPatterns;
244
		this.exclusionPatterns = exclusionPatterns;
280
		this.exclusionPatterns = exclusionPatterns;
245
281
		this.referencingEntry = referencingEntry;
282
		
246
		int length;
283
		int length;
247
		if (accessRules != null && (length = accessRules.length) > 0) {
284
		if (accessRules != null && (length = accessRules.length) > 0) {
248
			AccessRule[] rules = new AccessRule[length];
285
			AccessRule[] rules = new AccessRule[length];
Lines 489-495 Link Here
489
	/**
526
	/**
490
	 * Returns the XML encoding of the class path.
527
	 * Returns the XML encoding of the class path.
491
	 */
528
	 */
492
	public void elementEncode(XMLWriter writer, IPath projectPath, boolean indent, boolean newLine, Map unknownElements) {
529
	public void elementEncode(XMLWriter writer, IPath projectPath, boolean indent, boolean newLine, Map unknownElements, boolean isReferencedEntry) {
493
		HashMap parameters = new HashMap();
530
		HashMap parameters = new HashMap();
494
531
495
		parameters.put(TAG_KIND, ClasspathEntry.kindToString(this.entryKind));
532
		parameters.put(TAG_KIND, ClasspathEntry.kindToString(this.entryKind));
Lines 553-564 Link Here
553
		boolean hasRestrictions = getAccessRuleSet() != null; // access rule set is null if no access rules
590
		boolean hasRestrictions = getAccessRuleSet() != null; // access rule set is null if no access rules
554
		ArrayList unknownChildren = unknownXmlElements != null ? unknownXmlElements.children : null;
591
		ArrayList unknownChildren = unknownXmlElements != null ? unknownXmlElements.children : null;
555
		boolean hasUnknownChildren = unknownChildren != null;
592
		boolean hasUnknownChildren = unknownChildren != null;
593
		
594
		/* close tag if no extra attributes, no restriction and no unknown children */
595
		String tagName = isReferencedEntry ? TAG_REFERENCED_ENTRY : TAG_CLASSPATHENTRY; 
556
		writer.printTag(
596
		writer.printTag(
557
			TAG_CLASSPATHENTRY,
597
			tagName,
558
			parameters,
598
			parameters,
559
			indent,
599
			indent,
560
			newLine,
600
			newLine,
561
			!hasExtraAttributes && !hasRestrictions && !hasUnknownChildren/*close tag if no extra attributes, no restriction and no unknown children*/);
601
			!hasExtraAttributes && !hasRestrictions && !hasUnknownChildren);
562
602
563
		if (hasExtraAttributes)
603
		if (hasExtraAttributes)
564
			encodeExtraAttributes(writer, indent, newLine);
604
			encodeExtraAttributes(writer, indent, newLine);
Lines 570-576 Link Here
570
			encodeUnknownChildren(writer, indent, newLine, unknownChildren);
610
			encodeUnknownChildren(writer, indent, newLine, unknownChildren);
571
611
572
		if (hasExtraAttributes || hasRestrictions || hasUnknownChildren)
612
		if (hasExtraAttributes || hasRestrictions || hasUnknownChildren)
573
			writer.endTag(TAG_CLASSPATHENTRY, indent, true/*insert new line*/);
613
			writer.endTag(tagName, indent, true/*insert new line*/);
574
	}
614
	}
575
615
576
	void encodeExtraAttributes(XMLWriter writer, boolean indent, boolean newLine) {
616
	void encodeExtraAttributes(XMLWriter writer, boolean indent, boolean newLine) {
Lines 1178-1183 Link Here
1178
		return this.sourceAttachmentRootPath;
1218
		return this.sourceAttachmentRootPath;
1179
	}
1219
	}
1180
1220
1221
1222
	public IClasspathEntry getReferencingEntry() {
1223
		return this.referencingEntry;
1224
	}
1225
1181
	/**
1226
	/**
1182
	 * Returns the hash code for this classpath entry
1227
	 * Returns the hash code for this classpath entry
1183
	 */
1228
	 */
Lines 1380-1385 Link Here
1380
							getSourceAttachmentPath(),
1425
							getSourceAttachmentPath(),
1381
							getSourceAttachmentRootPath(),
1426
							getSourceAttachmentRootPath(),
1382
							getOutputLocation(),
1427
							getOutputLocation(),
1428
							this.getReferencingEntry(),
1383
							this.isExported,
1429
							this.isExported,
1384
							getAccessRules(),
1430
							getAccessRules(),
1385
							this.combineAccessRules,
1431
							this.combineAccessRules,
Lines 1397-1415 Link Here
1397
			return NO_ENTRIES;
1443
			return NO_ENTRIES;
1398
		ClasspathEntry[] result = new ClasspathEntry[length];
1444
		ClasspathEntry[] result = new ClasspathEntry[length];
1399
		for (int i = 0; i < length; i++) {
1445
		for (int i = 0; i < length; i++) {
1446
			// Chained(referenced) libraries can have their own attachment path. Hence, set them to null
1400
			result[i] = new ClasspathEntry(
1447
			result[i] = new ClasspathEntry(
1401
									getContentKind(),
1448
					getContentKind(),
1402
									getEntryKind(),
1449
					getEntryKind(),
1403
									paths[i],
1450
					paths[i],
1404
									this.inclusionPatterns,
1451
					this.inclusionPatterns,
1405
									this.exclusionPatterns,
1452
					this.exclusionPatterns,
1406
									getSourceAttachmentPath(),
1453
					null,
1407
									getSourceAttachmentRootPath(),
1454
					null,
1408
									getOutputLocation(),
1455
					getOutputLocation(),
1409
									this.isExported,
1456
					this,
1410
									getAccessRules(),
1457
					this.isExported,
1411
									this.combineAccessRules,
1458
					getAccessRules(),
1412
									this.extraAttributes);
1459
					this.combineAccessRules,
1460
					NO_EXTRA_ATTRIBUTES);
1413
		}
1461
		}
1414
		return result;
1462
		return result;
1415
	}
1463
	}
(-)model/org/eclipse/jdt/internal/core/JavaModelManager.java (-21 / +68 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2009 IBM Corporation and others.
2
 * Copyright (c) 2000, 2010 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 1095-1100 Link Here
1095
		public Object savedState;
1095
		public Object savedState;
1096
		public boolean triedRead;
1096
		public boolean triedRead;
1097
		public IClasspathEntry[] rawClasspath;
1097
		public IClasspathEntry[] rawClasspath;
1098
		public IClasspathEntry[] referencedEntries;
1098
		public IJavaModelStatus rawClasspathStatus;
1099
		public IJavaModelStatus rawClasspathStatus;
1099
		public int rawTimeStamp = 0;
1100
		public int rawTimeStamp = 0;
1100
		public boolean writtingRawClasspath = false;
1101
		public boolean writtingRawClasspath = false;
Lines 1169-1177 Link Here
1169
			return setResolvedClasspath(null, null, null, null, this.rawTimeStamp, true/*add classpath change*/);
1170
			return setResolvedClasspath(null, null, null, null, this.rawTimeStamp, true/*add classpath change*/);
1170
		}
1171
		}
1171
1172
1172
		private ClasspathChange setClasspath(IClasspathEntry[] newRawClasspath, IPath newOutputLocation, IJavaModelStatus newRawClasspathStatus, IClasspathEntry[] newResolvedClasspath, Map newRootPathToRawEntries, Map newRootPathToResolvedEntries, IJavaModelStatus newUnresolvedEntryStatus, boolean addClasspathChange) {
1173
		private ClasspathChange setClasspath(IClasspathEntry[] newRawClasspath, IClasspathEntry[] referencedEntries, IPath newOutputLocation, IJavaModelStatus newRawClasspathStatus, IClasspathEntry[] newResolvedClasspath, Map newRootPathToRawEntries, Map newRootPathToResolvedEntries, IJavaModelStatus newUnresolvedEntryStatus, boolean addClasspathChange) {
1173
			ClasspathChange classpathChange = addClasspathChange ? addClasspathChange() : null;
1174
			ClasspathChange classpathChange = addClasspathChange ? addClasspathChange() : null;
1174
1175
1176
			if (referencedEntries != null)	this.referencedEntries = referencedEntries;
1177
			if (this.referencedEntries == null) this.referencedEntries = ClasspathEntry.NO_ENTRIES;
1175
			this.rawClasspath = newRawClasspath;
1178
			this.rawClasspath = newRawClasspath;
1176
			this.outputLocation = newOutputLocation;
1179
			this.outputLocation = newOutputLocation;
1177
			this.rawClasspathStatus = newRawClasspathStatus;
1180
			this.rawClasspathStatus = newRawClasspathStatus;
Lines 1191-1222 Link Here
1191
			return classpathChange;
1194
			return classpathChange;
1192
		}
1195
		}
1193
1196
1194
		public synchronized ClasspathChange setRawClasspath(IClasspathEntry[] newRawClasspath, IPath newOutputLocation, IJavaModelStatus newRawClasspathStatus) {
1197
		public ClasspathChange setRawClasspath(IClasspathEntry[] newRawClasspath, IPath newOutputLocation, IJavaModelStatus newRawClasspathStatus) {
1198
			return setRawClasspath(newRawClasspath, null, newOutputLocation, newRawClasspathStatus);
1199
		}
1200
1201
		public synchronized ClasspathChange setRawClasspath(IClasspathEntry[] newRawClasspath, IClasspathEntry[] referencedEntries, IPath newOutputLocation, IJavaModelStatus newRawClasspathStatus) {
1195
			this.rawTimeStamp++;
1202
			this.rawTimeStamp++;
1196
			return setClasspath(newRawClasspath, newOutputLocation, newRawClasspathStatus, null/*resolved classpath*/, null/*root to raw map*/, null/*root to resolved map*/, null/*unresolved status*/, true/*add classpath change*/);
1203
			return setClasspath(newRawClasspath, referencedEntries, newOutputLocation, newRawClasspathStatus, null/*resolved classpath*/, null/*root to raw map*/, null/*root to resolved map*/, null/*unresolved status*/, true/*add classpath change*/);
1197
		}
1204
		}
1198
1205
1199
		public synchronized ClasspathChange setResolvedClasspath(IClasspathEntry[] newResolvedClasspath, Map newRootPathToRawEntries, Map newRootPathToResolvedEntries, IJavaModelStatus newUnresolvedEntryStatus, int timeStamp, boolean addClasspathChange) {
1206
		public ClasspathChange setResolvedClasspath(IClasspathEntry[] newResolvedClasspath, Map newRootPathToRawEntries, Map newRootPathToResolvedEntries, IJavaModelStatus newUnresolvedEntryStatus, int timeStamp, boolean addClasspathChange) {
1207
			return setResolvedClasspath(newResolvedClasspath, null, newRootPathToRawEntries, newRootPathToResolvedEntries, newUnresolvedEntryStatus, timeStamp, addClasspathChange);
1208
		}
1209
		
1210
		public synchronized ClasspathChange setResolvedClasspath(IClasspathEntry[] newResolvedClasspath, IClasspathEntry[] referencedEntries, Map newRootPathToRawEntries, Map newRootPathToResolvedEntries, IJavaModelStatus newUnresolvedEntryStatus, int timeStamp, boolean addClasspathChange) {
1200
			if (this.rawTimeStamp != timeStamp)
1211
			if (this.rawTimeStamp != timeStamp)
1201
				return null;
1212
				return null;
1202
			return setClasspath(this.rawClasspath, this.outputLocation, this.rawClasspathStatus, newResolvedClasspath, newRootPathToRawEntries, newRootPathToResolvedEntries, newUnresolvedEntryStatus, addClasspathChange);
1213
			return setClasspath(this.rawClasspath, referencedEntries, this.outputLocation, this.rawClasspathStatus, newResolvedClasspath, newRootPathToRawEntries, newRootPathToResolvedEntries, newUnresolvedEntryStatus, addClasspathChange);
1203
		}
1214
		}
1204
1215
1205
		public synchronized IClasspathEntry[] readAndCacheClasspath(JavaProject javaProject) {
1216
		public synchronized IClasspathEntry[][] readAndCacheClasspath(JavaProject javaProject) {
1206
			// read file entries and update status
1217
			// read file entries and update status
1207
			IClasspathEntry[] classpath;
1218
			IClasspathEntry[][] classpath;
1208
			IJavaModelStatus status;
1219
			IJavaModelStatus status;
1209
			try {
1220
			try {
1210
				classpath = javaProject.readFileEntriesWithException(null/*not interested in unknown elements*/);
1221
				classpath = javaProject.readFileEntriesWithException(null/*not interested in unknown elements*/);
1211
				status = JavaModelStatus.VERIFIED_OK;
1222
				status = JavaModelStatus.VERIFIED_OK;
1212
			} catch (CoreException e) {
1223
			} catch (CoreException e) {
1213
				classpath = JavaProject.INVALID_CLASSPATH;
1224
				classpath = new IClasspathEntry[][]{JavaProject.INVALID_CLASSPATH, ClasspathEntry.NO_ENTRIES};
1214
				status =
1225
				status =
1215
					new JavaModelStatus(
1226
					new JavaModelStatus(
1216
						IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
1227
						IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
1217
						Messages.bind(Messages.classpath_cannotReadClasspathFile, javaProject.getElementName()));
1228
						Messages.bind(Messages.classpath_cannotReadClasspathFile, javaProject.getElementName()));
1218
			} catch (IOException e) {
1229
			} catch (IOException e) {
1219
				classpath = JavaProject.INVALID_CLASSPATH;
1230
				classpath = new IClasspathEntry[][]{JavaProject.INVALID_CLASSPATH, ClasspathEntry.NO_ENTRIES};
1220
				if (Messages.file_badFormat.equals(e.getMessage()))
1231
				if (Messages.file_badFormat.equals(e.getMessage()))
1221
					status =
1232
					status =
1222
						new JavaModelStatus(
1233
						new JavaModelStatus(
Lines 1228-1234 Link Here
1228
							IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
1239
							IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
1229
							Messages.bind(Messages.classpath_cannotReadClasspathFile, javaProject.getElementName()));
1240
							Messages.bind(Messages.classpath_cannotReadClasspathFile, javaProject.getElementName()));
1230
			} catch (ClasspathEntry.AssertionFailedException e) {
1241
			} catch (ClasspathEntry.AssertionFailedException e) {
1231
				classpath = JavaProject.INVALID_CLASSPATH;
1242
				classpath = new IClasspathEntry[][]{JavaProject.INVALID_CLASSPATH, ClasspathEntry.NO_ENTRIES};
1232
				status =
1243
				status =
1233
					new JavaModelStatus(
1244
					new JavaModelStatus(
1234
						IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
1245
						IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
Lines 1236-1254 Link Here
1236
			}
1247
			}
1237
1248
1238
			// extract out the output location
1249
			// extract out the output location
1250
			int rawClasspathLength = classpath[0].length;
1239
			IPath output = null;
1251
			IPath output = null;
1240
			if (classpath.length > 0) {
1252
			if (rawClasspathLength > 0) {
1241
				IClasspathEntry entry = classpath[classpath.length - 1];
1253
				IClasspathEntry entry = classpath[0][rawClasspathLength - 1];
1242
				if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
1254
				if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
1243
					output = entry.getPath();
1255
					output = entry.getPath();
1244
					IClasspathEntry[] copy = new IClasspathEntry[classpath.length - 1];
1256
					IClasspathEntry[] copy = new IClasspathEntry[rawClasspathLength - 1];
1245
					System.arraycopy(classpath, 0, copy, 0, copy.length);
1257
					System.arraycopy(classpath[0], 0, copy, 0, copy.length);
1246
					classpath = copy;
1258
					classpath[0] = copy;
1247
				}
1259
				}
1248
			}
1260
			}
1249
1261
1250
			// store new raw classpath, new output and new status, and null out resolved info
1262
			// store new raw classpath, new output and new status, and null out resolved info
1251
			setRawClasspath(classpath, output, status);
1263
			setRawClasspath(classpath[0], classpath[1], output, status);
1252
1264
1253
			return classpath;
1265
			return classpath;
1254
		}
1266
		}
Lines 1292-1311 Link Here
1292
			return buffer.toString();
1304
			return buffer.toString();
1293
		}
1305
		}
1294
1306
1295
		public boolean writeAndCacheClasspath(JavaProject javaProject, final IClasspathEntry[] newRawClasspath, final IPath newOutputLocation) throws JavaModelException {
1307
		public boolean writeAndCacheClasspath(
1308
				JavaProject javaProject, 
1309
				final IClasspathEntry[] newRawClasspath, 
1310
				IClasspathEntry[] newReferencedEntries,
1311
				final IPath newOutputLocation) throws JavaModelException {
1296
			try {
1312
			try {
1297
				this.writtingRawClasspath = true;
1313
				this.writtingRawClasspath = true;
1314
				if (newReferencedEntries == null) newReferencedEntries = this.referencedEntries;
1315
				
1298
				// write .classpath
1316
				// write .classpath
1299
				if (!javaProject.writeFileEntries(newRawClasspath, newOutputLocation)) {
1317
				if (!javaProject.writeFileEntries(newRawClasspath, newReferencedEntries,  newOutputLocation)) {
1300
					return false;
1318
					return false;
1301
				}
1319
				}
1302
				// store new raw classpath, new output and new status, and null out resolved info
1320
				// store new raw classpath, new output and new status, and null out resolved info
1303
				setRawClasspath(newRawClasspath, newOutputLocation, JavaModelStatus.VERIFIED_OK);
1321
				setRawClasspath(newRawClasspath, newReferencedEntries, newOutputLocation, JavaModelStatus.VERIFIED_OK);
1304
			} finally {
1322
			} finally {
1305
				this.writtingRawClasspath = false;
1323
				this.writtingRawClasspath = false;
1306
			}
1324
			}
1307
			return true;
1325
			return true;
1308
		}
1326
		}
1327
		
1328
		public boolean writeAndCacheClasspath(JavaProject javaProject, final IClasspathEntry[] newRawClasspath, final IPath newOutputLocation) throws JavaModelException {
1329
			return writeAndCacheClasspath(javaProject, newRawClasspath, null, newOutputLocation);
1330
		}
1331
1309
	}
1332
	}
1310
1333
1311
	public static class PerWorkingCopyInfo implements IProblemRequestor {
1334
	public static class PerWorkingCopyInfo implements IProblemRequestor {
Lines 1819-1824 Link Here
1819
		return container;
1842
		return container;
1820
	}
1843
	}
1821
1844
1845
	public IClasspathEntry[] getReferencedClasspathEntries(IClasspathEntry libraryEntry, IJavaProject project) {
1846
		
1847
		IClasspathEntry[] referencedEntries = ((ClasspathEntry)libraryEntry).resolvedChainedLibraries();
1848
		PerProjectInfo perProjectInfo = getPerProjectInfo(project.getProject(), false);
1849
		
1850
		if(perProjectInfo == null) 
1851
			return referencedEntries;
1852
		
1853
		List pathToReferencedEntries = new ArrayList(referencedEntries.length);
1854
		for (int index = 0; index < referencedEntries.length; index++) {
1855
1856
			if (pathToReferencedEntries.contains(referencedEntries[index].getPath()))
1857
				continue;
1858
1859
			IClasspathEntry persistedEntry = null;
1860
			if ((persistedEntry = (IClasspathEntry)perProjectInfo.rootPathToResolvedEntries.get(referencedEntries[index].getPath())) != null) {
1861
				// TODO: reconsider this - may want to copy the values instead of reference assignment?
1862
				referencedEntries[index] = persistedEntry;
1863
			}
1864
			pathToReferencedEntries.add(referencedEntries[index].getPath());
1865
		}
1866
		return referencedEntries;
1867
	}
1868
	
1822
	public DeltaProcessor getDeltaProcessor() {
1869
	public DeltaProcessor getDeltaProcessor() {
1823
		return this.deltaState.getDeltaProcessor();
1870
		return this.deltaState.getDeltaProcessor();
1824
	}
1871
	}
Lines 3488-3494 Link Here
3488
		} else {
3535
		} else {
3489
			IClasspathEntry[] entries;
3536
			IClasspathEntry[] entries;
3490
			try {
3537
			try {
3491
				entries = ((JavaProject) project).decodeClasspath(containerString, null/*not interested in unknown elements*/);
3538
				entries = ((JavaProject) project).decodeClasspath(containerString, null/*not interested in unknown elements*/)[0];
3492
			} catch (IOException e) {
3539
			} catch (IOException e) {
3493
				Util.log(e, "Could not recreate persisted container: \n" + containerString); //$NON-NLS-1$
3540
				Util.log(e, "Could not recreate persisted container: \n" + containerString); //$NON-NLS-1$
3494
				entries = JavaProject.INVALID_CLASSPATH;
3541
				entries = JavaProject.INVALID_CLASSPATH;
(-)model/org/eclipse/jdt/internal/core/JavaProject.java (-68 / +203 lines)
Lines 18-23 Link Here
18
import java.util.Hashtable;
18
import java.util.Hashtable;
19
import java.util.Iterator;
19
import java.util.Iterator;
20
import java.util.LinkedHashSet;
20
import java.util.LinkedHashSet;
21
import java.util.List;
21
import java.util.Map;
22
import java.util.Map;
22
23
23
import javax.xml.parsers.DocumentBuilder;
24
import javax.xml.parsers.DocumentBuilder;
Lines 45-50 Link Here
45
import org.eclipse.core.runtime.content.IContentDescription;
46
import org.eclipse.core.runtime.content.IContentDescription;
46
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
47
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
47
import org.eclipse.core.runtime.preferences.IScopeContext;
48
import org.eclipse.core.runtime.preferences.IScopeContext;
49
import org.eclipse.jdt.core.IClasspathAttribute;
48
import org.eclipse.jdt.core.IClasspathContainer;
50
import org.eclipse.jdt.core.IClasspathContainer;
49
import org.eclipse.jdt.core.IClasspathEntry;
51
import org.eclipse.jdt.core.IClasspathEntry;
50
import org.eclipse.jdt.core.ICompilationUnit;
52
import org.eclipse.jdt.core.ICompilationUnit;
Lines 260-265 Link Here
260
			return false;
262
			return false;
261
		return true;
263
		return true;
262
	}
264
	}
265
	
266
	private static boolean areClasspathEqual(IClasspathEntry[] first, IClasspathEntry[] second) {
267
		if (first != second){
268
		    if (first == null) return false;
269
			int length = first.length;
270
			if (second == null || second.length != length)
271
				return false;
272
			for (int i = 0; i < length; i++) {
273
				if (!first[i].equals(second[i]))
274
					return false;
275
			}
276
		}
277
		return true;
278
	}
263
279
264
	/**
280
	/**
265
	 * Returns a canonicalized path from the given external path.
281
	 * Returns a canonicalized path from the given external path.
Lines 848-854 Link Here
848
	/*
864
	/*
849
	 * Reads and decode an XML classpath string
865
	 * Reads and decode an XML classpath string
850
	 */
866
	 */
851
	public IClasspathEntry[] decodeClasspath(String xmlClasspath, Map unknownElements) throws IOException, ClasspathEntry.AssertionFailedException {
867
	public IClasspathEntry[][] decodeClasspath(String xmlClasspath, Map unknownElements) throws IOException, ClasspathEntry.AssertionFailedException {
852
868
853
		ArrayList paths = new ArrayList();
869
		ArrayList paths = new ArrayList();
854
		IClasspathEntry defaultOutput = null;
870
		IClasspathEntry defaultOutput = null;
Lines 868-874 Link Here
868
		if (!cpElement.getNodeName().equalsIgnoreCase("classpath")) { //$NON-NLS-1$
884
		if (!cpElement.getNodeName().equalsIgnoreCase("classpath")) { //$NON-NLS-1$
869
			throw new IOException(Messages.file_badFormat);
885
			throw new IOException(Messages.file_badFormat);
870
		}
886
		}
871
		NodeList list = cpElement.getElementsByTagName("classpathentry"); //$NON-NLS-1$
887
		NodeList list = cpElement.getElementsByTagName(ClasspathEntry.TAG_CLASSPATHENTRY);
872
		int length = list.getLength();
888
		int length = list.getLength();
873
889
874
		for (int i = 0; i < length; ++i) {
890
		for (int i = 0; i < length; ++i) {
Lines 880-894 Link Here
880
						defaultOutput = entry; // separate output
896
						defaultOutput = entry; // separate output
881
					} else {
897
					} else {
882
						paths.add(entry);
898
						paths.add(entry);
899
					}
900
				}
883
			}
901
			}
884
		}
902
		}
903
		int pathSize = paths.size();
904
		IClasspathEntry[][] entries = new IClasspathEntry[2][];
905
		entries[0] = new IClasspathEntry[pathSize + (defaultOutput == null ? 0 : 1)];
906
		paths.toArray(entries[0]);
907
		if (defaultOutput != null) entries[0][pathSize] = defaultOutput; // ensure output is last item
908
		
909
		paths.clear();
910
		list = cpElement.getElementsByTagName(ClasspathEntry.TAG_REFERENCED_ENTRY);
911
		length = list.getLength();
912
913
		for (int i = 0; i < length; ++i) {
914
			Node node = list.item(i);
915
			if (node.getNodeType() == Node.ELEMENT_NODE) {
916
				IClasspathEntry entry = ClasspathEntry.elementDecode((Element)node, this, unknownElements);
917
				if (entry != null){
918
					paths.add(entry);
919
				}
885
			}
920
			}
886
		}
921
		}
887
		// return a new empty classpath is it size is 0, to differenciate from an INVALID_CLASSPATH
922
		entries[1] = new IClasspathEntry[paths.size()];
888
		int pathSize = paths.size();
923
		paths.toArray(entries[1]);
889
		IClasspathEntry[] entries = new IClasspathEntry[pathSize + (defaultOutput == null ? 0 : 1)];
924
890
		paths.toArray(entries);
891
		if (defaultOutput != null) entries[pathSize] = defaultOutput; // ensure output is last item
892
		return entries;
925
		return entries;
893
	}
926
	}
894
927
Lines 911-917 Link Here
911
				reader.close();
944
				reader.close();
912
			}
945
			}
913
946
914
			if (!node.getNodeName().equalsIgnoreCase("classpathentry") //$NON-NLS-1$
947
			if (!node.getNodeName().equalsIgnoreCase(ClasspathEntry.TAG_CLASSPATHENTRY)
915
					|| node.getNodeType() != Node.ELEMENT_NODE) {
948
					|| node.getNodeType() != Node.ELEMENT_NODE) {
916
				return null;
949
				return null;
917
			}
950
			}
Lines 956-962 Link Here
956
	/**
989
	/**
957
	 * Returns the XML String encoding of the class path.
990
	 * Returns the XML String encoding of the class path.
958
	 */
991
	 */
959
	protected String encodeClasspath(IClasspathEntry[] classpath, IPath outputLocation, boolean indent, Map unknownElements) throws JavaModelException {
992
	protected String encodeClasspath(IClasspathEntry[] classpath, IClasspathEntry[] referencedEntries, IPath outputLocation, boolean indent, Map unknownElements) throws JavaModelException {
960
		try {
993
		try {
961
			ByteArrayOutputStream s = new ByteArrayOutputStream();
994
			ByteArrayOutputStream s = new ByteArrayOutputStream();
962
			OutputStreamWriter writer = new OutputStreamWriter(s, "UTF8"); //$NON-NLS-1$
995
			OutputStreamWriter writer = new OutputStreamWriter(s, "UTF8"); //$NON-NLS-1$
Lines 964-970 Link Here
964
997
965
			xmlWriter.startTag(ClasspathEntry.TAG_CLASSPATH, indent);
998
			xmlWriter.startTag(ClasspathEntry.TAG_CLASSPATH, indent);
966
			for (int i = 0; i < classpath.length; ++i) {
999
			for (int i = 0; i < classpath.length; ++i) {
967
				((ClasspathEntry)classpath[i]).elementEncode(xmlWriter, this.project.getFullPath(), indent, true, unknownElements);
1000
				((ClasspathEntry)classpath[i]).elementEncode(xmlWriter, this.project.getFullPath(), indent, true, unknownElements, false);
968
			}
1001
			}
969
1002
970
			if (outputLocation != null) {
1003
			if (outputLocation != null) {
Lines 976-981 Link Here
976
				xmlWriter.printTag(ClasspathEntry.TAG_CLASSPATHENTRY, parameters, indent, true, true);
1009
				xmlWriter.printTag(ClasspathEntry.TAG_CLASSPATHENTRY, parameters, indent, true, true);
977
			}
1010
			}
978
1011
1012
			if (referencedEntries != null) {
1013
				for (int i = 0; i < referencedEntries.length; ++i) {
1014
					((ClasspathEntry) referencedEntries[i]).elementEncode(xmlWriter, this.project.getFullPath(), indent, true, unknownElements, true);
1015
				}
1016
			}
1017
			
979
			xmlWriter.endTag(ClasspathEntry.TAG_CLASSPATH, indent, true/*insert new line*/);
1018
			xmlWriter.endTag(ClasspathEntry.TAG_CLASSPATH, indent, true/*insert new line*/);
980
			writer.flush();
1019
			writer.flush();
981
			writer.close();
1020
			writer.close();
Lines 991-997 Link Here
991
			OutputStreamWriter writer = new OutputStreamWriter(s, "UTF8"); //$NON-NLS-1$
1030
			OutputStreamWriter writer = new OutputStreamWriter(s, "UTF8"); //$NON-NLS-1$
992
			XMLWriter xmlWriter = new XMLWriter(writer, this, false/*don't print XML version*/);
1031
			XMLWriter xmlWriter = new XMLWriter(writer, this, false/*don't print XML version*/);
993
1032
994
			((ClasspathEntry)classpathEntry).elementEncode(xmlWriter, this.project.getFullPath(), true/*indent*/, true/*insert new line*/, null/*not interested in unknown elements*/);
1033
			((ClasspathEntry)classpathEntry).elementEncode(xmlWriter, this.project.getFullPath(), true/*indent*/, true/*insert new line*/, null/*not interested in unknown elements*/, (classpathEntry.getReferencingEntry() != null));
995
1034
996
			writer.flush();
1035
			writer.flush();
997
			writer.close();
1036
			writer.close();
Lines 1841-1847 Link Here
1841
		IClasspathEntry[] classpath = perProjectInfo.rawClasspath;
1880
		IClasspathEntry[] classpath = perProjectInfo.rawClasspath;
1842
		if (classpath != null) return classpath;
1881
		if (classpath != null) return classpath;
1843
1882
1844
		classpath = perProjectInfo.readAndCacheClasspath(this);
1883
		classpath = perProjectInfo.readAndCacheClasspath(this)[0];
1845
1884
1846
		if (classpath == JavaProject.INVALID_CLASSPATH)
1885
		if (classpath == JavaProject.INVALID_CLASSPATH)
1847
			return defaultClasspath();
1886
			return defaultClasspath();
Lines 1850-1855 Link Here
1850
	}
1889
	}
1851
1890
1852
	/**
1891
	/**
1892
	 * @see IJavaProject
1893
	 */
1894
	public IClasspathEntry[] getReferencedClasspathEntries() throws JavaModelException {
1895
		return getPerProjectInfo().referencedEntries;
1896
	}
1897
	
1898
	/**
1853
	 * @see IJavaProject#getRequiredProjectNames()
1899
	 * @see IJavaProject#getRequiredProjectNames()
1854
	 */
1900
	 */
1855
	public String[] getRequiredProjectNames() throws JavaModelException {
1901
	public String[] getRequiredProjectNames() throws JavaModelException {
Lines 2384-2390 Link Here
2384
	 * As a side effect, unknown elements are stored in the given map (if not null)
2430
	 * As a side effect, unknown elements are stored in the given map (if not null)
2385
	 * Throws exceptions if the file cannot be accessed or is malformed.
2431
	 * Throws exceptions if the file cannot be accessed or is malformed.
2386
	 */
2432
	 */
2387
	public IClasspathEntry[] readFileEntriesWithException(Map unknownElements) throws CoreException, IOException, ClasspathEntry.AssertionFailedException {
2433
	public IClasspathEntry[][] readFileEntriesWithException(Map unknownElements) throws CoreException, IOException, ClasspathEntry.AssertionFailedException {
2388
		IFile rscFile = this.project.getFile(JavaProject.CLASSPATH_FILENAME);
2434
		IFile rscFile = this.project.getFile(JavaProject.CLASSPATH_FILENAME);
2389
		byte[] bytes;
2435
		byte[] bytes;
2390
		if (rscFile.exists()) {
2436
		if (rscFile.exists()) {
Lines 2403-2409 Link Here
2403
				bytes = org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(file);
2449
				bytes = org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(file);
2404
			} catch (IOException e) {
2450
			} catch (IOException e) {
2405
				if (!file.exists())
2451
				if (!file.exists())
2406
					return defaultClasspath();
2452
					return new IClasspathEntry[][]{defaultClasspath(), ClasspathEntry.NO_ENTRIES};
2407
				throw e;
2453
				throw e;
2408
			}
2454
			}
2409
		}
2455
		}
Lines 2427-2444 Link Here
2427
	 * This includes the output entry.
2473
	 * This includes the output entry.
2428
	 * As a side effect, unknown elements are stored in the given map (if not null)
2474
	 * As a side effect, unknown elements are stored in the given map (if not null)
2429
	 */
2475
	 */
2430
	private IClasspathEntry[] readFileEntries(Map unkwownElements) {
2476
	private IClasspathEntry[][] readFileEntries(Map unkwownElements) {
2431
		try {
2477
		try {
2432
			return readFileEntriesWithException(unkwownElements);
2478
			return readFileEntriesWithException(unkwownElements);
2433
		} catch (CoreException e) {
2479
		} catch (CoreException e) {
2434
			Util.log(e, "Exception while reading " + getPath().append(JavaProject.CLASSPATH_FILENAME)); //$NON-NLS-1$
2480
			Util.log(e, "Exception while reading " + getPath().append(JavaProject.CLASSPATH_FILENAME)); //$NON-NLS-1$
2435
			return JavaProject.INVALID_CLASSPATH;
2481
			return new IClasspathEntry[][]{JavaProject.INVALID_CLASSPATH, ClasspathEntry.NO_ENTRIES};
2436
		} catch (IOException e) {
2482
		} catch (IOException e) {
2437
			Util.log(e, "Exception while reading " + getPath().append(JavaProject.CLASSPATH_FILENAME)); //$NON-NLS-1$
2483
			Util.log(e, "Exception while reading " + getPath().append(JavaProject.CLASSPATH_FILENAME)); //$NON-NLS-1$
2438
			return JavaProject.INVALID_CLASSPATH;
2484
			return new IClasspathEntry[][]{JavaProject.INVALID_CLASSPATH, ClasspathEntry.NO_ENTRIES};
2439
		} catch (ClasspathEntry.AssertionFailedException e) {
2485
		} catch (ClasspathEntry.AssertionFailedException e) {
2440
			Util.log(e, "Exception while reading " + getPath().append(JavaProject.CLASSPATH_FILENAME)); //$NON-NLS-1$
2486
			Util.log(e, "Exception while reading " + getPath().append(JavaProject.CLASSPATH_FILENAME)); //$NON-NLS-1$
2441
			return JavaProject.INVALID_CLASSPATH;
2487
			return new IClasspathEntry[][]{JavaProject.INVALID_CLASSPATH, ClasspathEntry.NO_ENTRIES};
2442
		}
2488
		}
2443
	}
2489
	}
2444
2490
Lines 2447-2460 Link Here
2447
	 */
2493
	 */
2448
	public IPath readOutputLocation() {
2494
	public IPath readOutputLocation() {
2449
		// Read classpath file without creating markers nor logging problems
2495
		// Read classpath file without creating markers nor logging problems
2450
		IClasspathEntry[] classpath = readFileEntries(null/*not interested in unknown elements*/);
2496
		IClasspathEntry[][] classpath = readFileEntries(null/*not interested in unknown elements*/);
2451
		if (classpath == JavaProject.INVALID_CLASSPATH)
2497
		if (classpath[0] == JavaProject.INVALID_CLASSPATH)
2452
			return defaultOutputLocation();
2498
			return defaultOutputLocation();
2453
2499
2454
		// extract the output location
2500
		// extract the output location
2455
		IPath outputLocation = null;
2501
		IPath outputLocation = null;
2456
		if (classpath.length > 0) {
2502
		if (classpath[0].length > 0) {
2457
			IClasspathEntry entry = classpath[classpath.length - 1];
2503
			IClasspathEntry entry = classpath[0][classpath[0].length - 1];
2458
			if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
2504
			if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
2459
				outputLocation = entry.getPath();
2505
				outputLocation = entry.getPath();
2460
			}
2506
			}
Lines 2467-2486 Link Here
2467
	 */
2513
	 */
2468
	public IClasspathEntry[] readRawClasspath() {
2514
	public IClasspathEntry[] readRawClasspath() {
2469
		// Read classpath file without creating markers nor logging problems
2515
		// Read classpath file without creating markers nor logging problems
2470
		IClasspathEntry[] classpath = readFileEntries(null/*not interested in unknown elements*/);
2516
		IClasspathEntry[][] classpath = readFileEntries(null/*not interested in unknown elements*/);
2471
		if (classpath == JavaProject.INVALID_CLASSPATH)
2517
		if (classpath[0] == JavaProject.INVALID_CLASSPATH)
2472
			return defaultClasspath();
2518
			return defaultClasspath();
2473
2519
2474
		// discard the output location
2520
		// discard the output location
2475
		if (classpath.length > 0) {
2521
		if (classpath[0].length > 0) {
2476
			IClasspathEntry entry = classpath[classpath.length - 1];
2522
			IClasspathEntry entry = classpath[0][classpath[0].length - 1];
2477
			if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
2523
			if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
2478
				IClasspathEntry[] copy = new IClasspathEntry[classpath.length - 1];
2524
				IClasspathEntry[] copy = new IClasspathEntry[classpath[0].length - 1];
2479
				System.arraycopy(classpath, 0, copy, 0, copy.length);
2525
				System.arraycopy(classpath[0], 0, copy, 0, copy.length);
2480
				classpath = copy;
2526
				classpath[0] = copy;
2481
			}
2527
			}
2482
		}
2528
		}
2483
		return classpath;
2529
		return classpath[0];
2484
	}
2530
	}
2485
2531
2486
	/**
2532
	/**
Lines 2533-2546 Link Here
2533
		IJavaModelStatus unresolvedEntryStatus = JavaModelStatus.VERIFIED_OK;
2579
		IJavaModelStatus unresolvedEntryStatus = JavaModelStatus.VERIFIED_OK;
2534
		HashMap rawReverseMap = new HashMap();
2580
		HashMap rawReverseMap = new HashMap();
2535
		Map rootPathToResolvedEntries = new HashMap();
2581
		Map rootPathToResolvedEntries = new HashMap();
2582
		IClasspathEntry[] referencedEntries = null;
2536
	}
2583
	}
2537
	
2584
	
2538
	public ResolvedClasspath resolveClasspath(IClasspathEntry[] rawClasspath, boolean usePreviousSession, boolean resolveChainedLibraries) throws JavaModelException {
2585
	public ResolvedClasspath resolveClasspath(IClasspathEntry[] rawClasspath, boolean usePreviousSession, boolean resolveChainedLibraries) throws JavaModelException {
2586
		return resolveClasspath(rawClasspath, null, usePreviousSession, resolveChainedLibraries);
2587
	}
2588
2589
	public ResolvedClasspath resolveClasspath(IClasspathEntry[] rawClasspath, IClasspathEntry[] referencedEntries, boolean usePreviousSession, boolean resolveChainedLibraries) throws JavaModelException {
2539
		JavaModelManager manager = JavaModelManager.getJavaModelManager();
2590
		JavaModelManager manager = JavaModelManager.getJavaModelManager();
2540
		ExternalFoldersManager externalFoldersManager = JavaModelManager.getExternalManager();
2591
		ExternalFoldersManager externalFoldersManager = JavaModelManager.getExternalManager();
2541
		ResolvedClasspath result = new ResolvedClasspath();
2592
		ResolvedClasspath result = new ResolvedClasspath();
2542
2593
2594
		Map referencedEntriesMap = new HashMap();
2595
		List rawLibrariesPath = new ArrayList();
2543
		LinkedHashSet resolvedEntries = new LinkedHashSet();
2596
		LinkedHashSet resolvedEntries = new LinkedHashSet();
2597
		
2598
		if(resolveChainedLibraries) {
2599
			for (int index = 0; index < rawClasspath.length; index++) {
2600
				IClasspathEntry currentEntry = rawClasspath[index]; 
2601
				if (currentEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
2602
					rawLibrariesPath.add(ClasspathEntry.resolveDotDot(currentEntry.getPath()));
2603
				}
2604
			}
2605
			if (referencedEntries != null) {
2606
				// The Set is required to keep the order intact while the referencedEntriesMap (Map)
2607
				// is used to map the referenced entries with path
2608
				LinkedHashSet referencedEntriesSet = new LinkedHashSet();
2609
				for (int index = 0; index < referencedEntries.length; index++) {
2610
					IPath path = referencedEntries[index].getPath();
2611
					if (!rawLibrariesPath.contains(path) && referencedEntriesMap.get(path) == null) {
2612
						referencedEntriesMap.put(path, referencedEntries[index]);
2613
						referencedEntriesSet.add(referencedEntries[index]);
2614
					}
2615
				}
2616
				result.referencedEntries = new IClasspathEntry[referencedEntriesSet.size()];
2617
				referencedEntriesSet.toArray(result.referencedEntries);
2618
			}
2619
		}
2620
		
2544
		int length = rawClasspath.length;
2621
		int length = rawClasspath.length;
2545
		for (int i = 0; i < length; i++) {
2622
		for (int i = 0; i < length; i++) {
2546
2623
Lines 2561-2574 Link Here
2561
					if (resolvedEntry == null) {
2638
					if (resolvedEntry == null) {
2562
						result.unresolvedEntryStatus = new JavaModelStatus(IJavaModelStatusConstants.CP_VARIABLE_PATH_UNBOUND, this, rawEntry.getPath());
2639
						result.unresolvedEntryStatus = new JavaModelStatus(IJavaModelStatusConstants.CP_VARIABLE_PATH_UNBOUND, this, rawEntry.getPath());
2563
					} else {
2640
					} else {
2564
						if (resolveChainedLibraries && resolvedEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
2641
						// If the entry is already present in the rawReversetMap, it means the entry and the chained libraries
2642
						// have already been processed. So, skip it.
2643
						if (resolveChainedLibraries && resolvedEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY
2644
													&& result.rawReverseMap.get(resolvedEntry.getPath()) == null) {
2565
							// resolve Class-Path: in manifest
2645
							// resolve Class-Path: in manifest
2566
							ClasspathEntry[] extraEntries = ((ClasspathEntry) resolvedEntry).resolvedChainedLibraries();
2646
							ClasspathEntry[] extraEntries = ((ClasspathEntry) resolvedEntry).resolvedChainedLibraries();
2567
							for (int j = 0, length2 = extraEntries.length; j < length2; j++) {
2647
							for (int j = 0, length2 = extraEntries.length; j < length2; j++) {
2568
								addToResult(rawEntry, extraEntries[j], result, resolvedEntries, externalFoldersManager);
2648
								if (!rawLibrariesPath.contains(extraEntries[j].getPath())) {
2649
									addToResult(rawEntry, extraEntries[j], result, resolvedEntries, externalFoldersManager, referencedEntriesMap, true);
2650
								}
2569
							}
2651
							}
2570
						}
2652
						}
2571
						addToResult(rawEntry, resolvedEntry, result, resolvedEntries, externalFoldersManager);
2653
						addToResult(rawEntry, resolvedEntry, result, resolvedEntries, externalFoldersManager, referencedEntriesMap, false);
2572
					}
2654
					}
2573
					break;
2655
					break;
2574
2656
Lines 2603-2617 Link Here
2603
							// resolve ".." in library path
2685
							// resolve ".." in library path
2604
							cEntry = cEntry.resolvedDotDot();
2686
							cEntry = cEntry.resolvedDotDot();
2605
							
2687
							
2606
							if (resolveChainedLibraries) {
2688
							if (resolveChainedLibraries && result.rawReverseMap.get(cEntry.getPath()) == null) {
2607
								// resolve Class-Path: in manifest
2689
								// resolve Class-Path: in manifest
2608
								ClasspathEntry[] extraEntries = cEntry.resolvedChainedLibraries();
2690
								ClasspathEntry[] extraEntries = cEntry.resolvedChainedLibraries();
2609
								for (int k = 0, length2 = extraEntries.length; k < length2; k++) {
2691
								for (int k = 0, length2 = extraEntries.length; k < length2; k++) {
2610
									addToResult(rawEntry, extraEntries[k], result, resolvedEntries, externalFoldersManager);
2692
									if (!rawLibrariesPath.contains(extraEntries[k].getPath())) {
2693
										addToResult(rawEntry, extraEntries[k], result, resolvedEntries, externalFoldersManager, referencedEntriesMap, true);
2694
									}
2611
								}
2695
								}
2612
							}
2696
							}
2613
						}
2697
						}
2614
						addToResult(rawEntry, cEntry, result, resolvedEntries, externalFoldersManager);
2698
						addToResult(rawEntry, cEntry, result, resolvedEntries, externalFoldersManager, referencedEntriesMap, false);
2615
					}
2699
					}
2616
					break;
2700
					break;
2617
2701
Lines 2619-2636 Link Here
2619
					// resolve ".." in library path
2703
					// resolve ".." in library path
2620
					resolvedEntry = ((ClasspathEntry) rawEntry).resolvedDotDot();
2704
					resolvedEntry = ((ClasspathEntry) rawEntry).resolvedDotDot();
2621
					
2705
					
2622
					if (resolveChainedLibraries) {
2706
					if (resolveChainedLibraries && result.rawReverseMap.get(resolvedEntry.getPath()) == null) {
2623
						// resolve Class-Path: in manifest
2707
						// resolve Class-Path: in manifest
2624
						ClasspathEntry[] extraEntries = ((ClasspathEntry) resolvedEntry).resolvedChainedLibraries();
2708
						ClasspathEntry[] extraEntries = ((ClasspathEntry) resolvedEntry).resolvedChainedLibraries();
2625
						for (int k = 0, length2 = extraEntries.length; k < length2; k++) {
2709
						for (int k = 0, length2 = extraEntries.length; k < length2; k++) {
2626
							addToResult(rawEntry, extraEntries[k], result, resolvedEntries, externalFoldersManager);
2710
							if (!rawLibrariesPath.contains(extraEntries[k].getPath())) {
2711
								addToResult(rawEntry, extraEntries[k], result, resolvedEntries, externalFoldersManager, referencedEntriesMap, true);
2712
							}
2627
						}
2713
						}
2628
					}
2714
					}
2629
2715
2630
					addToResult(rawEntry, resolvedEntry, result, resolvedEntries, externalFoldersManager);
2716
					addToResult(rawEntry, resolvedEntry, result, resolvedEntries, externalFoldersManager, referencedEntriesMap, false);
2631
					break;
2717
					break;
2632
				default :
2718
				default :
2633
					addToResult(rawEntry, resolvedEntry, result, resolvedEntries, externalFoldersManager);
2719
					addToResult(rawEntry, resolvedEntry, result, resolvedEntries, externalFoldersManager, referencedEntriesMap, false);
2634
					break;
2720
					break;
2635
			}
2721
			}
2636
		}
2722
		}
Lines 2639-2656 Link Here
2639
		return result;
2725
		return result;
2640
	}
2726
	}
2641
2727
2642
	private void addToResult(IClasspathEntry rawEntry, IClasspathEntry resolvedEntry, ResolvedClasspath result, LinkedHashSet resolvedEntries, ExternalFoldersManager externalFoldersManager) {
2728
	private void addToResult(IClasspathEntry rawEntry, IClasspathEntry resolvedEntry, ResolvedClasspath result,
2729
			LinkedHashSet resolvedEntries, ExternalFoldersManager externalFoldersManager,
2730
			Map oldChainedEntriesMap, boolean addAsChainedEntry) {
2731
2643
		IPath resolvedPath;
2732
		IPath resolvedPath;
2733
		// If it's already been resolved, do not add to resolvedEntries or newChainedEntries lists
2644
		if (result.rawReverseMap.get(resolvedPath = resolvedEntry.getPath()) == null) {
2734
		if (result.rawReverseMap.get(resolvedPath = resolvedEntry.getPath()) == null) {
2645
			result.rawReverseMap.put(resolvedPath, rawEntry);
2735
			result.rawReverseMap.put(resolvedPath, rawEntry);
2646
			result.rootPathToResolvedEntries.put(resolvedPath, resolvedEntry);
2736
			result.rootPathToResolvedEntries.put(resolvedPath, resolvedEntry);
2647
			resolvedEntries.add(resolvedEntry);
2737
			resolvedEntries.add(resolvedEntry);
2738
			if (addAsChainedEntry) {
2739
				IClasspathEntry chainedEntry = null;
2740
				if (rawEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
2741
2742
					chainedEntry = (ClasspathEntry) oldChainedEntriesMap.get(resolvedPath);
2743
					if (chainedEntry != null) {
2744
						// This is required to keep the attributes if any added by the user in
2745
						// the previous session such as source attachment path etc.
2746
						copyFromOldChainedEntry((ClasspathEntry) resolvedEntry, (ClasspathEntry) chainedEntry);
2747
					}
2748
				}
2749
			}
2648
		}
2750
		}
2649
		if (resolvedEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY && ExternalFoldersManager.isExternalFolderPath(resolvedPath)) {
2751
		if (resolvedEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY && ExternalFoldersManager.isExternalFolderPath(resolvedPath)) {
2650
			externalFoldersManager.addFolder(resolvedPath); // no-op if not an external folder or if already registered
2752
			externalFoldersManager.addFolder(resolvedPath); // no-op if not an external folder or if already registered
2651
		}
2753
		}
2652
	}
2754
	}
2653
2755
2756
	private void copyFromOldChainedEntry(ClasspathEntry resolvedEntry, ClasspathEntry chainedEntry) {
2757
		IPath path = chainedEntry.getSourceAttachmentPath();
2758
		if ( path != null) {
2759
			resolvedEntry.sourceAttachmentPath = path;
2760
		}
2761
		path = chainedEntry.getSourceAttachmentRootPath();
2762
		if (path != null) {
2763
			resolvedEntry.sourceAttachmentRootPath = path;
2764
		}
2765
		IClasspathAttribute[] attributes = chainedEntry.getExtraAttributes();
2766
		if (attributes != null) {
2767
			resolvedEntry.extraAttributes = attributes;
2768
		}
2769
	}
2770
	
2654
	/*
2771
	/*
2655
	 * Resolve the given perProjectInfo's raw classpath and store the resolved classpath in the perProjectInfo.
2772
	 * Resolve the given perProjectInfo's raw classpath and store the resolved classpath in the perProjectInfo.
2656
	 */
2773
	 */
Lines 2665-2686 Link Here
2665
			}
2782
			}
2666
2783
2667
			// get raw info inside a synchronized block to ensure that it is consistent
2784
			// get raw info inside a synchronized block to ensure that it is consistent
2668
			IClasspathEntry[] rawClasspath;
2785
			IClasspathEntry[][] classpath = new IClasspathEntry[2][];
2669
			int timeStamp;
2786
			int timeStamp;
2670
			synchronized (perProjectInfo) {
2787
			synchronized (perProjectInfo) {
2671
				rawClasspath= perProjectInfo.rawClasspath;
2788
				classpath[0] = perProjectInfo.rawClasspath;
2672
				if (rawClasspath == null)
2789
				classpath[1] = perProjectInfo.referencedEntries;
2673
					rawClasspath = perProjectInfo.readAndCacheClasspath(this);
2790
				// Checking null only for rawClasspath enough
2791
				if (classpath[0] == null)
2792
					classpath = perProjectInfo.readAndCacheClasspath(this);
2674
				timeStamp = perProjectInfo.rawTimeStamp;
2793
				timeStamp = perProjectInfo.rawTimeStamp;
2675
			}
2794
			}
2676
			
2677
			ResolvedClasspath result = resolveClasspath(rawClasspath, usePreviousSession, true/*resolve chained libraries*/);
2678
2795
2796
			ResolvedClasspath result = resolveClasspath(classpath[0], classpath[1], usePreviousSession, true/*resolve chained libraries*/);
2797
			
2679
			if (CP_RESOLUTION_BP_LISTENERS != null)
2798
			if (CP_RESOLUTION_BP_LISTENERS != null)
2680
				breakpoint(2, this);
2799
				breakpoint(2, this);
2681
2800
2682
			// store resolved info along with the raw info to ensure consistency
2801
			// store resolved info along with the raw info to ensure consistency
2683
			perProjectInfo.setResolvedClasspath(result.resolvedClasspath, result.rawReverseMap, result.rootPathToResolvedEntries, usePreviousSession ? PerProjectInfo.NEED_RESOLUTION : result.unresolvedEntryStatus, timeStamp, addClasspathChange);
2802
			perProjectInfo.setResolvedClasspath(result.resolvedClasspath, result.referencedEntries, result.rawReverseMap, result.rootPathToResolvedEntries, usePreviousSession ? PerProjectInfo.NEED_RESOLUTION : result.unresolvedEntryStatus, timeStamp, addClasspathChange);
2684
		} finally {
2803
		} finally {
2685
			if (!isClasspathBeingResolved) {
2804
			if (!isClasspathBeingResolved) {
2686
				manager.setClasspathBeingResolved(this, false);
2805
				manager.setClasspathBeingResolved(this, false);
Lines 2708-2732 Link Here
2708
	 * @return boolean Return whether the .classpath file was modified.
2827
	 * @return boolean Return whether the .classpath file was modified.
2709
	 * @throws JavaModelException
2828
	 * @throws JavaModelException
2710
	 */
2829
	 */
2711
	public boolean writeFileEntries(IClasspathEntry[] newClasspath, IPath newOutputLocation) throws JavaModelException {
2830
	public boolean writeFileEntries(IClasspathEntry[] newClasspath, IClasspathEntry[] referencedEntries, IPath newOutputLocation) throws JavaModelException {
2712
2831
2713
		if (!this.project.isAccessible()) return false;
2832
		if (!this.project.isAccessible()) return false;
2714
2833
2715
		Map unknownElements = new HashMap();
2834
		Map unknownElements = new HashMap();
2716
		IClasspathEntry[] fileEntries = readFileEntries(unknownElements);
2835
		IClasspathEntry[][] fileEntries = readFileEntries(unknownElements);
2717
		if (fileEntries != JavaProject.INVALID_CLASSPATH && areClasspathsEqual(newClasspath, newOutputLocation, fileEntries)) {
2836
		if (fileEntries[0] != JavaProject.INVALID_CLASSPATH && 
2837
				areClasspathsEqual(newClasspath, newOutputLocation, fileEntries[0])
2838
				&& areClasspathEqual(referencedEntries, fileEntries[1])) {
2718
			// no need to save it, it is the same
2839
			// no need to save it, it is the same
2719
			return false;
2840
			return false;
2720
		}
2841
		}
2721
2842
2722
		// actual file saving
2843
		// actual file saving
2723
		try {
2844
		try {
2724
			setSharedProperty(JavaProject.CLASSPATH_FILENAME, encodeClasspath(newClasspath, newOutputLocation, true, unknownElements));
2845
			setSharedProperty(JavaProject.CLASSPATH_FILENAME, encodeClasspath(newClasspath, referencedEntries, newOutputLocation, true, unknownElements));
2725
			return true;
2846
			return true;
2726
		} catch (CoreException e) {
2847
		} catch (CoreException e) {
2727
			throw new JavaModelException(e);
2848
			throw new JavaModelException(e);
2728
		}
2849
		}
2729
	}
2850
	}
2851
	public boolean writeFileEntries(IClasspathEntry[] newClasspath, IPath newOutputLocation) throws JavaModelException {
2852
		return writeFileEntries(newClasspath, ClasspathEntry.NO_ENTRIES, newOutputLocation);
2853
	}
2730
2854
2731
	/**
2855
	/**
2732
	 * Update the Java command in the build spec (replace existing one if present,
2856
	 * Update the Java command in the build spec (replace existing one if present,
Lines 2874-2895 Link Here
2874
			boolean canModifyResources,
2998
			boolean canModifyResources,
2875
			IProgressMonitor monitor)
2999
			IProgressMonitor monitor)
2876
			throws JavaModelException {
3000
			throws JavaModelException {
2877
3001
		setRawClasspath(newRawClasspath, null, newOutputLocation, canModifyResources, monitor);
2878
		try {
2879
			if (newRawClasspath == null) //are we already with the default classpath
2880
				newRawClasspath = defaultClasspath();
2881
2882
			SetClasspathOperation op =
2883
				new SetClasspathOperation(
2884
					this,
2885
					newRawClasspath,
2886
					newOutputLocation,
2887
					canModifyResources);
2888
			op.runOperation(monitor);
2889
		} catch (JavaModelException e) {
2890
			JavaModelManager.getJavaModelManager().getDeltaProcessor().flush();
2891
			throw e;
2892
		}
2893
	}
3002
	}
2894
3003
2895
	/**
3004
	/**
Lines 2907-2912 Link Here
2907
			true/*can change resource (as per API contract)*/,
3016
			true/*can change resource (as per API contract)*/,
2908
			monitor);
3017
			monitor);
2909
	}
3018
	}
3019
	
3020
	public void setRawClasspath(IClasspathEntry[] entries, IClasspathEntry[] referencedEntries, IPath outputLocation,
3021
			IProgressMonitor monitor) throws JavaModelException {
3022
		setRawClasspath(entries, referencedEntries, outputLocation, true, monitor);
3023
	}
3024
	
3025
	protected void setRawClasspath(IClasspathEntry[] newRawClasspath, IClasspathEntry[] referencedEntries, IPath newOutputLocation,
3026
			boolean canModifyResources,	IProgressMonitor monitor) throws JavaModelException {
3027
3028
		try {
3029
			if (newRawClasspath == null) //are we already with the default classpath
3030
				newRawClasspath = defaultClasspath();
3031
3032
			SetClasspathOperation op =
3033
				new SetClasspathOperation(
3034
					this,
3035
					newRawClasspath,
3036
					referencedEntries,
3037
					newOutputLocation,
3038
					canModifyResources);
3039
			op.runOperation(monitor);
3040
		} catch (JavaModelException e) {
3041
			JavaModelManager.getJavaModelManager().getDeltaProcessor().flush();
3042
			throw e;
3043
		}
3044
	}
2910
3045
2911
	/**
3046
	/**
2912
	 * @see IJavaProject
3047
	 * @see IJavaProject
(-)model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java (-1 / +17 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2008 IBM Corporation and others.
2
 * Copyright (c) 2000, 2010 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 554-559 Link Here
554
	}
554
	}
555
	return rawEntry;
555
	return rawEntry;
556
}
556
}
557
/*
558
 * @see IPackageFragmentRoot
559
 */
560
public IClasspathEntry getResolvedClasspathEntry() throws JavaModelException {
561
	IClasspathEntry resolvedEntry = null;
562
	JavaProject project = (JavaProject)getJavaProject();
563
	project.getResolvedClasspath(); // force the reverse rawEntry cache to be populated
564
	Map rootPathToResolvedEntries = project.getPerProjectInfo().rootPathToResolvedEntries;
565
	if (rootPathToResolvedEntries != null) {
566
		resolvedEntry = (IClasspathEntry) rootPathToResolvedEntries.get(getPath());
567
	}
568
	if (resolvedEntry == null) {
569
		throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_NOT_ON_CLASSPATH, this));
570
	}
571
	return resolvedEntry;
572
}
557
573
558
574
559
public IResource resource() {
575
public IResource resource() {
(-)model/org/eclipse/jdt/internal/core/SetClasspathOperation.java (-2 / +14 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2008 IBM Corporation and others.
2
 * Copyright (c) 2000, 2010 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 30-50 Link Here
30
public class SetClasspathOperation extends ChangeClasspathOperation {
30
public class SetClasspathOperation extends ChangeClasspathOperation {
31
31
32
	IClasspathEntry[] newRawClasspath;
32
	IClasspathEntry[] newRawClasspath;
33
	IClasspathEntry[] referencedEntries;
33
	IPath newOutputLocation;
34
	IPath newOutputLocation;
34
	JavaProject project;
35
	JavaProject project;
35
36
37
	public SetClasspathOperation(
38
		JavaProject project,
39
		IClasspathEntry[] newRawClasspath,
40
		IPath newOutputLocation,
41
		boolean canChangeResource) {
42
43
		this(project, newRawClasspath, null, newOutputLocation, canChangeResource);
44
	}
45
	
36
	/**
46
	/**
37
	 * When executed, this operation sets the raw classpath and output location of the given project.
47
	 * When executed, this operation sets the raw classpath and output location of the given project.
38
	 */
48
	 */
39
	public SetClasspathOperation(
49
	public SetClasspathOperation(
40
		JavaProject project,
50
		JavaProject project,
41
		IClasspathEntry[] newRawClasspath,
51
		IClasspathEntry[] newRawClasspath,
52
		IClasspathEntry[] referencedEntries,
42
		IPath newOutputLocation,
53
		IPath newOutputLocation,
43
		boolean canChangeResource) {
54
		boolean canChangeResource) {
44
55
45
		super(new IJavaElement[] { project }, canChangeResource);
56
		super(new IJavaElement[] { project }, canChangeResource);
46
		this.project = project;
57
		this.project = project;
47
		this.newRawClasspath = newRawClasspath;
58
		this.newRawClasspath = newRawClasspath;
59
		this.referencedEntries = referencedEntries;
48
		this.newOutputLocation = newOutputLocation;
60
		this.newOutputLocation = newOutputLocation;
49
	}
61
	}
50
62
Lines 56-62 Link Here
56
		try {
68
		try {
57
			// set raw classpath and null out resolved info
69
			// set raw classpath and null out resolved info
58
			PerProjectInfo perProjectInfo = this.project.getPerProjectInfo();
70
			PerProjectInfo perProjectInfo = this.project.getPerProjectInfo();
59
			ClasspathChange classpathChange = perProjectInfo.setRawClasspath(this.newRawClasspath, this.newOutputLocation, JavaModelStatus.VERIFIED_OK/*format is ok*/);
71
			ClasspathChange classpathChange = perProjectInfo.setRawClasspath(this.newRawClasspath, this.referencedEntries, this.newOutputLocation, JavaModelStatus.VERIFIED_OK/*format is ok*/);
60
72
61
			// if needed, generate delta, update project ref, create markers, ...
73
			// if needed, generate delta, update project ref, create markers, ...
62
			classpathChanged(classpathChange);
74
			classpathChanged(classpathChange);
(-)src/org/eclipse/jdt/core/tests/model/ClasspathTests.java (-2 / +313 lines)
Lines 88-95 Link Here
88
// All specified tests which do not belong to the class are skipped...
88
// All specified tests which do not belong to the class are skipped...
89
static {
89
static {
90
	// Names of tests to run: can be "testBugXXXX" or "BugXXXX")
90
	// Names of tests to run: can be "testBugXXXX" or "BugXXXX")
91
//	TESTS_PREFIX = "testClasspathDuplicateExtraAttribute";
91
//	TESTS_PREFIX = "testBug252341c";
92
//	TESTS_NAMES = new String[] {"testClasspathValidation42"};
92
//	TESTS_NAMES = new String[] {"testClasspathWithNonExistentLibraryEntry"};
93
//	TESTS_NUMBERS = new int[] { 23, 28, 38 };
93
//	TESTS_NUMBERS = new int[] { 23, 28, 38 };
94
//	TESTS_RANGE = new int[] { 21, 38 };
94
//	TESTS_RANGE = new int[] { 21, 38 };
95
}
95
}
Lines 6116-6120 Link Here
6116
		deleteExternalResource("lib.jar");
6116
		deleteExternalResource("lib.jar");
6117
	}
6117
	}
6118
}
6118
}
6119
/**
6120
 * @bug 252431:New API is needed to better identify referenced jars in the Class-Path: entry
6121
 * Test that 1) referenced libraries are added to the resolved classpath in the right order
6122
 * 			 2) referenced libraries are added to the appropriate referencing library in the correct order
6123
 * 			 3) referenced libraries and top-level libraries retain the source attachment and source attachment root path
6124
 * 			 4) referenced libraries point to the correct entry as their referencingEntry. 
6125
 * 			 5) referenced libraries and their attributes are persisted in the .classpath file
6126
 * 
6127
 * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=252431"
6128
 * @throws Exception
6129
 */ 
6130
public void testBug252341a() throws Exception {
6131
	try {
6132
		IJavaProject p = createJavaProject("P");
6133
		addLibrary(p, "lib1.jar", "abc.zip", new String[0], 
6134
			new String[] {
6135
				"META-INF/MANIFEST.MF",
6136
				"Manifest-Version: 1.0\n" +
6137
				"Class-Path: lib2.jar lib3.jar\n",
6138
			},
6139
			JavaCore.VERSION_1_4);
6140
		createFile("/P/lib2.jar", "");
6141
		createFile("/P/lib3.jar", "");
6142
		
6143
		// Test referenced entries are included in the right order in the resolved classpath
6144
		IClasspathEntry[] resolvedClasspath = p.getResolvedClasspath(true);
6145
		assertClasspathEquals(resolvedClasspath, 
6146
				"/P[CPE_SOURCE][K_SOURCE][isExported:false]\n" + 
6147
				""+ getExternalJCLPathString() + "[CPE_LIBRARY][K_BINARY][isExported:false]\n" + 
6148
				"/P/lib2.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" + 
6149
				"/P/lib3.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" + 
6150
				"/P/lib1.jar[CPE_LIBRARY][K_BINARY][sourcePath:/P/abc.zip][isExported:true]");
6151
		
6152
		IClasspathEntry[] rawClasspath = p.getRawClasspath();
6153
		assertClasspathEquals(rawClasspath,
6154
				"/P[CPE_SOURCE][K_SOURCE][isExported:false]\n" + 
6155
				"JCL_LIB[CPE_VARIABLE][K_SOURCE][isExported:false]\n" + 
6156
				"/P/lib1.jar[CPE_LIBRARY][K_BINARY][sourcePath:/P/abc.zip][isExported:true]");
6157
6158
		// Test referenced entries for a particular entry appear in the right order and the referencingEntry
6159
		// attribute has the correct value
6160
		IClasspathEntry[] chains = JavaCore.getReferencedClasspathEntries(rawClasspath[2], p);
6161
		assertClasspathEquals(chains, 
6162
				"/P/lib2.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" + 
6163
				"/P/lib3.jar[CPE_LIBRARY][K_BINARY][isExported:true]");
6164
6165
		assertSame("Referencing Entry", rawClasspath[2], chains[0].getReferencingEntry());
6166
		assertSame("Referencing Entry", rawClasspath[2], chains[1].getReferencingEntry());
6167
		
6168
		// Test a newly created library entry with similar attributes but without any referencing entry is equal to 
6169
		// the original referenced entry
6170
		IClasspathEntry tempLibEntry = JavaCore.newLibraryEntry(chains[0].getPath(), chains[0].getSourceAttachmentPath(), chains[0].getSourceAttachmentRootPath(), true);
6171
		assertEquals("Library Entry", tempLibEntry, chains[0]);
6172
		
6173
		// Test the source attachment and other attributes added to the referenced entries are stored and retrieved properly
6174
		assertEquals("source attachment", resolvedClasspath[4].getSourceAttachmentPath().toPortableString(), "/P/abc.zip");
6175
		assertNull("source attachment", chains[0].getSourceAttachmentPath());
6176
		assertNull("source attachment", chains[1].getSourceAttachmentPath());
6177
		assertNull("source attachment root", chains[0].getSourceAttachmentRootPath());
6178
		assertNull("source attachment root", chains[1].getSourceAttachmentRootPath());
6179
6180
		((ClasspathEntry)chains[0]).sourceAttachmentPath = new Path("/P/efg.zip");
6181
		((ClasspathEntry)chains[1]).sourceAttachmentPath = new Path("/P/xyz.zip");
6182
		((ClasspathEntry)chains[0]).sourceAttachmentRootPath = new Path("/src2");
6183
		((ClasspathEntry)chains[1]).sourceAttachmentRootPath = new Path("/src3");
6184
6185
		IClasspathAttribute javadocLoc = JavaCore.newClasspathAttribute("javadoc_location", "/P/efg.zip");
6186
		((ClasspathEntry)chains[0]).extraAttributes = new IClasspathAttribute[]{javadocLoc};
6187
		
6188
		p.setRawClasspath(rawClasspath, chains, p.getOutputLocation(), null);
6189
		
6190
		// Test the .classpath file contains all the referenced entries and their attributes
6191
		String contents = new String (org.eclipse.jdt.internal.core.util.Util.getResourceContentsAsCharArray(getFile("/P/.classpath")));
6192
		assertSourceEquals(
6193
			"Unexpected content",
6194
			"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + 
6195
			"<classpath>\n" + 
6196
			"	<classpathentry kind=\"src\" path=\"\"/>\n" + 
6197
			"	<classpathentry kind=\"var\" path=\"JCL_LIB\"/>\n" + 
6198
			"	<classpathentry exported=\"true\" kind=\"lib\" path=\"lib1.jar\" sourcepath=\"abc.zip\"/>\n" + 
6199
			"	<classpathentry kind=\"output\" path=\"\"/>\n" + 
6200
			"	<referencedentry exported=\"true\" kind=\"lib\" path=\"lib2.jar\" rootpath=\"/src2\" sourcepath=\"efg.zip\">\n" + 
6201
			"		<attributes>\n" + 
6202
			"			<attribute name=\"javadoc_location\" value=\"/P/efg.zip\"/>\n" + 
6203
			"		</attributes>\n" + 
6204
			"	</referencedentry>\n" + 
6205
			"	<referencedentry exported=\"true\" kind=\"lib\" path=\"lib3.jar\" rootpath=\"/src3\" sourcepath=\"xyz.zip\"/>\n" + 
6206
			"</classpath>\n",
6207
			contents);
6208
		
6209
		p.close();
6210
		p.open(null);
6211
		rawClasspath = p.getRawClasspath();
6212
		resolvedClasspath = p.getResolvedClasspath(true);
6213
6214
		assertClasspathEquals(rawClasspath,
6215
				"/P[CPE_SOURCE][K_SOURCE][isExported:false]\n" + 
6216
				"JCL_LIB[CPE_VARIABLE][K_SOURCE][isExported:false]\n" + 
6217
				"/P/lib1.jar[CPE_LIBRARY][K_BINARY][sourcePath:/P/abc.zip][isExported:true]");
6218
6219
		assertClasspathEquals(resolvedClasspath, 
6220
				"/P[CPE_SOURCE][K_SOURCE][isExported:false]\n" + 
6221
				""+ getExternalJCLPathString() + "[CPE_LIBRARY][K_BINARY][isExported:false]\n" + 
6222
				"/P/lib2.jar[CPE_LIBRARY][K_BINARY][sourcePath:/P/efg.zip][rootPath:/src2][isExported:true][attributes:javadoc_location=/P/efg.zip]\n" + 
6223
				"/P/lib3.jar[CPE_LIBRARY][K_BINARY][sourcePath:/P/xyz.zip][rootPath:/src3][isExported:true]\n" + 
6224
				"/P/lib1.jar[CPE_LIBRARY][K_BINARY][sourcePath:/P/abc.zip][isExported:true]");
6225
		
6226
	} finally {
6227
		deleteProject("P");
6228
	}
6229
}
6230
/**
6231
 * Additional tests for bug 252431.
6232
 * When multiple libraries have one or more common referenced library in their MANIFEST
6233
 * 1) The common referenced libries are added to the first library entry in the raw classpath
6234
 * 2) Removing one of the top-level library from the raw classpath doesn't remove the referenced
6235
 *    entry that was commonly referenced by another entry and the referenced entry's source
6236
 *    attachment and other attributes are retained.
6237
 * 3) Passing a NULL referencedEntries array retains the referenced entries
6238
 * 4) Passing an empty array as referencedEntries clears the earlier referenced entries 
6239
 * 
6240
 * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=252431"
6241
 * @throws Exception
6242
 */
6243
public void testBug252341b() throws Exception {
6244
	try {
6245
		IJavaProject p = createJavaProject("P");
6246
		addLibrary(p, "lib1.jar", null, new String[0], 
6247
			new String[] {
6248
				"META-INF/MANIFEST.MF",
6249
				"Manifest-Version: 1.0\n" +
6250
				"Class-Path: lib3.jar lib4.jar\n",
6251
			},
6252
			JavaCore.VERSION_1_4);
6253
		
6254
		addLibrary(p, "lib2.jar", null, new String[0], 
6255
				new String[] {
6256
					"META-INF/MANIFEST.MF",
6257
					"Manifest-Version: 1.0\n" +
6258
					"Class-Path: lib3.jar lib5.jar\n",
6259
				},
6260
				JavaCore.VERSION_1_4);
6261
		createFile("/P/lib3.jar", "");
6262
		createFile("/P/lib4.jar", "");
6263
		createFile("/P/lib5.jar", "");
6264
		
6265
		// Test that the referenced entries are not included in the raw classpath
6266
		IClasspathEntry[] rawClasspath = p.getRawClasspath();
6267
		assertClasspathEquals(
6268
				rawClasspath,
6269
				"/P[CPE_SOURCE][K_SOURCE][isExported:false]\n" + 
6270
				"JCL_LIB[CPE_VARIABLE][K_SOURCE][isExported:false]\n" + 
6271
				"/P/lib1.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" + 
6272
				"/P/lib2.jar[CPE_LIBRARY][K_BINARY][isExported:true]");
6273
6274
		IClasspathEntry[] rawEntries = new IClasspathEntry[2];
6275
		rawEntries[0] = JavaCore.newLibraryEntry(new Path("/P/lib1.jar"), null, null, true);
6276
		rawEntries[1] = JavaCore.newLibraryEntry(new Path("/P/lib2.jar"), null, null, true);
6277
		
6278
		// Test that the referenced entries are included in the raw classpath and in the right order
6279
		IClasspathEntry[] resolvedClasspath = p.getResolvedClasspath(true);
6280
		assertClasspathEquals(resolvedClasspath, 
6281
				"/P[CPE_SOURCE][K_SOURCE][isExported:false]\n" + 
6282
				""+ getExternalJCLPathString() + "[CPE_LIBRARY][K_BINARY][isExported:false]\n" + 
6283
				"/P/lib3.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" + 
6284
				"/P/lib4.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" + 
6285
				"/P/lib1.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" + 
6286
				"/P/lib5.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" + 
6287
				"/P/lib2.jar[CPE_LIBRARY][K_BINARY][isExported:true]");
6288
6289
		// Test that the referenced classpath entries has the appropriate referencingEntry value
6290
		IClasspathEntry[] chains = JavaCore.getReferencedClasspathEntries(rawEntries[0], p); 
6291
		assertClasspathEquals(
6292
				chains, 
6293
				"/P/lib3.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" + 
6294
				"/P/lib4.jar[CPE_LIBRARY][K_BINARY][isExported:true]");
6295
		assertEquals("Referencing Entry" , rawEntries[0], chains[0].getReferencingEntry()); 
6296
		assertEquals("Referencing Entry" , rawEntries[0], chains[1].getReferencingEntry()); 
6297
6298
		chains = JavaCore.getReferencedClasspathEntries(rawEntries[1], p);
6299
		assertClasspathEquals(
6300
				chains, 
6301
				"/P/lib3.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" + 
6302
				"/P/lib5.jar[CPE_LIBRARY][K_BINARY][isExported:true]");
6303
		
6304
		assertEquals("Referencing Entry" , rawEntries[0], chains[0].getReferencingEntry());
6305
		assertEquals("Referencing Entry" , rawEntries[1], chains[1].getReferencingEntry());
6306
		
6307
//		// Test IPackageFragmentRoot#getResolvedClasspathEntry
6308
		IPackageFragmentRoot[] roots = p.getPackageFragmentRoots();
6309
		assertEquals("Package fragment root", roots[2].getResolvedClasspathEntry(), resolvedClasspath[2]);
6310
		assertEquals("Package fragment root", roots[3].getResolvedClasspathEntry(), resolvedClasspath[3]);
6311
		assertEquals("Package fragment root", roots[4].getResolvedClasspathEntry(), resolvedClasspath[4]);
6312
		assertEquals("Package fragment root", roots[5].getResolvedClasspathEntry(), resolvedClasspath[5]);
6313
		assertEquals("Package fragment root", roots[6].getResolvedClasspathEntry(), resolvedClasspath[6]);
6314
		
6315
		// Test the attributes added to the referenced classpath entries are stored and retrieved properly
6316
		((ClasspathEntry)chains[0]).sourceAttachmentPath = new Path("/P/efg.zip");
6317
		((ClasspathEntry)chains[1]).sourceAttachmentPath = new Path("/P/xyz.zip");
6318
		((ClasspathEntry)chains[0]).sourceAttachmentRootPath = new Path("/src2");
6319
		((ClasspathEntry)chains[1]).sourceAttachmentRootPath = new Path("/src3");
6320
6321
		IClasspathAttribute javadocLoc = JavaCore.newClasspathAttribute("javadoc_location", "/P/efg.zip");
6322
		((ClasspathEntry)chains[0]).extraAttributes = new IClasspathAttribute[]{javadocLoc};
6323
6324
		p.setRawClasspath(rawClasspath, chains, p.getOutputLocation(), null);
6325
		resolvedClasspath = p.getResolvedClasspath(true);
6326
		
6327
		assertClasspathEquals(resolvedClasspath,
6328
				"/P[CPE_SOURCE][K_SOURCE][isExported:false]\n" +
6329
				""+ getExternalJCLPathString() + "[CPE_LIBRARY][K_BINARY][isExported:false]\n" +
6330
				"/P/lib3.jar[CPE_LIBRARY][K_BINARY][sourcePath:/P/efg.zip][rootPath:/src2][isExported:true][attributes:javadoc_location=/P/efg.zip]\n" +
6331
				"/P/lib4.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" +
6332
				"/P/lib1.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" +
6333
				"/P/lib5.jar[CPE_LIBRARY][K_BINARY][sourcePath:/P/xyz.zip][rootPath:/src3][isExported:true]\n" +
6334
				"/P/lib2.jar[CPE_LIBRARY][K_BINARY][isExported:true]");
6335
		
6336
		// Test that removing any of the referencing entry from the raw classpath has the correct effect 
6337
		// on the resolved classpath. Also test passing referencedEntries = null retains the existing
6338
		// referenced entries
6339
		IClasspathEntry[] newRawClasspath = new IClasspathEntry[rawClasspath.length-1];
6340
		System.arraycopy(rawClasspath, 0, newRawClasspath, 0, 2);
6341
		System.arraycopy(rawClasspath, 3, newRawClasspath, 2, 1);
6342
		p.setRawClasspath(newRawClasspath, null, p.getOutputLocation(), null);
6343
		resolvedClasspath = p.getResolvedClasspath(true);
6344
		assertClasspathEquals(resolvedClasspath,
6345
				"/P[CPE_SOURCE][K_SOURCE][isExported:false]\n" +
6346
				""+ getExternalJCLPathString() + "[CPE_LIBRARY][K_BINARY][isExported:false]\n" +
6347
				"/P/lib3.jar[CPE_LIBRARY][K_BINARY][sourcePath:/P/efg.zip][rootPath:/src2][isExported:true][attributes:javadoc_location=/P/efg.zip]\n" +
6348
				"/P/lib5.jar[CPE_LIBRARY][K_BINARY][sourcePath:/P/xyz.zip][rootPath:/src3][isExported:true]\n" +
6349
				"/P/lib2.jar[CPE_LIBRARY][K_BINARY][isExported:true]");
6350
6351
		// Test that passing empty array of referencedEntries clears all the earlier ones. 
6352
		p.setRawClasspath(newRawClasspath, new IClasspathEntry[]{}, p.getOutputLocation(), null);
6353
		resolvedClasspath = p.getResolvedClasspath(true);
6354
		assertClasspathEquals(resolvedClasspath,
6355
				"/P[CPE_SOURCE][K_SOURCE][isExported:false]\n" +
6356
				""+ getExternalJCLPathString() + "[CPE_LIBRARY][K_BINARY][isExported:false]\n" +
6357
				"/P/lib3.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" +
6358
				"/P/lib5.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" +
6359
				"/P/lib2.jar[CPE_LIBRARY][K_BINARY][isExported:true]");
6360
6361
	} finally {
6362
		deleteProject("P");
6363
	}
6364
}
6365
/**
6366
 * Additional tests for bug 252431.
6367
 * Test that duplicate referenced entries or entries that are already present in the raw classpath
6368
 * are excluded from the referenced entries when invoking 
6369
 * {@link IJavaProject#setRawClasspath(IClasspathEntry[], IClasspathEntry[], IPath, IProgressMonitor)}
6370
 * 
6371
 * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=252431"
6372
 * @throws Exception
6373
 */
6374
public void testBug252341c() throws Exception {
6375
	try {
6376
		IJavaProject p = createJavaProject("P");
6377
		addLibrary(p, "lib1.jar", null, new String[0], 
6378
			new String[] {
6379
				"META-INF/MANIFEST.MF",
6380
				"Manifest-Version: 1.0\n" +
6381
				"Class-Path: lib3.jar lib4.jar\n",
6382
			},
6383
			JavaCore.VERSION_1_4);
6384
		
6385
		addLibrary(p, "lib2.jar", null, new String[0], 
6386
				new String[] {
6387
					"META-INF/MANIFEST.MF",
6388
					"Manifest-Version: 1.0\n" +
6389
					"Class-Path: lib3.jar lib5.jar\n",
6390
				},
6391
				JavaCore.VERSION_1_4);
6392
		createFile("/P/lib3.jar", "");
6393
		createFile("/P/lib4.jar", "");
6394
		createFile("/P/lib5.jar", "");
6395
		
6396
		IClasspathEntry[] rawClasspath = p.getRawClasspath();
6397
		
6398
		IClasspathEntry[] rawEntries = new IClasspathEntry[2];
6399
		rawEntries[0] = JavaCore.newLibraryEntry(new Path("/P/lib1.jar"), null, null, true);
6400
		rawEntries[1] = JavaCore.newLibraryEntry(new Path("/P/lib2.jar"), null, null, true);
6401
		
6402
		// Test that the referenced classpath entries has the appropriate referencingEntry value
6403
		IClasspathEntry[] chains = JavaCore.getReferencedClasspathEntries(rawEntries[0], p);
6404
6405
		IClasspathEntry[] referencedEntries = new IClasspathEntry[5];
6406
		referencedEntries[0] = chains[0]; 
6407
		referencedEntries[1] = chains[1]; 
6408
		
6409
		chains = JavaCore.getReferencedClasspathEntries(rawEntries[1], p);
6410
6411
		referencedEntries[2] = chains[0];
6412
		referencedEntries[3] = chains[1];
6413
		referencedEntries[4] = chains[1];
6414
		
6415
		p.setRawClasspath(rawClasspath, referencedEntries, p.getOutputLocation(), null);
6416
		
6417
		p.close();
6418
		p.open(null);
6419
		
6420
		IClasspathEntry[] storedReferencedEnties = p.getReferencedClasspathEntries();
6421
		assertClasspathEquals(storedReferencedEnties, 
6422
				"/P/lib3.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" + 
6423
				"/P/lib4.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" + 
6424
				"/P/lib5.jar[CPE_LIBRARY][K_BINARY][isExported:true]");
6425
	}
6426
	finally {
6427
		deleteProject("P");
6428
	}
6429
}
6119
6430
6120
}
6431
}

Return to bug 281551