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

Collapse All | Expand All

(-)src/org/eclipse/jdt/core/tests/model/ReconcilerTests.java (-1 / +2 lines)
Lines 309-318 Link Here
309
				"public class X {\n" +
309
				"public class X {\n" +
310
				"}",
310
				"}",
311
			},
311
			},
312
			null/*no non-Java resources*/,
312
			new String[] {
313
			new String[] {
313
				"**/*"
314
				"**/*"
314
			},
315
			},
315
			null,
316
			null, 
316
			"1.4"
317
			"1.4"
317
		);
318
		);
318
		createJavaProject("P2", new String[] {"src"}, new String[] {"JCL_LIB"}, new String[] {"/P1"}, "bin");
319
		createJavaProject("P2", new String[] {"src"}, new String[] {"JCL_LIB"}, new String[] {"/P1"}, "bin");
(-)src/org/eclipse/jdt/core/tests/model/ClasspathTests.java (+369 lines)
Lines 2970-2975 Link Here
2970
	}
2970
	}
2971
}
2971
}
2972
/*
2972
/*
2973
 * Ensures that the extra libraries in the Class-Path: clause of a jar are taken into account.
2974
 */
2975
public void testExtraLibraries01() throws Exception {
2976
	try {
2977
		IJavaProject p = createJavaProject("P");
2978
		addLibrary(p, "lib1.jar", null, new String[0], 
2979
			new String[] {
2980
				"META-INF/MANIFEST.MF",
2981
				"Manifest-Version: 1.0\n" +
2982
				"Class-Path: lib2.jar\n",
2983
			},
2984
			JavaCore.VERSION_1_4);
2985
		createFile("/P/lib2.jar", "");
2986
		assertClasspathEquals(
2987
			p.getResolvedClasspath(true), 
2988
			"/P[CPE_SOURCE][K_SOURCE][isExported:false]\n" + 
2989
			""+ getExternalJCLPathString() + "[CPE_LIBRARY][K_BINARY][isExported:false]\n" + 
2990
			"/P/lib2.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" + 
2991
			"/P/lib1.jar[CPE_LIBRARY][K_BINARY][isExported:true]"
2992
		);
2993
	} finally {
2994
		deleteProject("P");
2995
	}
2996
}
2997
/*
2998
 * Ensures that the extra libraries in the Class-Path: clause of a jar are taken into account.
2999
 */
3000
public void testExtraLibraries02() throws Exception {
3001
	try {
3002
		IJavaProject p = createJavaProject("P");
3003
		addLibrary(p, "lib1.jar", null, new String[0], 
3004
			new String[] {
3005
				"META-INF/MANIFEST.MF",
3006
				"Manifest-Version: 1.0\n" +
3007
				"Class-Path: lib2.jar lib3.jar\n",
3008
			},
3009
			JavaCore.VERSION_1_4);
3010
		createFile("/P/lib2.jar", "");
3011
		createFile("/P/lib3.jar", "");
3012
		assertClasspathEquals(
3013
			p.getResolvedClasspath(true), 
3014
			"/P[CPE_SOURCE][K_SOURCE][isExported:false]\n" + 
3015
			""+ getExternalJCLPathString() + "[CPE_LIBRARY][K_BINARY][isExported:false]\n" + 
3016
			"/P/lib2.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" + 
3017
			"/P/lib3.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" + 
3018
			"/P/lib1.jar[CPE_LIBRARY][K_BINARY][isExported:true]"
3019
		);
3020
	} finally {
3021
		deleteProject("P");
3022
	}
3023
}
3024
/*
3025
 * Ensures that the extra libraries in the Class-Path: clause of a jar are taken into account.
3026
 */
3027
public void testExtraLibraries03() throws Exception {
3028
	try {
3029
		IJavaProject p = createJavaProject("P");
3030
		createFile("/P/lib3.jar", "");
3031
		createLibrary(p, "lib2.jar", null, new String[0],
3032
			new String[] {
3033
				"META-INF/MANIFEST.MF",
3034
				"Manifest-Version: 1.0\n" +
3035
				"Class-Path: lib3.jar\n",
3036
			},
3037
			JavaCore.VERSION_1_4);
3038
		addLibrary(p, "lib1.jar", null, new String[0], 
3039
			new String[] {
3040
				"META-INF/MANIFEST.MF",
3041
				"Manifest-Version: 1.0\n" +
3042
				"Class-Path: lib2.jar\n",
3043
			},
3044
			JavaCore.VERSION_1_4);
3045
		assertClasspathEquals(
3046
			p.getResolvedClasspath(true), 
3047
			"/P[CPE_SOURCE][K_SOURCE][isExported:false]\n" + 
3048
			""+ getExternalJCLPathString() + "[CPE_LIBRARY][K_BINARY][isExported:false]\n" + 
3049
			"/P/lib3.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" + 
3050
			"/P/lib2.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" + 
3051
			"/P/lib1.jar[CPE_LIBRARY][K_BINARY][isExported:true]"
3052
		);
3053
	} finally {
3054
		deleteProject("P");
3055
	}
3056
}
3057
/*
3058
 * Ensures that the extra libraries in the Class-Path: clause of a jar are taken into account.
3059
 */
3060
public void testExtraLibraries04() throws Exception {
3061
	try {
3062
		IJavaProject p = createJavaProject("P");
3063
		addLibrary(p, "lib1.jar", null, new String[0], 
3064
			new String[] {
3065
				"META-INF/MANIFEST.MF",
3066
				"Manifest-Version: 1.0\n" +
3067
				"Class-Path: lib2.jar\n",
3068
			},
3069
			JavaCore.VERSION_1_4);
3070
		createLibrary(p, "lib2.jar", null, new String[0],
3071
			new String[] {
3072
				"META-INF/MANIFEST.MF",
3073
				"Manifest-Version: 1.0\n" +
3074
				"Class-Path: lib3.jar\n",
3075
			},
3076
			JavaCore.VERSION_1_4);
3077
		createFile("/P/lib3.jar", "");
3078
		assertClasspathEquals(
3079
			p.getResolvedClasspath(true), 
3080
			"/P[CPE_SOURCE][K_SOURCE][isExported:false]\n" + 
3081
			""+ getExternalJCLPathString() + "[CPE_LIBRARY][K_BINARY][isExported:false]\n" + 
3082
			"/P/lib3.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" + 
3083
			"/P/lib2.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" + 
3084
			"/P/lib1.jar[CPE_LIBRARY][K_BINARY][isExported:true]"
3085
		);
3086
	} finally {
3087
		deleteProject("P");
3088
	}
3089
}
3090
/*
3091
 * Ensures that no markers are created for correct extra libraries in the Class-Path: clause of a jar
3092
 */
3093
public void testExtraLibraries05() throws Exception {
3094
	try {
3095
		IJavaProject p = createJavaProject("P");
3096
		addLibrary(p, "lib1.jar", null, new String[0], 
3097
			new String[] {
3098
				"META-INF/MANIFEST.MF",
3099
				"Manifest-Version: 1.0\n" +
3100
				"Class-Path: lib2.jar\n",
3101
			},
3102
			JavaCore.VERSION_1_4);
3103
		createFile("/P/lib2.jar", "");
3104
		assertMarkers(
3105
			"Unexpected markers",
3106
			"",
3107
			p);
3108
	} finally {
3109
		deleteProject("P");
3110
	}
3111
}
3112
/*
3113
 * Ensures that a marker is created for incorrect extra libraries in the Class-Path: clause of a jar
3114
 */
3115
public void testExtraLibraries06() throws Exception {
3116
	try {
3117
		IJavaProject p = createJavaProject("P");
3118
		addLibrary(p, "lib1.jar", null, new String[0], 
3119
			new String[] {
3120
				"META-INF/MANIFEST.MF",
3121
				"Manifest-Version: 1.0\n" +
3122
				"Class-Path: lib2.jar\n",
3123
			},
3124
			JavaCore.VERSION_1_4);
3125
		assertMarkers(
3126
			"Unexpected markers",
3127
			"Project \'P\' is missing required library: \'lib2.jar\'",
3128
			p);
3129
	} finally {
3130
		deleteProject("P");
3131
	}
3132
}
3133
/*
3134
 * Ensures that the extra libraries in the Class-Path: clause of an external jar are taken into account.
3135
 */
3136
public void testExtraLibraries07() throws Exception {
3137
	try {
3138
		IJavaProject p = createJavaProject("P");
3139
		addExternalLibrary(p, getExternalResourcePath("lib1.jar"), new String[0], 
3140
			new String[] {
3141
				"META-INF/MANIFEST.MF",
3142
				"Manifest-Version: 1.0\n" +
3143
				"Class-Path: lib2.jar\n",
3144
			},
3145
			JavaCore.VERSION_1_4);
3146
		createExternalFile("lib2.jar", "");
3147
		assertClasspathEquals(
3148
			p.getResolvedClasspath(true), 
3149
			"/P[CPE_SOURCE][K_SOURCE][isExported:false]\n" + 
3150
			""+ getExternalJCLPathString() + "[CPE_LIBRARY][K_BINARY][isExported:false]\n" + 
3151
			""+ getExternalPath() + "lib2.jar[CPE_LIBRARY][K_BINARY][isExported:true]\n" + 
3152
			""+ getExternalPath() + "lib1.jar[CPE_LIBRARY][K_BINARY][isExported:true]"
3153
		);
3154
	} finally {
3155
		deleteProject("P");
3156
		deleteExternalResource("lib1.jar");
3157
		deleteExternalResource("lib2.jar");
3158
	}
3159
}
3160
/*
3161
 * Ensures that no markers are created for correct extra libraries in the Class-Path: clause of an external jar
3162
 */
3163
public void testExtraLibraries08() throws Exception {
3164
	try {
3165
		IJavaProject p = createJavaProject("P");
3166
		addExternalLibrary(p, getExternalResourcePath("lib1.jar"), new String[0], 
3167
			new String[] {
3168
				"META-INF/MANIFEST.MF",
3169
				"Manifest-Version: 1.0\n" +
3170
				"Class-Path: lib2.jar\n",
3171
			},
3172
			JavaCore.VERSION_1_4);
3173
		createExternalFile("lib2.jar", "");
3174
		refreshExternalArchives(p);
3175
		assertMarkers(
3176
			"Unexpected markers",
3177
			"",
3178
			p);
3179
	} finally {
3180
		deleteProject("P");
3181
		deleteExternalResource("lib1.jar");
3182
		deleteExternalResource("lib2.jar");
3183
	}
3184
}
3185
/*
3186
 * Ensures that a marker is created for incorrect extra libraries in the Class-Path: clause of an external jar
3187
 */
3188
public void testExtraLibraries09() throws Exception {
3189
	try {
3190
		IJavaProject p = createJavaProject("P");
3191
		addExternalLibrary(p, getExternalResourcePath("lib1.jar"), new String[0], 
3192
			new String[] {
3193
				"META-INF/MANIFEST.MF",
3194
				"Manifest-Version: 1.0\n" +
3195
				"Class-Path: lib2.jar\n",
3196
			},
3197
			JavaCore.VERSION_1_4);
3198
		assertMarkers(
3199
			"Unexpected markers",
3200
			"Project \'P\' is missing required library: \'"+ getExternalPath() + "lib2.jar\'",
3201
			p);
3202
	} finally {
3203
		deleteProject("P");
3204
		deleteExternalResource("lib1.jar");
3205
		deleteExternalResource("lib2.jar");
3206
	}
3207
}
3208
/*
3209
 * Ensures that a marker is created for incorrect extra libraries in the Class-Path: clause of an external jar
3210
 */
3211
public void testExtraLibraries10() throws Exception {
3212
	try {
3213
		IJavaProject p = createJavaProject("P");
3214
		addExternalLibrary(p, getExternalResourcePath("lib1.jar"), new String[0], 
3215
			new String[] {
3216
				"META-INF/MANIFEST.MF",
3217
				"Manifest-Version: 1.0\n" +
3218
				"Class-Path: lib2.jar\n",
3219
			},
3220
			JavaCore.VERSION_1_4);
3221
		createExternalFile("lib2.jar", "");
3222
		refreshExternalArchives(p);
3223
		waitForAutoBuild(); // wait until classpath is validated -> no markers
3224
		
3225
		deleteExternalResource("lib2.jar");
3226
		refreshExternalArchives(p);
3227
		assertMarkers(
3228
			"Unexpected markers",
3229
			"Project \'P\' is missing required library: \'"+ getExternalPath() + "lib2.jar\'",
3230
			p);
3231
	} finally {
3232
		deleteProject("P");
3233
		deleteExternalResource("lib1.jar");
3234
		deleteExternalResource("lib2.jar");
3235
	}
3236
}
3237
/*
3238
 * Ensures that the correct delta is reported when editing the Class-Path: clause of a jar
3239
 */
3240
public void testExtraLibraries11() throws Exception {
3241
	try {
3242
		IJavaProject p = createJavaProject("P");
3243
		addLibrary(p, "lib1.jar", null, new String[0], 
3244
			new String[] {
3245
				"META-INF/MANIFEST.MF",
3246
				"Manifest-Version: 1.0\n" +
3247
				"Class-Path: lib2.jar\n",
3248
			},
3249
			JavaCore.VERSION_1_4);
3250
		createFile("/P/lib2.jar", "");
3251
		startDeltas();
3252
		createLibrary(p, "lib1.jar", null, new String[0], 
3253
			new String[] {
3254
				"META-INF/MANIFEST.MF",
3255
				"Manifest-Version: 1.0\n" +
3256
				"Class-Path: lib3.jar\n",
3257
			},
3258
			JavaCore.VERSION_1_4);
3259
		assertDeltas(
3260
			"Unexpected delta",
3261
			"P[*]: {CHILDREN | RESOLVED CLASSPATH CHANGED}\n" + 
3262
			"	lib1.jar[*]: {CONTENT | ARCHIVE CONTENT CHANGED}\n" + 
3263
			"	lib2.jar[*]: {REMOVED FROM CLASSPATH}"
3264
		);
3265
	} finally {
3266
		stopDeltas();
3267
		deleteProject("P");
3268
	}
3269
}
3270
/*
3271
 * Ensures that the correct delta is reported when editing the Class-Path: clause of an external jar
3272
 */
3273
public void testExtraLibraries12() throws Exception {
3274
	try {
3275
		IJavaProject p = createJavaProject("P");
3276
		addExternalLibrary(p, getExternalResourcePath("lib1.jar"), new String[0], 
3277
			new String[] {
3278
				"META-INF/MANIFEST.MF",
3279
				"Manifest-Version: 1.0\n" +
3280
				"Class-Path: lib2.jar\n",
3281
			},
3282
			JavaCore.VERSION_1_4);
3283
		createExternalFile("lib2.jar", "");
3284
		refreshExternalArchives(p);
3285
		
3286
		startDeltas();
3287
		org.eclipse.jdt.core.tests.util.Util.createJar(new String[0],
3288
			new String[] {
3289
				"META-INF/MANIFEST.MF",
3290
				"Manifest-Version: 1.0\n" +
3291
				"Class-Path: lib3.jar\n",
3292
			},
3293
			getExternalResourcePath("lib1.jar"),
3294
			JavaCore.VERSION_1_4);
3295
		refreshExternalArchives(p);
3296
		assertDeltas(
3297
			"Unexpected delta",
3298
			"P[*]: {CHILDREN | RESOLVED CLASSPATH CHANGED}\n" + 
3299
			"	"+ getExternalPath() + "lib1.jar[*]: {CONTENT | ARCHIVE CONTENT CHANGED}\n" + 
3300
			"	"+ getExternalPath() + "lib2.jar[*]: {REMOVED FROM CLASSPATH}"
3301
		);
3302
	} finally {
3303
		stopDeltas();
3304
		deleteProject("P");
3305
		deleteExternalResource("lib1.jar");
3306
		deleteExternalResource("lib2.jar");
3307
	}
3308
}
3309
/*
3310
 * Ensures that the correct delta is reported when removing an external jar with a Class-Path: clause
3311
 */
3312
public void testExtraLibraries13() throws Exception {
3313
	try {
3314
		IJavaProject p = createJavaProject("P");
3315
		addExternalLibrary(p, getExternalResourcePath("lib1.jar"), new String[0], 
3316
			new String[] {
3317
				"META-INF/MANIFEST.MF",
3318
				"Manifest-Version: 1.0\n" +
3319
				"Class-Path: lib2.jar\n",
3320
			},
3321
			JavaCore.VERSION_1_4);
3322
		createExternalFile("lib2.jar", "");
3323
		refreshExternalArchives(p);
3324
		
3325
		startDeltas();
3326
		deleteExternalResource("lib1.jar");
3327
		refreshExternalArchives(p);
3328
		assertDeltas(
3329
			"Unexpected delta",
3330
			"P[*]: {CHILDREN | RESOLVED CLASSPATH CHANGED}\n" + 
3331
			"	"+ getExternalPath() + "lib1.jar[-]: {}\n" + 
3332
			"	"+ getExternalPath() + "lib2.jar[*]: {REMOVED FROM CLASSPATH}"
3333
		);
3334
	} finally {
3335
		stopDeltas();
3336
		deleteProject("P");
3337
		deleteExternalResource("lib1.jar");
3338
		deleteExternalResource("lib2.jar");
3339
	}
3340
}
3341
/*
2973
 * Ensures that a marker is removed if adding an internal jar that is on the classpath in another project
3342
 * Ensures that a marker is removed if adding an internal jar that is on the classpath in another project
2974
 * (regression test for https://bugs.eclipse.org/bugs/show_bug.cgi?id=213723 )
3343
 * (regression test for https://bugs.eclipse.org/bugs/show_bug.cgi?id=213723 )
2975
 */
3344
 */
(-)src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java (-12 / +26 lines)
Lines 391-421 Link Here
391
		);
391
		);
392
392
393
	}
393
	}
394
	protected void addExternalLibrary(IJavaProject javaProject, String jarPath, String[] pathAndContents, String[] nonJavaResources, String compliance) throws Exception {
395
		org.eclipse.jdt.core.tests.util.Util.createJar(pathAndContents, nonJavaResources, jarPath, compliance);
396
		addLibraryEntry(javaProject, new Path(jarPath), true/*exported*/);
397
	}
394
	protected void addLibrary(String jarName, String sourceZipName, String[] pathAndContents, String compliance) throws CoreException, IOException {
398
	protected void addLibrary(String jarName, String sourceZipName, String[] pathAndContents, String compliance) throws CoreException, IOException {
395
		addLibrary(this.currentProject, jarName, sourceZipName, pathAndContents, null, null, compliance);
399
		addLibrary(this.currentProject, jarName, sourceZipName, pathAndContents, null/*no non-Java resources*/, null, null, compliance);
396
	}
400
	}
397
	protected void addLibrary(IJavaProject javaProject, String jarName, String sourceZipName, String[] pathAndContents, String compliance) throws CoreException, IOException {
401
	protected void addLibrary(IJavaProject javaProject, String jarName, String sourceZipName, String[] pathAndContents, String compliance) throws CoreException, IOException {
398
		addLibrary(javaProject, jarName, sourceZipName, pathAndContents, null, null, compliance);
402
		addLibrary(javaProject, jarName, sourceZipName, pathAndContents, null/*no non-Java resources*/, null, null, compliance);
399
	}
403
	}
400
	protected void addLibrary(IJavaProject javaProject, String jarName, String sourceZipName, String[] pathAndContents, String[] librariesInclusionPatterns, String[] librariesExclusionPatterns, String compliance) throws CoreException, IOException {
404
	protected void addLibrary(IJavaProject javaProject, String jarName, String sourceZipName, String[] pathAndContents, String[] nonJavaResources, String compliance) throws CoreException, IOException {
401
		IProject project = javaProject.getProject();
405
		addLibrary(javaProject, jarName, sourceZipName, pathAndContents, nonJavaResources, null, null, compliance);
402
		String projectLocation = project.getLocation().toOSString();
406
	}
403
		String jarPath = projectLocation + File.separator + jarName;
407
	protected void addLibrary(IJavaProject javaProject, String jarName, String sourceZipName, String[] pathAndContents, String[] nonJavaResources, String[] librariesInclusionPatterns, String[] librariesExclusionPatterns, String compliance) throws CoreException, IOException {
404
		String sourceZipPath = projectLocation + File.separator + sourceZipName;
408
		IProject project = createLibrary(javaProject, jarName, sourceZipName, pathAndContents, nonJavaResources, compliance);
405
		org.eclipse.jdt.core.tests.util.Util.createJar(pathAndContents, jarPath, compliance);
406
		org.eclipse.jdt.core.tests.util.Util.createSourceZip(pathAndContents, sourceZipPath);
407
		project.refreshLocal(IResource.DEPTH_INFINITE, null);
408
		String projectPath = '/' + project.getName() + '/';
409
		String projectPath = '/' + project.getName() + '/';
409
		addLibraryEntry(
410
		addLibraryEntry(
410
			javaProject,
411
			javaProject,
411
			new Path(projectPath + jarName),
412
			new Path(projectPath + jarName),
412
			new Path(projectPath + sourceZipName),
413
			sourceZipName == null ? null : new Path(projectPath + sourceZipName),
413
			null,
414
			null,
414
			toIPathArray(librariesInclusionPatterns),
415
			toIPathArray(librariesInclusionPatterns),
415
			toIPathArray(librariesExclusionPatterns),
416
			toIPathArray(librariesExclusionPatterns),
416
			true
417
			true
417
		);
418
		);
418
	}
419
	}
420
421
	protected IProject createLibrary(IJavaProject javaProject, String jarName, String sourceZipName, String[] pathAndContents, String[] nonJavaResources, String compliance) throws IOException, CoreException {
422
		IProject project = javaProject.getProject();
423
		String projectLocation = project.getLocation().toOSString();
424
		String jarPath = projectLocation + File.separator + jarName;
425
		org.eclipse.jdt.core.tests.util.Util.createJar(pathAndContents, nonJavaResources, jarPath, compliance);
426
		if (pathAndContents != null && pathAndContents.length != 0) {
427
			String sourceZipPath = projectLocation + File.separator + sourceZipName;
428
			org.eclipse.jdt.core.tests.util.Util.createSourceZip(pathAndContents, sourceZipPath);
429
		}
430
		project.refreshLocal(IResource.DEPTH_INFINITE, null);
431
		return project;
432
	}
419
	protected void addLibraryEntry(String path, boolean exported) throws JavaModelException {
433
	protected void addLibraryEntry(String path, boolean exported) throws JavaModelException {
420
		addLibraryEntry(this.currentProject, new Path(path), null, null, null, null, exported);
434
		addLibraryEntry(this.currentProject, new Path(path), null, null, null, null, exported);
421
	}
435
	}
Lines 878-884 Link Here
878
			actual = buffer.toString();
892
			actual = buffer.toString();
879
		}
893
		}
880
		if (!actual.equals(expected)) {
894
		if (!actual.equals(expected)) {
881
		 	System.out.print(org.eclipse.jdt.core.tests.util.Util.displayString(actual, 2));
895
		 	System.out.print(displayString(actual, 2));
882
		}
896
		}
883
		assertEquals(expected, actual);
897
		assertEquals(expected, actual);
884
	}
898
	}
(-)batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJar.java (-115 / +1 lines)
Lines 14-20 Link Here
14
import java.io.File;
14
import java.io.File;
15
import java.io.IOException;
15
import java.io.IOException;
16
import java.io.InputStreamReader;
16
import java.io.InputStreamReader;
17
import java.io.Reader;
18
import java.util.ArrayList;
17
import java.util.ArrayList;
19
import java.util.Enumeration;
18
import java.util.Enumeration;
20
import java.util.Hashtable;
19
import java.util.Hashtable;
Lines 28-33 Link Here
28
import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
27
import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
29
import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
28
import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
30
import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
29
import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
30
import org.eclipse.jdt.internal.compiler.util.ManifestAnalyzer;
31
import org.eclipse.jdt.internal.compiler.util.Util;
31
import org.eclipse.jdt.internal.compiler.util.Util;
32
32
33
public class ClasspathJar extends ClasspathLocation {
33
public class ClasspathJar extends ClasspathLocation {
Lines 44-163 Link Here
44
	this.closeZipFileAtEnd = closeZipFileAtEnd;
44
	this.closeZipFileAtEnd = closeZipFileAtEnd;
45
}
45
}
46
46
47
// manifest file analyzer limited to Class-Path sections analysis
48
public static class ManifestAnalyzer {
49
	private static final int
50
		START = 0,
51
		IN_CLASSPATH_HEADER = 1, // multistate
52
		PAST_CLASSPATH_HEADER = 2,
53
		SKIPPING_WHITESPACE = 3,
54
		READING_JAR = 4,
55
		CONTINUING = 5,
56
		SKIP_LINE = 6;
57
	private static final char[] CLASSPATH_HEADER_TOKEN =
58
		"Class-Path:".toCharArray(); //$NON-NLS-1$
59
	private int ClasspathSectionsCount;
60
	private ArrayList calledFilesNames;
61
	public boolean analyzeManifestContents(Reader reader) throws IOException {
62
		int state = START, substate = 0;
63
		StringBuffer currentJarToken = new StringBuffer();
64
		int currentChar;
65
		this.ClasspathSectionsCount = 0;
66
		this.calledFilesNames = null;
67
		for (;;) {
68
			currentChar = reader.read();
69
			switch (state) {
70
				case START:
71
					if (currentChar == -1) {
72
						return true;
73
					} else if (currentChar == CLASSPATH_HEADER_TOKEN[0]) {
74
						state = IN_CLASSPATH_HEADER;
75
						substate = 1;
76
					} else {
77
						state = SKIP_LINE;
78
					}
79
					break;
80
				case IN_CLASSPATH_HEADER:
81
					if (currentChar == -1) {
82
						return true;
83
					} else if (currentChar == '\n') {
84
						state = START;
85
					} else if (currentChar != CLASSPATH_HEADER_TOKEN[substate++]) {
86
						state = SKIP_LINE;
87
					} else if (substate == CLASSPATH_HEADER_TOKEN.length) {
88
						state = PAST_CLASSPATH_HEADER;
89
					}
90
					break;
91
				case PAST_CLASSPATH_HEADER:
92
					if (currentChar == ' ') {
93
						state = SKIPPING_WHITESPACE;
94
						this.ClasspathSectionsCount++;
95
					} else {
96
						return false;
97
					}
98
					break;
99
				case SKIPPING_WHITESPACE:
100
					if (currentChar == -1) {
101
						return true;
102
					} else if (currentChar == '\n') {
103
						state = CONTINUING;
104
					} else if (currentChar != ' ') {
105
						currentJarToken.append((char) currentChar);
106
						state = READING_JAR;
107
					}
108
					break;
109
				case CONTINUING:
110
					if (currentChar == -1) {
111
						return true;
112
					} else if (currentChar == '\n') {
113
						state = START;
114
					} else if (currentChar == ' ') {
115
						state = SKIPPING_WHITESPACE;
116
					} else if (currentChar == CLASSPATH_HEADER_TOKEN[0]) {
117
						state = IN_CLASSPATH_HEADER;
118
						substate = 1;
119
					} else if (this.calledFilesNames == null) {
120
						return false;
121
					} else {
122
						state = SKIP_LINE;
123
					}
124
					break;
125
				case SKIP_LINE:
126
					if (currentChar == -1) {
127
						return true;
128
					} else if (currentChar == '\n') {
129
						state = START;
130
					}
131
					break;
132
				case READING_JAR:
133
					if (currentChar == -1) {
134
						return false;
135
					} else if (currentChar == '\n') {
136
						// appends token below
137
						state = CONTINUING;
138
					} else if (currentChar == ' ') {
139
						// appends token below
140
						state = SKIPPING_WHITESPACE;
141
					} else {
142
						currentJarToken.append((char) currentChar);
143
						break;
144
					}
145
					if (this.calledFilesNames == null) {
146
						this.calledFilesNames = new ArrayList();
147
					}
148
					this.calledFilesNames.add(currentJarToken.toString());
149
					currentJarToken.setLength(0);
150
					break;
151
			}
152
		}
153
	}
154
	public int getClasspathSectionsCount() {
155
		return this.ClasspathSectionsCount;
156
	}
157
	public List getCalledFileNames() {
158
		return this.calledFilesNames;
159
	}
160
}
161
public static final ManifestAnalyzer MANIFEST_ANALYZER = new ManifestAnalyzer();
47
public static final ManifestAnalyzer MANIFEST_ANALYZER = new ManifestAnalyzer();
162
48
163
public List fetchLinkedJars(FileSystem.ClasspathSectionProblemReporter problemReporter) {
49
public List fetchLinkedJars(FileSystem.ClasspathSectionProblemReporter problemReporter) {
(-)model/org/eclipse/jdt/internal/core/JavaProject.java (-30 / +65 lines)
Lines 1848-1854 Link Here
1848
			resolvedClasspath = perProjectInfo.getResolvedClasspath();
1848
			resolvedClasspath = perProjectInfo.getResolvedClasspath();
1849
			if (resolvedClasspath == null) {
1849
			if (resolvedClasspath == null) {
1850
				// another thread reset the resolved classpath, use a temporary PerProjectInfo
1850
				// another thread reset the resolved classpath, use a temporary PerProjectInfo
1851
				PerProjectInfo temporaryInfo = new PerProjectInfo(getProject());
1851
				PerProjectInfo temporaryInfo = newTemporaryInfo();
1852
				resolveClasspath(temporaryInfo, false/*don't use previous session values*/);
1852
				resolveClasspath(temporaryInfo, false/*don't use previous session values*/);
1853
				resolvedClasspath = temporaryInfo.getResolvedClasspath();
1853
				resolvedClasspath = temporaryInfo.getResolvedClasspath();
1854
			}
1854
			}
Lines 1884-1890 Link Here
1884
			}
1884
			}
1885
			if (resolvedClasspath == null) {
1885
			if (resolvedClasspath == null) {
1886
				// another thread reset the resolved classpath, use a temporary PerProjectInfo
1886
				// another thread reset the resolved classpath, use a temporary PerProjectInfo
1887
				PerProjectInfo temporaryInfo = new PerProjectInfo(getProject());
1887
				PerProjectInfo temporaryInfo = newTemporaryInfo();
1888
				resolveClasspath(temporaryInfo, false/*don't use previous session values*/);
1888
				resolveClasspath(temporaryInfo, false/*don't use previous session values*/);
1889
				resolvedClasspath = temporaryInfo.getResolvedClasspath();
1889
				resolvedClasspath = temporaryInfo.getResolvedClasspath();
1890
				unresolvedEntryStatus = temporaryInfo.unresolvedEntryStatus;
1890
				unresolvedEntryStatus = temporaryInfo.unresolvedEntryStatus;
Lines 2251-2256 Link Here
2251
		return new SearchableEnvironment(this, owner);
2251
		return new SearchableEnvironment(this, owner);
2252
	}
2252
	}
2253
2253
2254
	/*
2255
	 * Returns a PerProjectInfo that doesn't register classpath change
2256
	 * and that should be used as a temporary info.
2257
	 */
2258
	public PerProjectInfo newTemporaryInfo() {
2259
		return 
2260
			new PerProjectInfo(this.project.getProject()) {
2261
				protected ClasspathChange addClasspathChange() {
2262
					return null;
2263
				}
2264
		};
2265
	}
2266
2254
	/**
2267
	/**
2255
	 * @see IJavaProject
2268
	 * @see IJavaProject
2256
	 */
2269
	 */
Lines 2469-2474 Link Here
2469
		}
2482
		}
2470
	}
2483
	}
2471
2484
2485
	public ClasspathChange resetResolvedClasspath() {
2486
		try {
2487
			return getPerProjectInfo().resetResolvedClasspath();
2488
		} catch (JavaModelException e) {
2489
			// project doesn't exist
2490
			return null;
2491
		}
2492
	}		
2493
	
2472
	/*
2494
	/*
2473
	 * Resolve the given raw classpath.
2495
	 * Resolve the given raw classpath.
2474
	 */
2496
	 */
Lines 2494-2506 Link Here
2494
2516
2495
			IClasspathEntry rawEntry = rawClasspath[i];
2517
			IClasspathEntry rawEntry = rawClasspath[i];
2496
			IClasspathEntry resolvedEntry = rawEntry;
2518
			IClasspathEntry resolvedEntry = rawEntry;
2497
			IPath resolvedPath;
2498
2519
2499
			switch (rawEntry.getEntryKind()){
2520
			switch (rawEntry.getEntryKind()){
2500
2521
2501
				case IClasspathEntry.CPE_VARIABLE :
2522
				case IClasspathEntry.CPE_VARIABLE :
2502
					try {
2523
					try {
2503
						resolvedEntry = manager.getResolvedClasspathEntry(rawEntry, usePreviousSession);
2524
						resolvedEntry = manager.resolveVariableEntry(rawEntry, usePreviousSession);
2504
					} catch (ClasspathEntry.AssertionFailedException e) {
2525
					} catch (ClasspathEntry.AssertionFailedException e) {
2505
						// Catch the assertion failure and set status instead
2526
						// Catch the assertion failure and set status instead
2506
						// see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=55992
2527
						// see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=55992
Lines 2510-2523 Link Here
2510
					if (resolvedEntry == null) {
2531
					if (resolvedEntry == null) {
2511
						result.unresolvedEntryStatus = new JavaModelStatus(IJavaModelStatusConstants.CP_VARIABLE_PATH_UNBOUND, this, rawEntry.getPath());
2532
						result.unresolvedEntryStatus = new JavaModelStatus(IJavaModelStatusConstants.CP_VARIABLE_PATH_UNBOUND, this, rawEntry.getPath());
2512
					} else {
2533
					} else {
2513
						if (result.rawReverseMap.get(resolvedPath = resolvedEntry.getPath()) == null) {
2534
						if (resolvedEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
2514
							result.rawReverseMap.put(resolvedPath , rawEntry);
2535
							// resolve Class-Path: in manifest
2515
							result.rootPathToResolvedEntries.put(resolvedPath, resolvedEntry);
2536
							ClasspathEntry[] extraEntries = ((ClasspathEntry) resolvedEntry).resolvedChainedLibraries();
2516
						}
2537
							for (int j = 0, length2 = extraEntries.length; j < length2; j++) {
2517
						resolvedEntries.add(resolvedEntry);
2538
								addToResult(rawEntry, extraEntries[j], result, resolvedEntries, externalFoldersManager);
2518
						if (resolvedEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY && ExternalFoldersManager.isExternalFolderPath(resolvedPath)) {
2539
							}
2519
							externalFoldersManager.addFolder(resolvedPath); // no-op if not an external folder or if already registered
2520
						}
2540
						}
2541
						addToResult(rawEntry, resolvedEntry, result, resolvedEntries, externalFoldersManager);
2521
					}
2542
					}
2522
					break;
2543
					break;
2523
2544
Lines 2547-2580 Link Here
2547
						}
2568
						}
2548
						// if container is exported or restricted, then its nested entries must in turn be exported  (21749) and/or propagate restrictions
2569
						// if container is exported or restricted, then its nested entries must in turn be exported  (21749) and/or propagate restrictions
2549
						cEntry = cEntry.combineWith((ClasspathEntry) rawEntry);
2570
						cEntry = cEntry.combineWith((ClasspathEntry) rawEntry);
2550
						// resolve ".." in library path
2571
						
2551
						if (cEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
2572
						if (cEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
2573
							// resolve ".." in library path
2552
							cEntry = cEntry.resolvedDotDot();
2574
							cEntry = cEntry.resolvedDotDot();
2575
							
2576
							// resolve Class-Path: in manifest
2577
							ClasspathEntry[] extraEntries = cEntry.resolvedChainedLibraries();
2578
							for (int k = 0, length2 = extraEntries.length; k < length2; k++) {
2579
								addToResult(rawEntry, extraEntries[k], result, resolvedEntries, externalFoldersManager);
2580
							}
2553
						}
2581
						}
2554
						if (result.rawReverseMap.get(resolvedPath = cEntry.getPath()) == null) {
2582
						addToResult(rawEntry, cEntry, result, resolvedEntries, externalFoldersManager);
2555
							result.rawReverseMap.put(resolvedPath , rawEntry);
2556
							result.rootPathToResolvedEntries.put(resolvedPath, cEntry);
2557
						}
2558
						resolvedEntries.add(cEntry);
2559
						if (cEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY && ExternalFoldersManager.isExternalFolderPath(resolvedPath)) {
2560
							externalFoldersManager.addFolder(resolvedPath); // no-op if not an external folder or if already registered
2561
						}
2562
					}
2583
					}
2563
					break;
2584
					break;
2564
2585
2565
				case IClasspathEntry.CPE_LIBRARY:
2586
				case IClasspathEntry.CPE_LIBRARY:
2587
					// resolve ".." in library path
2566
					resolvedEntry = ((ClasspathEntry) rawEntry).resolvedDotDot();
2588
					resolvedEntry = ((ClasspathEntry) rawEntry).resolvedDotDot();
2567
					// $FALL-THROUGH$ use the default code below
2589
					
2568
				default :
2590
					// resolve Class-Path: in manifest
2569
					if (result.rawReverseMap.get(resolvedPath = resolvedEntry.getPath()) == null) {
2591
					ClasspathEntry[] extraEntries = ((ClasspathEntry) resolvedEntry).resolvedChainedLibraries();
2570
						result.rawReverseMap.put(resolvedPath , rawEntry);
2592
					for (int k = 0, length2 = extraEntries.length; k < length2; k++) {
2571
						result.rootPathToResolvedEntries.put(resolvedPath, resolvedEntry);
2593
						addToResult(rawEntry, extraEntries[k], result, resolvedEntries, externalFoldersManager);
2572
					}
2573
					resolvedEntries.add(resolvedEntry);
2574
					if (resolvedEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY && ExternalFoldersManager.isExternalFolderPath(resolvedPath)) {
2575
						externalFoldersManager.addFolder(resolvedPath); // no-op if not an external folder or if already registered
2576
					}
2594
					}
2577
2595
2596
					addToResult(rawEntry, resolvedEntry, result, resolvedEntries, externalFoldersManager);
2597
					break;
2598
				default :
2599
					addToResult(rawEntry, resolvedEntry, result, resolvedEntries, externalFoldersManager);
2600
					break;
2578
			}
2601
			}
2579
		}
2602
		}
2580
		result.resolvedClasspath = new IClasspathEntry[resolvedEntries.size()];
2603
		result.resolvedClasspath = new IClasspathEntry[resolvedEntries.size()];
Lines 2582-2587 Link Here
2582
		return result;
2605
		return result;
2583
	}
2606
	}
2584
2607
2608
	private void addToResult(IClasspathEntry rawEntry, IClasspathEntry resolvedEntry, ResolvedClasspath result, ArrayList resolvedEntries, ExternalFoldersManager externalFoldersManager) {
2609
		IPath resolvedPath;
2610
		if (result.rawReverseMap.get(resolvedPath = resolvedEntry.getPath()) == null) {
2611
			result.rawReverseMap.put(resolvedPath, rawEntry);
2612
			result.rootPathToResolvedEntries.put(resolvedPath, resolvedEntry);
2613
		}
2614
		resolvedEntries.add(resolvedEntry);
2615
		if (resolvedEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY && ExternalFoldersManager.isExternalFolderPath(resolvedPath)) {
2616
			externalFoldersManager.addFolder(resolvedPath); // no-op if not an external folder or if already registered
2617
		}
2618
	}
2619
2585
	/*
2620
	/*
2586
	 * Resolve the given perProjectInfo's raw classpath and store the resolved classpath in the perProjectInfo.
2621
	 * Resolve the given perProjectInfo's raw classpath and store the resolved classpath in the perProjectInfo.
2587
	 */
2622
	 */
Lines 2620-2626 Link Here
2620
				breakpoint(3, this);
2655
				breakpoint(3, this);
2621
		}
2656
		}
2622
	}
2657
	}
2623
2658
	
2624
	/**
2659
	/**
2625
	 * Answers an ID which is used to distinguish project/entries during package
2660
	 * Answers an ID which is used to distinguish project/entries during package
2626
	 * fragment root computations
2661
	 * fragment root computations
(-)model/org/eclipse/jdt/internal/core/ClasspathEntry.java (-54 / +181 lines)
Lines 10-25 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.jdt.internal.core;
11
package org.eclipse.jdt.internal.core;
12
12
13
import java.io.BufferedReader;
13
import java.io.ByteArrayOutputStream;
14
import java.io.ByteArrayOutputStream;
14
import java.io.File;
15
import java.io.File;
16
import java.io.IOException;
17
import java.io.InputStreamReader;
15
import java.io.OutputStreamWriter;
18
import java.io.OutputStreamWriter;
16
import java.io.UnsupportedEncodingException;
19
import java.io.UnsupportedEncodingException;
17
import java.util.ArrayList;
20
import java.util.ArrayList;
18
import java.util.HashMap;
21
import java.util.HashMap;
19
import java.util.HashSet;
22
import java.util.HashSet;
23
import java.util.Iterator;
24
import java.util.List;
20
import java.util.Map;
25
import java.util.Map;
26
import java.util.zip.ZipEntry;
27
import java.util.zip.ZipFile;
21
28
22
import org.eclipse.core.resources.IContainer;
29
import org.eclipse.core.resources.IContainer;
30
import org.eclipse.core.resources.IFile;
23
import org.eclipse.core.resources.IProject;
31
import org.eclipse.core.resources.IProject;
24
import org.eclipse.core.resources.IResource;
32
import org.eclipse.core.resources.IResource;
25
import org.eclipse.core.resources.IWorkspaceRoot;
33
import org.eclipse.core.resources.IWorkspaceRoot;
Lines 44-49 Link Here
44
import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
52
import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
45
import org.eclipse.jdt.internal.compiler.env.AccessRule;
53
import org.eclipse.jdt.internal.compiler.env.AccessRule;
46
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
54
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
55
import org.eclipse.jdt.internal.compiler.util.ManifestAnalyzer;
47
import org.eclipse.jdt.internal.core.util.Messages;
56
import org.eclipse.jdt.internal.core.util.Messages;
48
import org.eclipse.jdt.internal.core.util.Util;
57
import org.eclipse.jdt.internal.core.util.Util;
49
import org.w3c.dom.DOMException;
58
import org.w3c.dom.DOMException;
Lines 133-138 Link Here
133
	private IPath[] exclusionPatterns;
142
	private IPath[] exclusionPatterns;
134
	private char[][] fullExclusionPatternChars;
143
	private char[][] fullExclusionPatternChars;
135
	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$
145
	private final static ClasspathEntry[] NO_ENTRIES = new ClasspathEntry[0];
146
	private final static IPath[] NO_PATHS = new IPath[0];
136
147
137
	private boolean combineAccessRules;
148
	private boolean combineAccessRules;
138
149
Lines 848-853 Link Here
848
	}
859
	}
849
860
850
	/*
861
	/*
862
	 * Read the Class-Path clause of the manifest of the jar pointed by this path, and return
863
	 * the corresponding paths.
864
	 */
865
	public static IPath[] resolvedChainedLibraries(IPath jarPath) {
866
		ArrayList result = new ArrayList();
867
		resolvedChainedLibraries(jarPath, new HashSet(), result);
868
		if (result.size() == 0)
869
			return NO_PATHS;
870
		return (IPath[]) result.toArray(new IPath[result.size()]);
871
	}
872
	
873
	private static void resolvedChainedLibraries(IPath jarPath, HashSet visited, ArrayList result) {
874
		if (visited.contains( jarPath))
875
			return;
876
		visited.add(jarPath);
877
		Object target = JavaModel.getTarget(jarPath, true/*check existence, otherwise the manifest cannot be read*/);
878
		if (target instanceof IFile || target instanceof File) {
879
			JavaModelManager manager = JavaModelManager.getJavaModelManager();
880
			ZipFile zip = null;
881
			BufferedReader reader = null;
882
			try {
883
				zip = manager.getZipFile(jarPath);
884
				ZipEntry manifest =	zip.getEntry("META-INF/MANIFEST.MF"); //$NON-NLS-1$
885
				if (manifest != null) { // non-null implies regular file
886
					reader = new BufferedReader(new InputStreamReader(zip.getInputStream(manifest)));
887
					ManifestAnalyzer analyzer = new ManifestAnalyzer();
888
					boolean success = analyzer.analyzeManifestContents(reader);
889
					List calledFileNames = analyzer.getCalledFileNames();
890
					if (!success || analyzer.getClasspathSectionsCount() == 1 && calledFileNames == null) {
891
						Util.log(IStatus.WARNING, "Invalid Class-Path header in manifest of jar file: " + jarPath.toOSString()); //$NON-NLS-1$
892
						return;
893
					} else if (analyzer.getClasspathSectionsCount() > 1) {
894
						Util.log(IStatus.WARNING, "Multiple Class-Path headers in manifest of jar file: " + jarPath.toOSString()); //$NON-NLS-1$
895
						return;
896
					}
897
					if (calledFileNames != null) {
898
						Iterator calledFilesIterator = calledFileNames.iterator();
899
						IPath directoryPath = jarPath.removeLastSegments(1);
900
						while (calledFilesIterator.hasNext()) {
901
							String calledFileName = (String) calledFilesIterator.next();
902
							if (!directoryPath.isValidPath(calledFileName)) {
903
								Util.log(IStatus.WARNING, "Invalid Class-Path entry " + calledFileName + " in manifest of jar file: " + jarPath.toOSString()); //$NON-NLS-1$ //$NON-NLS-2$
904
							} else {
905
								IPath calledJar = directoryPath.append(new Path(calledFileName));
906
								resolvedChainedLibraries(calledJar, visited, result);
907
								result.add(calledJar);
908
							}
909
						}
910
					}
911
				}
912
			} catch (CoreException e) {
913
				// not a zip file
914
			} catch (IOException e) {
915
				Util.log(e, "Could not read Class-Path header in manifest of jar file: " + jarPath.toOSString()); //$NON-NLS-1$
916
			} finally {
917
				manager.closeZipFile(zip);
918
				if (reader != null) {
919
					try {
920
						reader.close();
921
					} catch (IOException e) {
922
						// best effort
923
					}
924
				}
925
			}
926
		}
927
	}
928
	
929
	/*
851
	 * Resolves the ".." in the given path. Returns the given path if it contains no ".." segment.
930
	 * Resolves the ".." in the given path. Returns the given path if it contains no ".." segment.
852
	 */
931
	 */
853
	public static IPath resolveDotDot(IPath path) {
932
	public static IPath resolveDotDot(IPath path) {
Lines 1163-1169 Link Here
1163
	 */
1242
	 */
1164
	public String toString() {
1243
	public String toString() {
1165
		StringBuffer buffer = new StringBuffer();
1244
		StringBuffer buffer = new StringBuffer();
1166
		buffer.append(String.valueOf(getPath()));
1245
		Object target = JavaModel.getTarget(getPath(), true);
1246
		if (target instanceof File)
1247
			buffer.append(getPath().toOSString());
1248
		else
1249
			buffer.append(String.valueOf(getPath()));
1167
		buffer.append('[');
1250
		buffer.append('[');
1168
		switch (getEntryKind()) {
1251
		switch (getEntryKind()) {
1169
			case IClasspathEntry.CPE_LIBRARY :
1252
			case IClasspathEntry.CPE_LIBRARY :
Lines 1278-1283 Link Here
1278
							this.extraAttributes);
1361
							this.extraAttributes);
1279
	}
1362
	}
1280
	
1363
	
1364
	/*
1365
	 * Read the Class-Path clause of the manifest of the jar pointed by this entry, and return
1366
	 * the corresponding library entries.
1367
	 */
1368
	public ClasspathEntry[] resolvedChainedLibraries() {
1369
		IPath[] paths = resolvedChainedLibraries(getPath());
1370
		int length = paths.length;
1371
		if (length == 0)
1372
			return NO_ENTRIES;
1373
		ClasspathEntry[] result = new ClasspathEntry[length];
1374
		for (int i = 0; i < length; i++) {
1375
			result[i] = new ClasspathEntry(
1376
									getContentKind(),
1377
									getEntryKind(),
1378
									paths[i],
1379
									this.inclusionPatterns,
1380
									this.exclusionPatterns,
1381
									getSourceAttachmentPath(),
1382
									getSourceAttachmentRootPath(),
1383
									getOutputLocation(),
1384
									this.isExported,
1385
									getAccessRules(),
1386
									this.combineAccessRules,
1387
									this.extraAttributes);
1388
		}
1389
		return result;
1390
	}
1391
	
1281
	/**
1392
	/**
1282
	 * Answers an ID which is used to distinguish entries during package
1393
	 * Answers an ID which is used to distinguish entries during package
1283
	 * fragment root computations
1394
	 * fragment root computations
Lines 1614-1620 Link Here
1614
	 *
1725
	 *
1615
	 * @param project the given java project
1726
	 * @param project the given java project
1616
	 * @param entry the given classpath entry
1727
	 * @param entry the given classpath entry
1617
	 * @param checkSourceAttachment a flag to determine if source attachement should be checked
1728
	 * @param checkSourceAttachment a flag to determine if source attachment should be checked
1618
	 * @param recurseInContainers flag indicating whether validation should be applied to container entries recursively
1729
	 * @param recurseInContainers flag indicating whether validation should be applied to container entries recursively
1619
	 * @return a java model status describing the problem related to this classpath entry if any, a status object with code <code>IStatus.OK</code> if the entry is fine
1730
	 * @return a java model status describing the problem related to this classpath entry if any, a status object with code <code>IStatus.OK</code> if the entry is fine
1620
	 */
1731
	 */
Lines 1625-1632 Link Here
1625
1736
1626
		// Build some common strings for status message
1737
		// Build some common strings for status message
1627
		String projectName = project.getElementName();
1738
		String projectName = project.getElementName();
1628
		boolean pathStartsWithProject = projectName.equals(path.segment(0));
1739
		String entryPathMsg = projectName.equals(path.segment(0)) ? path.removeFirstSegments(1).makeRelative().toString() : path.toString();
1629
		String entryPathMsg = pathStartsWithProject ? path.removeFirstSegments(1).makeRelative().toString() : path.toString();
1630
1740
1631
		switch(entry.getEntryKind()){
1741
		switch(entry.getEntryKind()){
1632
1742
Lines 1719-1774 Link Here
1719
			// library entry check
1829
			// library entry check
1720
			case IClasspathEntry.CPE_LIBRARY :
1830
			case IClasspathEntry.CPE_LIBRARY :
1721
				path = ClasspathEntry.resolveDotDot(path);
1831
				path = ClasspathEntry.resolveDotDot(path);
1722
				if (path.isAbsolute() && !path.isEmpty()) {
1832
				
1723
					IPath sourceAttachment = entry.getSourceAttachmentPath();
1833
				// resolve Class-Path: in manifest
1724
					Object target = JavaModel.getTarget(path, true);
1834
				IPath[] chainedJars = ClasspathEntry.resolvedChainedLibraries(path);
1725
					if (target != null && !JavaCore.IGNORE.equals(project.getOption(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL, true))) {
1835
				for (int i = 0, length = chainedJars.length; i < length; i++) {
1726
						long projectTargetJDK = CompilerOptions.versionToJdkLevel(project.getOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, true));
1836
					IPath chainedJar = chainedJars[i];
1727
						long libraryJDK = Util.getJdkLevel(target);
1837
					IJavaModelStatus status = validateLibraryEntry(chainedJar, project, null/*don't check source attachment*/, null/*force computing of entryPathMsg*/);
1728
						if (libraryJDK != 0 && libraryJDK > projectTargetJDK) {
1838
					if (!status.isOK())
1729
							return new JavaModelStatus(IJavaModelStatusConstants.INCOMPATIBLE_JDK_LEVEL, project, path, CompilerOptions.versionFromJdkLevel(libraryJDK));
1839
						return status;
1730
						}
1840
				}
1731
					}
1841
				
1732
					if (target instanceof IResource){
1842
				IJavaModelStatus status = validateLibraryEntry(path, project, checkSourceAttachment ? entry.getSourceAttachmentPath() : null, entryPathMsg);
1733
						IResource resolvedResource = (IResource) target;
1843
				if (!status.isOK())
1734
						switch(resolvedResource.getType()){
1844
					return status;
1735
							case IResource.FILE :
1736
								if (checkSourceAttachment
1737
									&& sourceAttachment != null
1738
									&& !sourceAttachment.isEmpty()
1739
									&& JavaModel.getTarget(sourceAttachment, true) == null){
1740
									return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundSourceAttachment, new String [] {sourceAttachment.toString(), path.toString(), projectName}));
1741
								}
1742
								break;
1743
							case IResource.FOLDER :	// internal binary folder
1744
								if (checkSourceAttachment
1745
									&& sourceAttachment != null
1746
									&& !sourceAttachment.isEmpty()
1747
									&& JavaModel.getTarget(sourceAttachment, true) == null){
1748
									return  new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundSourceAttachment, new String [] {sourceAttachment.toString(), path.toString(), projectName}));
1749
								}
1750
						}
1751
					} else if (target instanceof File){
1752
						File file = JavaModel.getFile(target);
1753
					    if (file == null) {
1754
							return  new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_illegalExternalFolder, new String[] {path.toOSString(), projectName}));
1755
					    } else if (checkSourceAttachment
1756
								&& sourceAttachment != null
1757
								&& !sourceAttachment.isEmpty()
1758
								&& JavaModel.getTarget(sourceAttachment, true) == null){
1759
								return  new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundSourceAttachment, new String [] {sourceAttachment.toString(), path.toOSString(), projectName}));
1760
					    }
1761
					} else {
1762
						boolean isExternal = path.getDevice() != null || !workspaceRoot.getProject(path.segment(0)).exists();
1763
						if (isExternal) {
1764
							return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundLibrary, new String[] {path.toOSString(), projectName}));
1765
						} else {
1766
							return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundLibrary, new String[] {entryPathMsg, projectName}));
1767
						}
1768
					}
1769
				} else {
1770
					return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_illegalLibraryPath, new String[] {entryPathMsg, projectName}));
1771
				}
1772
				break;
1845
				break;
1773
1846
1774
			// project entry check
1847
			// project entry check
Lines 1834-1837 Link Here
1834
1907
1835
		return JavaModelStatus.VERIFIED_OK;
1908
		return JavaModelStatus.VERIFIED_OK;
1836
	}
1909
	}
1910
1911
	private static IJavaModelStatus validateLibraryEntry(IPath path, IJavaProject project, IPath sourceAttachment, String entryPathMsg) {
1912
		if (path.isAbsolute() && !path.isEmpty()) {
1913
			Object target = JavaModel.getTarget(path, true);
1914
			if (target != null && !JavaCore.IGNORE.equals(project.getOption(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL, true))) {
1915
				long projectTargetJDK = CompilerOptions.versionToJdkLevel(project.getOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, true));
1916
				long libraryJDK = Util.getJdkLevel(target);
1917
				if (libraryJDK != 0 && libraryJDK > projectTargetJDK) {
1918
					return new JavaModelStatus(IJavaModelStatusConstants.INCOMPATIBLE_JDK_LEVEL, project, path, CompilerOptions.versionFromJdkLevel(libraryJDK));
1919
				}
1920
			}
1921
			if (target instanceof IResource){
1922
				IResource resolvedResource = (IResource) target;
1923
				switch(resolvedResource.getType()){
1924
					case IResource.FILE :
1925
						if (sourceAttachment != null
1926
							&& !sourceAttachment.isEmpty()
1927
							&& JavaModel.getTarget(sourceAttachment, true) == null){
1928
							return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundSourceAttachment, new String [] {sourceAttachment.toString(), path.toString(), project.getElementName()}));
1929
						}
1930
						break;
1931
					case IResource.FOLDER :	// internal binary folder
1932
						if (sourceAttachment != null
1933
							&& !sourceAttachment.isEmpty()
1934
							&& JavaModel.getTarget(sourceAttachment, true) == null){
1935
							return  new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundSourceAttachment, new String [] {sourceAttachment.toString(), path.toString(), project.getElementName()}));
1936
						}
1937
				}
1938
			} else if (target instanceof File){
1939
				File file = JavaModel.getFile(target);
1940
			    if (file == null) {
1941
					return  new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_illegalExternalFolder, new String[] {path.toOSString(), project.getElementName()}));
1942
			    } else if (sourceAttachment != null
1943
						&& !sourceAttachment.isEmpty()
1944
						&& JavaModel.getTarget(sourceAttachment, true) == null){
1945
						return  new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundSourceAttachment, new String [] {sourceAttachment.toString(), path.toOSString(), project.getElementName()}));
1946
			    }
1947
			} else {
1948
				boolean isExternal = path.getDevice() != null || !ResourcesPlugin.getWorkspace().getRoot().getProject(path.segment(0)).exists();
1949
				if (isExternal) {
1950
					return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundLibrary, new String[] {path.toOSString(), project.getElementName()}));
1951
				} else {
1952
					if (entryPathMsg == null) 
1953
						entryPathMsg = 	project.getElementName().equals(path.segment(0)) ? path.removeFirstSegments(1).makeRelative().toString() : path.toString();
1954
					return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundLibrary, new String[] {entryPathMsg, project.getElementName()}));
1955
				}
1956
			}
1957
		} else {
1958
			if (entryPathMsg == null) 
1959
				entryPathMsg = 	project.getElementName().equals(path.segment(0)) ? path.removeFirstSegments(1).makeRelative().toString() : path.toString();
1960
			return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_illegalLibraryPath, new String[] {entryPathMsg, project.getElementName()}));
1961
		}
1962
		return JavaModelStatus.VERIFIED_OK;
1963
	}
1837
}
1964
}
(-)model/org/eclipse/jdt/internal/core/JavaModelManager.java (-5 / +10 lines)
Lines 1098-1107 Link Here
1098
		}
1098
		}
1099
1099
1100
		private ClasspathChange setClasspath(IClasspathEntry[] newRawClasspath, IPath newOutputLocation, IJavaModelStatus newRawClasspathStatus, IClasspathEntry[] newResolvedClasspath, Map newRootPathToRawEntries, Map newRootPathToResolvedEntries, IJavaModelStatus newUnresolvedEntryStatus) {
1100
		private ClasspathChange setClasspath(IClasspathEntry[] newRawClasspath, IPath newOutputLocation, IJavaModelStatus newRawClasspathStatus, IClasspathEntry[] newResolvedClasspath, Map newRootPathToRawEntries, Map newRootPathToResolvedEntries, IJavaModelStatus newUnresolvedEntryStatus) {
1101
			// remember old info
1101
			ClasspathChange classpathChange = addClasspathChange();
1102
			JavaModelManager manager = JavaModelManager.getJavaModelManager();
1103
			DeltaProcessor deltaProcessor = manager.deltaState.getDeltaProcessor();
1104
			ClasspathChange classpathChange = deltaProcessor.addClasspathChange(this.project, this.rawClasspath, this.outputLocation, this.resolvedClasspath);
1105
1102
1106
			this.rawClasspath = newRawClasspath;
1103
			this.rawClasspath = newRawClasspath;
1107
			this.outputLocation = newOutputLocation;
1104
			this.outputLocation = newOutputLocation;
Lines 1115-1120 Link Here
1115
			return classpathChange;
1112
			return classpathChange;
1116
		}
1113
		}
1117
1114
1115
		protected ClasspathChange addClasspathChange() {
1116
			// remember old info
1117
			JavaModelManager manager = JavaModelManager.getJavaModelManager();
1118
			DeltaProcessor deltaProcessor = manager.deltaState.getDeltaProcessor();
1119
			ClasspathChange classpathChange = deltaProcessor.addClasspathChange(this.project, this.rawClasspath, this.outputLocation, this.resolvedClasspath);
1120
			return classpathChange;
1121
		}
1122
1118
		public synchronized ClasspathChange setRawClasspath(IClasspathEntry[] newRawClasspath, IPath newOutputLocation, IJavaModelStatus newRawClasspathStatus) {
1123
		public synchronized ClasspathChange setRawClasspath(IClasspathEntry[] newRawClasspath, IPath newOutputLocation, IJavaModelStatus newRawClasspathStatus) {
1119
			this.rawTimeStamp++;
1124
			this.rawTimeStamp++;
1120
			return setClasspath(newRawClasspath, newOutputLocation, newRawClasspathStatus, null/*resolved classpath*/, null/*root to raw map*/, null/*root to resolved map*/, null/*unresolved status*/);
1125
			return setClasspath(newRawClasspath, newOutputLocation, newRawClasspathStatus, null/*resolved classpath*/, null/*root to raw map*/, null/*root to resolved map*/, null/*unresolved status*/);
Lines 2178-2184 Link Here
2178
		return containerIDs;
2183
		return containerIDs;
2179
	}
2184
	}
2180
2185
2181
	public IClasspathEntry getResolvedClasspathEntry(IClasspathEntry entry, boolean usePreviousSession) {
2186
	public IClasspathEntry resolveVariableEntry(IClasspathEntry entry, boolean usePreviousSession) {
2182
2187
2183
		if (entry.getEntryKind() != IClasspathEntry.CPE_VARIABLE)
2188
		if (entry.getEntryKind() != IClasspathEntry.CPE_VARIABLE)
2184
			return entry;
2189
			return entry;
(-)model/org/eclipse/jdt/internal/core/DeltaProcessor.java (-25 / +34 lines)
Lines 313-319 Link Here
313
	 * In all cases, add the project's dependents to the list of projects to update
313
	 * In all cases, add the project's dependents to the list of projects to update
314
	 * so that the classpath related markers can be updated.
314
	 * so that the classpath related markers can be updated.
315
	 */
315
	 */
316
	private void checkProjectsBeingAddedOrRemoved(IResourceDelta delta) {
316
	private void checkProjectsAndClasspathChanges(IResourceDelta delta) {
317
		IResource resource = delta.getResource();
317
		IResource resource = delta.getResource();
318
		IResourceDelta[] children = null;
318
		IResourceDelta[] children = null;
319
319
Lines 438-449 Link Here
438
				}
438
				}
439
439
440
				break;
440
				break;
441
			case IResource.FOLDER:
442
				if (delta.getKind() == IResourceDelta.CHANGED) { // look for .jar file change to update classpath
443
					children = delta.getAffectedChildren();
444
				}
445
				break;
441
			case IResource.FILE :
446
			case IResource.FILE :
442
				IFile file = (IFile) resource;
447
				IFile file = (IFile) resource;
443
				/* classpath file change */
448
				int kind = delta.getKind();
449
				RootInfo rootInfo;
444
				if (file.getName().equals(JavaProject.CLASSPATH_FILENAME)) {
450
				if (file.getName().equals(JavaProject.CLASSPATH_FILENAME)) {
451
					/* classpath file change */
445
					this.manager.forceBatchInitializations(false/*not initAfterLoad*/);
452
					this.manager.forceBatchInitializations(false/*not initAfterLoad*/);
446
					switch (delta.getKind()) {
453
					switch (kind) {
447
						case IResourceDelta.CHANGED :
454
						case IResourceDelta.CHANGED :
448
							int flags = delta.getFlags();
455
							int flags = delta.getFlags();
449
							if ((flags & IResourceDelta.CONTENT) == 0  // only consider content change
456
							if ((flags & IResourceDelta.CONTENT) == 0  // only consider content change
Lines 463-475 Link Here
463
							break;
470
							break;
464
					}
471
					}
465
					this.state.rootsAreStale = true;
472
					this.state.rootsAreStale = true;
473
				} else if ((rootInfo = rootInfo(file.getFullPath(), kind)) != null && rootInfo.entryKind == IClasspathEntry.CPE_LIBRARY) {
474
					javaProject = (JavaProject)JavaCore.create(file.getProject());
475
					javaProject.resetResolvedClasspath();
476
					this.state.rootsAreStale = true;
466
				}
477
				}
467
				break;
478
				break;
468
479
469
		}
480
		}
470
		if (children != null) {
481
		if (children != null) {
471
			for (int i = 0; i < children.length; i++) {
482
			for (int i = 0; i < children.length; i++) {
472
				checkProjectsBeingAddedOrRemoved(children[i]);
483
				checkProjectsAndClasspathChanges(children[i]);
473
			}
484
			}
474
		}
485
		}
475
	}
486
	}
Lines 815-829 Link Here
815
						javaProject = (JavaProject) JavaCore.create(project);
826
						javaProject = (JavaProject) JavaCore.create(project);
816
						try {
827
						try {
817
							classpath = javaProject.getResolvedClasspath();
828
							classpath = javaProject.getResolvedClasspath();
829
							for (int k = 0, cpLength = classpath.length; k < cpLength; k++){
830
								if (classpath[k].getEntryKind() == IClasspathEntry.CPE_LIBRARY){
831
									archivePathsToRefresh.add(classpath[k].getPath());
832
								}
833
							}
818
						} catch (JavaModelException e2) {
834
						} catch (JavaModelException e2) {
819
							// project doesn't exist -> ignore
835
							// project doesn't exist -> ignore
820
							continue;
836
							continue;
821
						}
837
						}
822
						for (int k = 0, cpLength = classpath.length; k < cpLength; k++){
823
							if (classpath[k].getEntryKind() == IClasspathEntry.CPE_LIBRARY){
824
								archivePathsToRefresh.add(classpath[k].getPath());
825
							}
826
						}
827
					}
838
					}
828
					break;
839
					break;
829
			}
840
			}
Lines 852-858 Link Here
852
			}
863
			}
853
			for (int j = 0; j < entries.length; j++){
864
			for (int j = 0; j < entries.length; j++){
854
				if (entries[j].getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
865
				if (entries[j].getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
855
856
					IPath entryPath = entries[j].getPath();
866
					IPath entryPath = entries[j].getPath();
857
867
858
					if (!archivePathsToRefresh.contains(entryPath)) continue; // not supposed to be refreshed
868
					if (!archivePathsToRefresh.contains(entryPath)) continue; // not supposed to be refreshed
Lines 919-924 Link Here
919
								System.out.println("- External JAR ADDED, affecting root: "+root.getElementName()); //$NON-NLS-1$
929
								System.out.println("- External JAR ADDED, affecting root: "+root.getElementName()); //$NON-NLS-1$
920
							}
930
							}
921
							elementAdded(root, null, null);
931
							elementAdded(root, null, null);
932
							javaProject.resetResolvedClasspath(); // in case it contains a chained jar
922
							this.state.addClasspathValidation(javaProject); // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=185733
933
							this.state.addClasspathValidation(javaProject); // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=185733
923
							hasDelta = true;
934
							hasDelta = true;
924
						} else if (status == EXTERNAL_JAR_CHANGED) {
935
						} else if (status == EXTERNAL_JAR_CHANGED) {
Lines 927-932 Link Here
927
								System.out.println("- External JAR CHANGED, affecting root: "+root.getElementName()); //$NON-NLS-1$
938
								System.out.println("- External JAR CHANGED, affecting root: "+root.getElementName()); //$NON-NLS-1$
928
							}
939
							}
929
							contentChanged(root);
940
							contentChanged(root);
941
							javaProject.resetResolvedClasspath(); // in case it contains a chained jar
930
							hasDelta = true;
942
							hasDelta = true;
931
						} else if (status == EXTERNAL_JAR_REMOVED) {
943
						} else if (status == EXTERNAL_JAR_REMOVED) {
932
							PackageFragmentRoot root = (PackageFragmentRoot) javaProject.getPackageFragmentRoot(entryPath.toString());
944
							PackageFragmentRoot root = (PackageFragmentRoot) javaProject.getPackageFragmentRoot(entryPath.toString());
Lines 934-939 Link Here
934
								System.out.println("- External JAR REMOVED, affecting root: "+root.getElementName()); //$NON-NLS-1$
946
								System.out.println("- External JAR REMOVED, affecting root: "+root.getElementName()); //$NON-NLS-1$
935
							}
947
							}
936
							elementRemoved(root, null, null);
948
							elementRemoved(root, null, null);
949
							javaProject.resetResolvedClasspath(); // in case it contains a chained jar
937
							this.state.addClasspathValidation(javaProject); // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=185733
950
							this.state.addClasspathValidation(javaProject); // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=185733
938
							hasDelta = true;
951
							hasDelta = true;
939
						}
952
						}
Lines 1894-1900 Link Here
1894
					try {
1907
					try {
1895
						try {
1908
						try {
1896
							stopDeltas();
1909
							stopDeltas();
1897
							checkProjectsBeingAddedOrRemoved(delta);
1910
							checkProjectsAndClasspathChanges(delta);
1911
1912
							// generate external archive change deltas
1913
							if (elementsToRefresh != null) {
1914
								createExternalArchiveDelta(elementsToRefresh, null);
1915
							}
1898
1916
1899
							// generate classpath change deltas
1917
							// generate classpath change deltas
1900
							if (this.classpathChanges.size() > 0) {
1918
							if (this.classpathChanges.size() > 0) {
Lines 1920-1944 Link Here
1920
										this.state.addExternalFolderChange(change.project, change.oldResolvedClasspath);
1938
										this.state.addExternalFolderChange(change.project, change.oldResolvedClasspath);
1921
									}
1939
									}
1922
								}
1940
								}
1941
								// process late coming external elements to refresh (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=212769 )
1942
								elementsToRefresh = this.state.removeExternalElementsToRefresh();
1943
								if (elementsToRefresh != null) {
1944
									hasDelta |= createExternalArchiveDelta(elementsToRefresh, null);
1945
								}
1923
								this.classpathChanges.clear();
1946
								this.classpathChanges.clear();
1924
								if (!hasDelta)
1947
								if (!hasDelta)
1925
									this.currentDelta = null;
1948
									this.currentDelta = null;
1926
							}
1949
							}
1927
1950
1928
							// add late coming elements to refresh (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=212769 )
1929
							if (elementsToRefresh == null) {
1930
								elementsToRefresh = this.state.removeExternalElementsToRefresh();
1931
							} else {
1932
								HashSet newElementsToRefresh = this.state.removeExternalElementsToRefresh();
1933
								if (newElementsToRefresh != null)
1934
									elementsToRefresh.addAll(newElementsToRefresh);
1935
							}
1936
1937
							// generate external archive change deltas
1938
							if (elementsToRefresh != null) {
1939
								createExternalArchiveDelta(elementsToRefresh, null);
1940
							}
1941
1942
							// generate Java deltas from resource changes
1951
							// generate Java deltas from resource changes
1943
							IJavaElementDelta translatedDelta = processResourceDelta(delta);
1952
							IJavaElementDelta translatedDelta = processResourceDelta(delta);
1944
							if (translatedDelta != null) {
1953
							if (translatedDelta != null) {
(-)model/org/eclipse/jdt/internal/core/ClasspathChange.java (-1 / +1 lines)
Lines 226-232 Link Here
226
226
227
			if (newResolvedClasspath == null) {
227
			if (newResolvedClasspath == null) {
228
				// another thread reset the resolved classpath, use a temporary PerProjectInfo
228
				// another thread reset the resolved classpath, use a temporary PerProjectInfo
229
				PerProjectInfo temporaryInfo = new PerProjectInfo(this.project.getProject());
229
				PerProjectInfo temporaryInfo = this.project.newTemporaryInfo();
230
				this.project.resolveClasspath(temporaryInfo, false/*don't use previous session values*/);
230
				this.project.resolveClasspath(temporaryInfo, false/*don't use previous session values*/);
231
				newRawClasspath = temporaryInfo.rawClasspath;
231
				newRawClasspath = temporaryInfo.rawClasspath;
232
				newResolvedClasspath = temporaryInfo.getResolvedClasspath();
232
				newResolvedClasspath = temporaryInfo.getResolvedClasspath();
(-)model/org/eclipse/jdt/core/JavaCore.java (-1 / +5 lines)
Lines 3234-3240 Link Here
3234
	 *   if the given variable entry could not be resolved to a valid classpath entry
3234
	 *   if the given variable entry could not be resolved to a valid classpath entry
3235
	 */
3235
	 */
3236
	public static IClasspathEntry getResolvedClasspathEntry(IClasspathEntry entry) {
3236
	public static IClasspathEntry getResolvedClasspathEntry(IClasspathEntry entry) {
3237
		return JavaModelManager.getJavaModelManager().getResolvedClasspathEntry(entry, false/*don't use previous session value*/);
3237
		return JavaModelManager.getJavaModelManager().resolveVariableEntry(entry, false/*don't use previous session value*/);
3238
	}
3238
	}
3239
3239
3240
3240
Lines 3929-3934 Link Here
3929
	 * accessible files patterns of the projects, and they will concatenate the non accessible files patterns of this entry
3929
	 * accessible files patterns of the projects, and they will concatenate the non accessible files patterns of this entry
3930
	 * with the non accessible files patterns of the project.
3930
	 * with the non accessible files patterns of the project.
3931
	 * </p>
3931
	 * </p>
3932
	 * <p>
3933
	 * Since 3.5, if the libray is a ZIP archive, the "Class-Path" clause (if any) in the "META-INF/MANIFEST.MF" is read
3934
	 * and referenced ZIP archives are added to the {@link IJavaProject#getResolvedClasspath(boolean) resolved classpath}.
3935
	 * </p>
3932
	 *
3936
	 *
3933
	 * @param path the path to the library
3937
	 * @param path the path to the library
3934
	 * @param sourceAttachmentPath the absolute path of the corresponding source archive or folder,
3938
	 * @param sourceAttachmentPath the absolute path of the corresponding source archive or folder,
(-)compiler/org/eclipse/jdt/internal/compiler/util/ManifestAnalyzer.java (+130 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2008 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.jdt.internal.compiler.util;
12
13
import java.io.IOException;
14
import java.io.Reader;
15
import java.util.ArrayList;
16
import java.util.List;
17
18
public class ManifestAnalyzer {
19
	private static final int
20
		START = 0,
21
		IN_CLASSPATH_HEADER = 1, // multistate
22
		PAST_CLASSPATH_HEADER = 2,
23
		SKIPPING_WHITESPACE = 3,
24
		READING_JAR = 4,
25
		CONTINUING = 5,
26
		SKIP_LINE = 6;
27
	private static final char[] CLASSPATH_HEADER_TOKEN =
28
		"Class-Path:".toCharArray(); //$NON-NLS-1$
29
	private int ClasspathSectionsCount;
30
	private ArrayList calledFilesNames;
31
	public boolean analyzeManifestContents(Reader reader) throws IOException {
32
		int state = START, substate = 0;
33
		StringBuffer currentJarToken = new StringBuffer();
34
		int currentChar;
35
		this.ClasspathSectionsCount = 0;
36
		this.calledFilesNames = null;
37
		for (;;) {
38
			currentChar = reader.read();
39
			switch (state) {
40
				case START:
41
					if (currentChar == -1) {
42
						return true;
43
					} else if (currentChar == CLASSPATH_HEADER_TOKEN[0]) {
44
						state = IN_CLASSPATH_HEADER;
45
						substate = 1;
46
					} else {
47
						state = SKIP_LINE;
48
					}
49
					break;
50
				case IN_CLASSPATH_HEADER:
51
					if (currentChar == -1) {
52
						return true;
53
					} else if (currentChar == '\n') {
54
						state = START;
55
					} else if (currentChar != CLASSPATH_HEADER_TOKEN[substate++]) {
56
						state = SKIP_LINE;
57
					} else if (substate == CLASSPATH_HEADER_TOKEN.length) {
58
						state = PAST_CLASSPATH_HEADER;
59
					}
60
					break;
61
				case PAST_CLASSPATH_HEADER:
62
					if (currentChar == ' ') {
63
						state = SKIPPING_WHITESPACE;
64
						this.ClasspathSectionsCount++;
65
					} else {
66
						return false;
67
					}
68
					break;
69
				case SKIPPING_WHITESPACE:
70
					if (currentChar == -1) {
71
						return true;
72
					} else if (currentChar == '\n') {
73
						state = CONTINUING;
74
					} else if (currentChar != ' ') {
75
						currentJarToken.append((char) currentChar);
76
						state = READING_JAR;
77
					}
78
					break;
79
				case CONTINUING:
80
					if (currentChar == -1) {
81
						return true;
82
					} else if (currentChar == '\n') {
83
						state = START;
84
					} else if (currentChar == ' ') {
85
						state = SKIPPING_WHITESPACE;
86
					} else if (currentChar == CLASSPATH_HEADER_TOKEN[0]) {
87
						state = IN_CLASSPATH_HEADER;
88
						substate = 1;
89
					} else if (this.calledFilesNames == null) {
90
						return false;
91
					} else {
92
						state = SKIP_LINE;
93
					}
94
					break;
95
				case SKIP_LINE:
96
					if (currentChar == -1) {
97
						return true;
98
					} else if (currentChar == '\n') {
99
						state = START;
100
					}
101
					break;
102
				case READING_JAR:
103
					if (currentChar == -1) {
104
						return false;
105
					} else if (currentChar == '\n' || currentChar == '\r') {
106
						// appends token below
107
						state = CONTINUING;
108
					} else if (currentChar == ' ') {
109
						// appends token below
110
						state = SKIPPING_WHITESPACE;
111
					} else {
112
						currentJarToken.append((char) currentChar);
113
						break;
114
					}
115
					if (this.calledFilesNames == null) {
116
						this.calledFilesNames = new ArrayList();
117
					}
118
					this.calledFilesNames.add(currentJarToken.toString());
119
					currentJarToken.setLength(0);
120
					break;
121
			}
122
		}
123
	}
124
	public int getClasspathSectionsCount() {
125
		return this.ClasspathSectionsCount;
126
	}
127
	public List getCalledFileNames() {
128
		return this.calledFilesNames;
129
	}
130
}
(-)src/org/eclipse/jdt/core/tests/util/Util.java (-4 / +6 lines)
Lines 349-358 Link Here
349
	if (pathsAndContents != null) {
349
	if (pathsAndContents != null) {
350
		compile(pathsAndContents, options, classpath, classesPath);
350
		compile(pathsAndContents, options, classpath, classesPath);
351
	}
351
	}
352
	for (int i = 0, l = extraPathsAndContents == null ? 0 : extraPathsAndContents.length; i < l; /* inc in loop */) {
352
	if (extraPathsAndContents != null) {
353
		File  outputFile = new File(classesPath, extraPathsAndContents[i++]);
353
		for (int i = 0, l = extraPathsAndContents == null ? 0 : extraPathsAndContents.length; i < l; /* inc in loop */) {
354
		outputFile.getParentFile().mkdirs();
354
			File  outputFile = new File(classesPath, extraPathsAndContents[i++]);
355
		Util.writeToFile(extraPathsAndContents[i++], outputFile.getAbsolutePath());
355
			outputFile.getParentFile().mkdirs();
356
			Util.writeToFile(extraPathsAndContents[i++], outputFile.getAbsolutePath());
357
		}
356
	}
358
	}
357
    zip(classesDir, jarPath);
359
    zip(classesDir, jarPath);
358
}
360
}

Return to bug 198572