1 /*******************************************************************************
2 * Copyright (c) 2000, 2018 IBM Corporation and others.
3 *
4 * This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License 2.0
6 * which accompanies this distribution, and is available at
7 * https://www.eclipse.org/legal/epl-2.0/
8 *
9 * SPDX-License-Identifier: EPL-2.0
10 *
11 * Contributors:
12 * IBM Corporation - initial API and implementation
13 *******************************************************************************/
14 package org.eclipse.jdt.core.tests.model;
15
16 import java.io.IOException;
17 import java.util.HashMap;
18 import java.util.Map;
19 import java.util.concurrent.atomic.AtomicInteger;
20 import java.util.concurrent.atomic.AtomicReference;
21
22 import org.eclipse.core.resources.*;
23 import org.eclipse.core.runtime.*;
24 import org.eclipse.core.runtime.preferences.IEclipsePreferences;
25 import org.eclipse.core.runtime.preferences.InstanceScope;
26 import org.eclipse.jdt.core.*;
27 import org.eclipse.jdt.core.tests.model.Semaphore.TimeOutException;
28 import org.eclipse.jdt.internal.core.ClasspathEntry;
29 import org.eclipse.jdt.internal.core.JavaModelManager;
30 import org.eclipse.jdt.internal.core.JavaModelStatus;
31 import org.eclipse.jdt.internal.core.JavaProject;
32 import org.eclipse.jdt.internal.core.UserLibrary;
33 import org.eclipse.jdt.internal.core.UserLibraryClasspathContainer;
34
35 import junit.framework.Test;
36
37 @SuppressWarnings({"rawtypes", "unchecked"})
38 public class ClasspathInitializerTests extends ModifyingResourceTests {
39
40 public static class DefaultVariableInitializer implements VariablesInitializer.ITestInitializer {
41 Map variableValues;
42
43 /*
44 * values is [<var name>, <var value>]*
45 */
DefaultVariableInitializer(String[] values)46 public DefaultVariableInitializer(String[] values) {
47 this.variableValues = new HashMap();
48 for (int i = 0; i < values.length; i+=2) {
49 this.variableValues.put(values[i], new Path(values[i+1]));
50 }
51 }
52
53 @Override
initialize(String variable)54 public void initialize(String variable) throws JavaModelException {
55 if (this.variableValues == null) return;
56 JavaCore.setClasspathVariable(
57 variable,
58 (IPath)this.variableValues.get(variable),
59 null);
60 }
61 }
62
63 // Simple container initializer, which keeps setting container to null
64 // (30920 - stackoverflow when setting container to null)
65 public class NullContainerInitializer implements ContainerInitializer.ITestInitializer {
66 public boolean hasRun = false;
67 @Override
allowFailureContainer()68 public boolean allowFailureContainer() {
69 return false; // allow the initializer to run again
70 }
71 @Override
initialize(IPath containerPath, IJavaProject project)72 public void initialize(IPath containerPath, IJavaProject project) throws CoreException {
73 this.hasRun = true;
74 JavaCore.setClasspathContainer(
75 containerPath,
76 new IJavaProject[] {project},
77 new IClasspathContainer[] { null },
78 null);
79 }
80 }
81
ClasspathInitializerTests(String name)82 public ClasspathInitializerTests(String name) {
83 super(name);
84 }
suite()85 public static Test suite() {
86 return buildModelTestSuite(ClasspathInitializerTests.class);
87 }
88 // Use this static initializer to specify subset for tests
89 // All specified tests which do not belong to the class are skipped...
90 static {
91 // Names of tests to run: can be "testBugXXXX" or "BugXXXX")
92 // TESTS_NAMES = new String[] { "testBug346002" };
93 // Numbers of tests to run: "test<number>" will be run for each number of this array
94 // TESTS_NUMBERS = new int[] { 2, 12 };
95 // Range numbers of tests to run: all tests between "test<first>" and "test<last>" will be run for { first, last }
96 // TESTS_RANGE = new int[] { 16, -1 };
97 }
98 @Override
tearDown()99 protected void tearDown() throws Exception {
100 // Cleanup caches
101 JavaModelManager manager = JavaModelManager.getJavaModelManager();
102 manager.containers = new HashMap(5);
103 manager.variables = new HashMap(5);
104
105 super.tearDown();
106 }
107
testContainerInitializer01()108 public void testContainerInitializer01() throws CoreException {
109 try {
110 createProject("P1");
111 createFile("/P1/lib.jar", "");
112 ContainerInitializer.setInitializer(new DefaultContainerInitializer(new String[] {"P2", "/P1/lib.jar"}));
113 IJavaProject p2 = createJavaProject(
114 "P2",
115 new String[] {},
116 new String[] {"org.eclipse.jdt.core.tests.model.TEST_CONTAINER"},
117 "");
118 IPackageFragmentRoot root = p2.getPackageFragmentRoot(getFile("/P1/lib.jar"));
119 assertTrue("/P1/lib.jar should exist", root.exists());
120 } finally {
121 stopDeltas();
122 deleteProject("P1");
123 deleteProject("P2");
124 }
125 }
testContainerInitializer02()126 public void testContainerInitializer02() throws CoreException {
127 try {
128 createProject("P1");
129 createFile("/P1/lib.jar", "");
130 ContainerInitializer.setInitializer(new DefaultContainerInitializer(new String[] {"P2", "/P1/lib.jar"}));
131 IJavaProject p2 = createJavaProject(
132 "P2",
133 new String[] {},
134 new String[] {"org.eclipse.jdt.core.tests.model.TEST_CONTAINER"},
135 "");
136
137 // simulate state on startup
138 simulateExitRestart();
139
140 startDeltas();
141 p2.getResolvedClasspath(true);
142
143 assertDeltas(
144 "Unexpected delta on startup",
145 ""
146 );
147 } finally {
148 stopDeltas();
149 deleteProject("P1");
150 deleteProject("P2");
151 }
152 }
testContainerInitializer03()153 public void testContainerInitializer03() throws CoreException {
154 try {
155 createProject("P1");
156 createFile("/P1/lib.jar", "");
157 ContainerInitializer.setInitializer(new DefaultContainerInitializer(new String[] {"P2", "/P1/lib.jar"}));
158 createJavaProject(
159 "P2",
160 new String[] {},
161 new String[] {"org.eclipse.jdt.core.tests.model.TEST_CONTAINER"},
162 "");
163
164 // change value of TEST_CONTAINER
165 createFile("/P1/lib2.jar", "");
166 ContainerInitializer.setInitializer(new DefaultContainerInitializer(new String[] {"P2", "/P1/lib2.jar"}));
167
168 // simulate state on startup
169 simulateExitRestart();
170
171 startDeltas();
172 getJavaProject("P2").getResolvedClasspath(true);
173
174 assertDeltas(
175 "Unexpected delta on startup",
176 "P2[*]: {CHILDREN | RESOLVED CLASSPATH CHANGED}\n" +
177 " /P1/lib.jar[*]: {REMOVED FROM CLASSPATH}\n" +
178 " /P1/lib2.jar[*]: {ADDED TO CLASSPATH}"
179 );
180 } finally {
181 stopDeltas();
182 deleteProject("P1");
183 deleteProject("P2");
184 }
185 }
186 /* Ensure that initializer is not callled when resource tree is locked.
187 * (regression test for bug 29585 Core Exception as resource tree is locked initializing classpath container)
188 */
testContainerInitializer04()189 public void testContainerInitializer04() throws CoreException {
190 try {
191 createProject("P1");
192 createFile("/P1/lib.jar", "");
193 DefaultContainerInitializer initializer = new DefaultContainerInitializer(new String[] {"P2", "/P1/lib.jar"});
194 ContainerInitializer.setInitializer(initializer);
195 createJavaProject(
196 "P2",
197 new String[] {""},
198 new String[] {"org.eclipse.jdt.core.tests.model.TEST_CONTAINER"},
199 "");
200
201 // simulate state on startup
202 simulateExitRestart();
203
204 startDeltas();
205 createFile("/P2/X.java", "public class X {}");
206
207 assertEquals("Should not get exception", null, initializer.exception);
208
209 assertDeltas(
210 "Unexpected delta on startup",
211 "P2[*]: {CHILDREN}\n" +
212 " <project root>[*]: {CHILDREN}\n" +
213 " <default>[*]: {CHILDREN}\n" +
214 " X.java[+]: {}"
215 );
216 } finally {
217 stopDeltas();
218 deleteProject("P1");
219 deleteProject("P2");
220 }
221 }
222 /*
223 * 30920 - Stack overflow when container resolved to null
224 */
testContainerInitializer05()225 public void testContainerInitializer05() throws CoreException {
226 try {
227 NullContainerInitializer nullInitializer = new NullContainerInitializer();
228 ContainerInitializer.setInitializer(nullInitializer);
229 createJavaProject(
230 "P1",
231 new String[] {""},
232 new String[] {"org.eclipse.jdt.core.tests.model.TEST_CONTAINER"},
233 "");
234
235 // simulate state on startup
236 simulateExitRestart();
237
238 startDeltas();
239
240 // will trigger classpath resolution (with null container value)
241 createFile("/P1/X.java", "public class X {}");
242 assertDeltas(
243 "Unexpected delta on startup",
244 "P1[*]: {CHILDREN}\n" +
245 " <project root>[*]: {CHILDREN}\n" +
246 " <default>[*]: {CHILDREN}\n" +
247 " X.java[+]: {}"
248 );
249 assertTrue("initializer did not run", nullInitializer.hasRun);
250
251 // next cp resolution request will rerun the initializer
252 waitForAutoBuild();
253 nullInitializer.hasRun = false; // reset
254 getJavaProject("P1").getResolvedClasspath(true);
255 assertTrue("initializer did not run", nullInitializer.hasRun); // initializer should have run again (since keep setting to null)
256
257 // assigning new (non-null) value to container
258 waitForAutoBuild();
259 createFile("/P1/lib.jar", "");
260 ContainerInitializer.setInitializer(new DefaultContainerInitializer(new String[] {"P1", "/P1/lib.jar"}));
261 clearDeltas();
262 getJavaProject("P1").getResolvedClasspath(true);
263 assertDeltas(
264 "Unexpected delta after setting container",
265 "P1[*]: {CHILDREN | RESOLVED CLASSPATH CHANGED}\n" +
266 " lib.jar[*]: {ADDED TO CLASSPATH}"
267 );
268
269 } catch (StackOverflowError e) {
270 e.printStackTrace();
271 assertTrue("stack overflow assigning container", false);
272 } finally {
273 stopDeltas();
274 deleteProject("P1");
275 }
276 }
277 /*
278 * Ensures that running the initializer during a reconcile operation just after workspace startup
279 * doesn't throw a NPE
280 * (regression test for bug 48818 NPE in delta processor)
281 */
testContainerInitializer06()282 public void testContainerInitializer06() throws CoreException {
283 ICompilationUnit workingCopy = null;
284 try {
285 createProject("P1");
286 ContainerInitializer.setInitializer(new DefaultContainerInitializer(new String[] {"P2", ""}));
287 createJavaProject(
288 "P2",
289 new String[] {"src"},
290 new String[] {"org.eclipse.jdt.core.tests.model.TEST_CONTAINER"},
291 "bin");
292 createFile(
293 "/P2/src/X,java",
294 "public class X {\n" +
295 "}"
296 );
297
298 // change value of TEST_CONTAINER
299 ContainerInitializer.setInitializer(new DefaultContainerInitializer(new String[] {"P2", "/P1"}));
300
301 // simulate state on startup
302 simulateExitRestart();
303
304 startDeltas();
305 workingCopy = getCompilationUnit("/P2/src/X.java");
306 workingCopy.becomeWorkingCopy(null);
307
308 assertWorkingCopyDeltas(
309 "Unexpected delta on startup",
310 "P2[*]: {CHILDREN}\n" +
311 " src[*]: {CHILDREN}\n" +
312 " <default>[*]: {CHILDREN}\n" +
313 " [Working copy] X.java[+]: {PRIMARY WORKING COPY}"
314 );
315 } finally {
316 stopDeltas();
317 if (workingCopy != null) workingCopy.discardWorkingCopy();
318 deleteProject("P1");
319 deleteProject("P2");
320 }
321 }
322 /*
323 * Ensure that an OperationCanceledException goes through
324 * (regression test for bug 59363 Should surface cancellation exceptions)
325 */
testContainerInitializer07()326 public void testContainerInitializer07() throws CoreException {
327 try {
328 boolean gotException = false;
329 try {
330 ContainerInitializer.setInitializer(new DefaultContainerInitializer(new String[] {"P1", "/P1/lib.jar"}) {
331 @Override
332 public void initialize(IPath containerPath, IJavaProject project) throws CoreException {
333 throw new OperationCanceledException("test");
334 }});
335 IJavaProject p1 = createJavaProject(
336 "P1",
337 new String[] {},
338 new String[] {"org.eclipse.jdt.core.tests.model.TEST_CONTAINER"},
339 "");
340 p1.getResolvedClasspath(true);
341 } catch (OperationCanceledException e) {
342 gotException = true;
343 }
344 assertTrue("Should get an OperationCanceledException", gotException);
345 } finally {
346 stopDeltas();
347 deleteProject("P1");
348 }
349 }
350 /*
351 * Ensure that the stack doesn't blow up if initializer is missbehaving
352 * (regression test for bug 61052 Flatten cp container initialization)
353 */
testContainerInitializer08()354 public void testContainerInitializer08() throws CoreException {
355 final int projectLength = 10;
356 final String[] projects = new String[projectLength];
357 for (int i = 0; i < projectLength; i++) {
358 projects[i] = "P" + i;
359 }
360 try {
361 String[] projectRefs = new String[(projectLength-1) * 2];
362 for (int i = 0; i < projectLength-1; i++) {
363 projectRefs[i*2] = "P" + i;
364 projectRefs[(i*2)+1] = "/P" + i + "/test.jar";
365 }
366 ContainerInitializer.setInitializer(new DefaultContainerInitializer(projectRefs) {
367 void foo(int n) {
368 if (n > 0) {
369 foo(n-1);
370 return;
371 }
372 IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
373 for (int i = 0; i < projectLength-1; i++) {
374 try {
375 JavaCore.create(root.getProject(projects[i])).getResolvedClasspath(true);
376 } catch (JavaModelException e) {
377 // project doesn't exist: ignore
378 }
379 }
380 }
381 @Override
382 public void initialize(IPath containerPath, IJavaProject project) throws CoreException {
383 foo(500);
384 super.initialize(containerPath, project);
385 }
386 });
387 JavaCore.run(new IWorkspaceRunnable() {
388 public void run(IProgressMonitor monitor) throws CoreException {
389 for (int i = 0; i < projectLength; i++) {
390 createProject(projects[i]);
391 editFile(
392 "/" + projects[i] + "/.project",
393 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
394 "<projectDescription>\n" +
395 " <name>" + projects[i] + "</name>\n" +
396 " <comment></comment>\n" +
397 " <projects>\n" +
398 (i == 0 ? "" : "<project>" + projects[i-1] + "</project>\n") +
399 " </projects>\n" +
400 " <buildSpec>\n" +
401 " <buildCommand>\n" +
402 " <name>org.eclipse.jdt.core.javabuilder</name>\n" +
403 " <arguments>\n" +
404 " </arguments>\n" +
405 " </buildCommand>\n" +
406 " </buildSpec>\n" +
407 " <natures>\n" +
408 " <nature>org.eclipse.jdt.core.javanature</nature>\n" +
409 " </natures>\n" +
410 "</projectDescription>"
411 );
412 createFile(
413 "/" + projects[i] + "/.classpath",
414 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
415 "<classpath>\n" +
416 (i == 0 ? "" : "<classpathentry kind=\"src\" path=\"/" + projects[i-1] + "\"/>\n") +
417 " <classpathentry kind=\"con\" path=\"org.eclipse.jdt.core.tests.model.TEST_CONTAINER\"/>\n" +
418 " <classpathentry kind=\"output\" path=\"\"/>\n" +
419 "</classpath>"
420 );
421 }
422 }
423 }, null);
424 getJavaProject("P0").getResolvedClasspath(true);
425 } finally {
426 stopDeltas();
427 deleteProjects(projects);
428 }
429 }
430 /*
431 * Ensure that a StackOverFlowError is not thrown if the initializer asks for the resolved classpath
432 * that is being resolved.
433 * (regression test for bug 61040 Should add protect for reentrance to #getResolvedClasspath)
434 */
testContainerInitializer09()435 public void testContainerInitializer09() throws CoreException {
436 try {
437 DefaultContainerInitializer initializer = new DefaultContainerInitializer(new String[] {"P1", "/P1/lib.jar"}) {
438 @Override
439 protected DefaultContainer newContainer(char[][] libPaths) {
440 return new DefaultContainer(libPaths) {
441 @Override
442 public IClasspathEntry[] getClasspathEntries() {
443 try {
444 getJavaProject("P1").getResolvedClasspath(true);
445 } catch (JavaModelException e) {
446 // project doesn't exist: ignore
447 }
448 return super.getClasspathEntries();
449 }
450 };
451 }
452 };
453 ContainerInitializer.setInitializer(initializer);
454 JavaCore.run(new IWorkspaceRunnable() {
455 public void run(IProgressMonitor monitor) throws CoreException {
456 createProject("P1");
457 editFile(
458 "/P1/.project",
459 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
460 "<projectDescription>\n" +
461 " <name>P1</name>\n" +
462 " <comment></comment>\n" +
463 " <projects>\n" +
464 " </projects>\n" +
465 " <buildSpec>\n" +
466 " <buildCommand>\n" +
467 " <name>org.eclipse.jdt.core.javabuilder</name>\n" +
468 " <arguments>\n" +
469 " </arguments>\n" +
470 " </buildCommand>\n" +
471 " </buildSpec>\n" +
472 " <natures>\n" +
473 " <nature>org.eclipse.jdt.core.javanature</nature>\n" +
474 " </natures>\n" +
475 "</projectDescription>"
476 );
477 createFile(
478 "/P1/.classpath",
479 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
480 "<classpath>\n" +
481 " <classpathentry kind=\"con\" path=\"org.eclipse.jdt.core.tests.model.TEST_CONTAINER\"/>\n" +
482 " <classpathentry kind=\"output\" path=\"\"/>\n" +
483 "</classpath>"
484 );
485 }
486 }, null);
487 getJavaProject("P1").getResolvedClasspath(true);
488 } finally {
489 stopDeltas();
490 ContainerInitializer.setInitializer(null);
491 deleteProject("P1");
492 }
493 }
494 /*
495 * Ensure that creating a Java project initializes a container and refreshes the external jar at the same time
496 * without throwing a ConcurrentModificationException
497 * (regression test for bug 63534 ConcurrentModificationException after "catching up")
498 */
testContainerInitializer10()499 public void testContainerInitializer10() throws CoreException {
500 class LogListener implements ILogListener {
501 IStatus loggedStatus;
502 public void logging(IStatus status, String plugin) {
503 this.loggedStatus = status;
504 }
505 }
506 LogListener listener = new LogListener();
507 try {
508 Platform.addLogListener(listener);
509 final IJavaProject p1 = createJavaProject("P1");
510 final IJavaProject p2 = createJavaProject("P2");
511 ContainerInitializer.setInitializer(new DefaultContainerInitializer(new String[] {"P3", "/P1"}) {
512 @Override
513 public void initialize(IPath containerPath, IJavaProject project) throws CoreException {
514 super.initialize(containerPath, project);
515 getJavaModel().refreshExternalArchives(new IJavaElement[] {p1}, null);
516 }
517 });
518 getWorkspace().run(new IWorkspaceRunnable() {
519 public void run(IProgressMonitor monitor) throws CoreException {
520 p2.setRawClasspath(new IClasspathEntry[] {JavaCore.newSourceEntry(new Path("/P2/src"))}, new Path("/P2/bin"), null);
521 createProject("P3");
522 editFile(
523 "/P3/.project",
524 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
525 "<projectDescription>\n" +
526 " <name>P3</name>\n" +
527 " <comment></comment>\n" +
528 " <projects>\n" +
529 " </projects>\n" +
530 " <buildSpec>\n" +
531 " <buildCommand>\n" +
532 " <name>org.eclipse.jdt.core.javabuilder</name>\n" +
533 " <arguments>\n" +
534 " </arguments>\n" +
535 " </buildCommand>\n" +
536 " </buildSpec>\n" +
537 " <natures>\n" +
538 " <nature>org.eclipse.jdt.core.javanature</nature>\n" +
539 " </natures>\n" +
540 "</projectDescription>\n"
541 );
542 createFile(
543 "/P3/.classpath",
544 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
545 "<classpath>\n" +
546 " <classpathentry kind=\"src\" path=\"\"/>\n" +
547 " <classpathentry kind=\"var\" path=\"JCL_LIB\"/>\n" +
548 " <classpathentry kind=\"con\" path=\"org.eclipse.jdt.core.tests.model.TEST_CONTAINER\"/>\n" +
549 " <classpathentry kind=\"output\" path=\"\"/>\n" +
550 "</classpath>"
551 );
552 }
553 }, null);
554
555 assertEquals("Should not get any exception in log", null, listener.loggedStatus);
556 } finally {
557 Platform.removeLogListener(listener);
558 deleteProject("P1");
559 deleteProject("P2");
560 deleteProject("P3");
561 }
562 }
563 /*
564 * Ensure that a classpath initializer is not run on shutdown
565 * (regression test for bug 93941 Classpath initialization on shutdown)
566 */
testContainerInitializer11()567 public void testContainerInitializer11() throws CoreException {
568 boolean hasExited = false;
569 try {
570 ContainerInitializer.setInitializer(null);
571 createJavaProject(
572 "P",
573 new String[] {},
574 new String[] {"org.eclipse.jdt.core.tests.model.TEST_CONTAINER"},
575 "");
576 simulateExitRestart();
577 DefaultContainerInitializer initializer = new DefaultContainerInitializer(new String[] {}) {
578 @Override
579 public void initialize(IPath containerPath,IJavaProject project) throws CoreException {
580 assertTrue("Should not initialize container on shutdown", false);
581 }
582 };
583 ContainerInitializer.setInitializer(initializer);
584 simulateExit();
585 hasExited = true;
586 } finally {
587 ContainerInitializer.setInitializer(null);
588 if (hasExited)
589 simulateRestart();
590 deleteProject("P");
591 }
592 }
593
594 /*
595 * Ensure that the initializer is removed from the cache when the project is deleted
596 * (regression test for bug 116072 cached classpath containers not removed when project deleted)
597 */
testContainerInitializer12()598 public void testContainerInitializer12() throws CoreException {
599 try {
600 ContainerInitializer.setInitializer(new DefaultContainerInitializer(new String[] {"P1", "/P1/lib.jar"}));
601 IJavaProject project = createJavaProject(
602 "P1",
603 new String[] {},
604 new String[] {"org.eclipse.jdt.core.tests.model.TEST_CONTAINER"},
605 "");
606 createFile("/P1/lib.jar", "");
607 IPackageFragmentRoot root = project.getPackageFragmentRoot(getFile("/P1/lib.jar"));
608 assertTrue("/P1/lib.jar should exist", root.exists());
609 deleteProject("P1");
610
611 class Initializer extends DefaultContainerInitializer {
612 boolean initialized;
613 public Initializer(String[] args) {
614 super(args);
615 }
616 @Override
617 public void initialize(IPath containerPath, IJavaProject p) throws CoreException {
618 super.initialize(containerPath, p);
619 this.initialized = true;
620 }
621 }
622 Initializer initializer = new Initializer(new String[] {"P1", "/P1/lib.jar"});
623 ContainerInitializer.setInitializer(initializer);
624 createJavaProject(
625 "P1",
626 new String[] {},
627 new String[] {"org.eclipse.jdt.core.tests.model.TEST_CONTAINER"},
628 "");
629 createFile("/P1/lib.jar", "");
630 assertTrue("/P1/lib.jar should exist", root.exists());
631 assertTrue("Should have been initialized", initializer.initialized);
632 } finally {
633 stopDeltas();
634 deleteProject("P1");
635 }
636 }
637
638 /*
639 * Ensures that no resource deta is reported if a container that was not initialized is initialized with null
640 * (regression test for bug 149043 Unresolvable classpath container leads to lots of scheduled jobs)
641 */
testContainerInitializer13()642 public void testContainerInitializer13() throws CoreException {
643 IResourceChangeListener listener = new IResourceChangeListener() {
644 StringBuffer buffer = new StringBuffer();
645 public void resourceChanged(IResourceChangeEvent event) {
646 this.buffer.append(event.getDelta().findMember(new Path("/P1")));
647 }
648 public String toString() {
649 return this.buffer.toString();
650 }
651 };
652 try {
653 NullContainerInitializer nullInitializer = new NullContainerInitializer();
654 ContainerInitializer.setInitializer(nullInitializer);
655 IJavaProject project = createJavaProject(
656 "P1",
657 new String[] {},
658 new String[] {"org.eclipse.jdt.core.tests.model.TEST_CONTAINER"},
659 "");
660
661 // simulate state on startup
662 simulateExitRestart();
663
664 getWorkspace().addResourceChangeListener(listener, IResourceChangeEvent.POST_CHANGE);
665
666 // force resolution of container
667 project.findPackageFragmentRoots(project.getRawClasspath()[0]);
668
669 assertEquals(
670 "Unexpected resource delta on startup",
671 "",
672 listener.toString()
673 );
674 } finally {
675 getWorkspace().removeResourceChangeListener(listener);
676 deleteProject("P1");
677 }
678 }
679
680 /*
681 * Ensures that a misbehaving container (that initializes another project than the one asked for) doesn't cause
682 * the container to be initialized again
683 * (regression test for bug 160005 Add protection about misbehaving container initializer)
684 */
testContainerInitializer14()685 public void testContainerInitializer14() throws CoreException {
686 try {
687 createProject("P1");
688 createFile("/P1/lib.jar", "");
689 class Container extends DefaultContainerInitializer {
690 int initializeCount = 0;
691 Container(String[] values) {
692 super(values);
693 }
694 @Override
695 public void initialize(IPath containerPath, IJavaProject project) throws CoreException {
696 this.initializeCount++;
697 super.initialize(containerPath, getJavaProject("P1"));
698 }
699 }
700 Container container = new Container(new String[] {"P2", "/P1/lib.jar"});
701 ContainerInitializer.setInitializer(container);
702 IJavaProject p2 = createJavaProject(
703 "P2",
704 new String[] {},
705 new String[] {"org.eclipse.jdt.core.tests.model.TEST_CONTAINER"},
706 "");
707 p2.getResolvedClasspath(true);
708 assertEquals("Unexpected number of initalizations", 1, container.initializeCount);
709 } finally {
710 stopDeltas();
711 deleteProject("P1");
712 deleteProject("P2");
713 }
714 }
715
716 /*
717 * Ensures that if a container is misbehaving (it doesn't initialize a project when asked for),
718 * then the resulting container's classpath is not null
719 * (regression test for bug 161846 Expanding a java project with invalid classpath container entries in Project Explorer causes CPU to stay at 100%)
720 */
testContainerInitializer15()721 public void testContainerInitializer15() throws CoreException {
722 try {
723 class Container extends DefaultContainerInitializer {
724 Container(String[] values) {
725 super(values);
726 }
727 @Override
728 public void initialize(IPath containerPath, IJavaProject project) throws CoreException {
729 }
730 }
731 Container container = new Container(new String[] {"P1", "/P1/lib.jar"});
732 ContainerInitializer.setInitializer(container);
733 IJavaProject p1 = createJavaProject(
734 "P1",
735 new String[] {},
736 new String[] {"org.eclipse.jdt.core.tests.model.TEST_CONTAINER"},
737 "");
738 IClasspathContainer classpathContainer = JavaCore.getClasspathContainer(new Path("org.eclipse.jdt.core.tests.model.TEST_CONTAINER"), p1);
739 assertClasspathEquals(classpathContainer.getClasspathEntries(), "");
740 } finally {
741 stopDeltas();
742 deleteProject("P1");
743 }
744 }
745 /*
746 * Ensure that an initializer cannot return a project entry that points to the project of the container (cycle).
747 */
testContainerInitializer16()748 public void testContainerInitializer16() throws CoreException {
749 try {
750 ContainerInitializer.setInitializer(new DefaultContainerInitializer(new String[] {"P1", "/P1"}));
751 JavaModelException exception = null;
752 try {
753 IJavaProject p1 = createJavaProject(
754 "P1",
755 new String[] {},
756 new String[] {"org.eclipse.jdt.core.tests.model.TEST_CONTAINER"},
757 "");
758 p1.getResolvedClasspath(true);
759 } catch (JavaModelException e) {
760 exception = e;
761 }
762 assertExceptionEquals(
763 "Unexpected expection",
764 "Project 'P1' cannot reference itself",
765 exception);
766 } finally {
767 stopDeltas();
768 deleteProject("P1");
769 }
770 }
771
772 /*
773 * Ensures that no resource deta is reported if a container is initialized right after startup to the same value it had before shutdown.
774 * (regression test for bug 175849 Project is touched on restart)
775 */
testContainerInitializer17()776 public void testContainerInitializer17() throws CoreException {
777 IResourceChangeListener listener = new IResourceChangeListener() {
778 StringBuffer buffer = new StringBuffer();
779 public void resourceChanged(IResourceChangeEvent event) {
780 this.buffer.append(event.getDelta().findMember(new Path("/P2")));
781 }
782 public String toString() {
783 return this.buffer.toString();
784 }
785 };
786 try {
787 createProject("P1");
788 createFile("/P1/lib.jar", "");
789 ContainerInitializer.setInitializer(new DefaultContainerInitializer(new String[] {"P2", "/P1/lib.jar", "P3", "/P1/lib.jar"}));
790 IJavaProject p2 = createJavaProject(
791 "P2",
792 new String[] {},
793 new String[] {"org.eclipse.jdt.core.tests.model.TEST_CONTAINER"},
794 "");
795 createJavaProject(
796 "P3",
797 new String[] {},
798 new String[] {"org.eclipse.jdt.core.tests.model.TEST_CONTAINER"},
799 "");
800
801 // simulate state on startup
802 simulateExitRestart();
803
804 getWorkspace().addResourceChangeListener(listener, IResourceChangeEvent.POST_CHANGE);
805
806 // initialize to the same value
807 ContainerInitializer.setInitializer(new DefaultContainerInitializer(new String[] {"P2", "/P1/lib.jar", "P3", "/P1/lib.jar"}) {
808 @Override
809 public void initialize(IPath containerPath, IJavaProject project) throws CoreException {
810 // simulate concurrency (another thread is initializing all containers in parallel and thus this flag is set to true)
811 JavaModelManager.getJavaModelManager().batchContainerInitializations = JavaModelManager.NEED_BATCH_INITIALIZATION;
812 super.initialize(containerPath, project);
813 }
814 });
815 p2.getResolvedClasspath(true);
816
817 assertEquals(
818 "Unexpected resource delta on container initialization",
819 "",
820 listener.toString()
821 );
822 } finally {
823 getWorkspace().removeResourceChangeListener(listener);
824 deleteProject("P1");
825 deleteProject("P2");
826 deleteProject("P3");
827 }
828 }
829 /*
830 * Ensures that an unbound container marker is created if container is reset to null
831 * (regression test for 182204 Deleting a JRE referenced by container does not result in unbound container problem)
832 */
testContainerInitializer18()833 public void testContainerInitializer18() throws CoreException {
834 try {
835 ContainerInitializer.setInitializer(new DefaultContainerInitializer(new String[] {"P1", "/P1/lib.jar"}));
836 IJavaProject p1 = createJavaProject(
837 "P1",
838 new String[] {},
839 new String[] {"org.eclipse.jdt.core.tests.model.TEST_CONTAINER"},
840 "");
841 createFile("/P1/lib.jar", "");
842 p1.getResolvedClasspath(true);
843 waitForAutoBuild();
844
845 ContainerInitializer.setInitializer(new DefaultContainerInitializer(new String[0]));
846 JavaCore.setClasspathContainer(new Path("org.eclipse.jdt.core.tests.model.TEST_CONTAINER"), new IJavaProject[] {p1}, new IClasspathContainer[] {null}, null);
847 assertBuildPathMarkers(
848 "Unexpected markers",
849 "Unbound classpath container: \'org.eclipse.jdt.core.tests.model.TEST_CONTAINER\' in project \'P1\'",
850 p1);
851 } finally {
852 deleteProject("P1");
853 }
854 }
855
856 /*
857 * Ensures that a container is not kept in the cache if no longer referenced on the classpath
858 * (regression test for 139446 [build path] bug in the Edit Library dialog box, when changing the default JRE, and switching from alternate JRE to workspace default)
859 */
testContainerInitializer19()860 public void testContainerInitializer19() throws CoreException {
861 try {
862 // setup
863 ContainerInitializer.setInitializer(new DefaultContainerInitializer(new String[] {"P1", "/P1/lib1.jar"}));
864 IJavaProject p1 = createJavaProject(
865 "P1",
866 new String[] {},
867 new String[] {"org.eclipse.jdt.core.tests.model.TEST_CONTAINER"},
868 "");
869 createFile("/P1/lib1.jar", "");
870 createFile("/P1/lib2.jar", "");
871 p1.getResolvedClasspath(true);
872 IClasspathEntry[] initialClasspath = p1.getRawClasspath();
873
874 // remove reference to container, change initializer, and add reference to container back
875 p1.setRawClasspath(new IClasspathEntry[0], null);
876 ContainerInitializer.setInitializer(new DefaultContainerInitializer(new String[] {"P1", "/P1/lib2.jar"}));
877 p1.setRawClasspath(initialClasspath, null);
878
879 assertClasspathEquals(
880 p1.getResolvedClasspath(true),
881 "/P1/lib2.jar[CPE_LIBRARY][K_BINARY][isExported:false]"
882 );
883 } finally {
884 deleteProject("P1");
885 }
886 }
887
888 /*
889 * Ensures that container a container is not kept in the cache if no longer referenced on the classpath
890 * (regression test for 136382 [classpath] Discard container if not referenced on classpath)
891 */
testContainerInitializer20()892 public void testContainerInitializer20() throws CoreException {
893 try {
894 IJavaProject p = createJavaProject("P");
895 final StringBuffer paths = new StringBuffer();
896 DefaultContainerInitializer initializer = new DefaultContainerInitializer(new String[] {"P", "/P/lib.jar"}) {
897 @Override
898 public void initialize(IPath containerPath, IJavaProject project) throws CoreException {
899 paths.append(containerPath);
900 paths.append('\n');
901 super.initialize(containerPath, project);
902 }
903 };
904 ContainerInitializer.setInitializer(initializer);
905
906 setClasspath(p, new IClasspathEntry[] {JavaCore.newContainerEntry(new Path("org.eclipse.jdt.core.tests.model.TEST_CONTAINER/JRE1"))});
907 setClasspath(p, new IClasspathEntry[] {JavaCore.newContainerEntry(new Path("org.eclipse.jdt.core.tests.model.TEST_CONTAINER/JRE2"))});
908 setClasspath(p, new IClasspathEntry[] {JavaCore.newContainerEntry(new Path("org.eclipse.jdt.core.tests.model.TEST_CONTAINER/JRE1"))});
909 assertStringEquals(
910 "org.eclipse.jdt.core.tests.model.TEST_CONTAINER/JRE1\n" +
911 "org.eclipse.jdt.core.tests.model.TEST_CONTAINER/JRE2\n" +
912 "org.eclipse.jdt.core.tests.model.TEST_CONTAINER/JRE1\n",
913 paths.toString(),
914 false);
915 } finally {
916 stopDeltas();
917 deleteProject("P");
918 }
919 }
920
testContainerInitializer21()921 public void testContainerInitializer21() throws CoreException {
922 try {
923 createProject("P1");
924 createExternalFolder("externalLib");
925 ContainerInitializer.setInitializer(new DefaultContainerInitializer(new String[] {"P2", getExternalResourcePath("externalLib")}));
926 IJavaProject p2 = createJavaProject(
927 "P2",
928 new String[] {},
929 new String[] {"org.eclipse.jdt.core.tests.model.TEST_CONTAINER"},
930 "");
931 IPackageFragmentRoot root = p2.getPackageFragmentRoot(getExternalResourcePath("externalLib"));
932 assertTrue(getExternalResourcePath("externalLib") + " should exist", root.exists());
933 } finally {
934 stopDeltas();
935 deleteExternalResource("externalLib");
936 deleteProject("P1");
937 deleteProject("P2");
938 }
939 }
940
testContainerInitializer22()941 public void testContainerInitializer22() throws CoreException {
942 try {
943 createProject("P1");
944 createExternalFile("externalLib.abc", "");
945 ContainerInitializer.setInitializer(new DefaultContainerInitializer(new String[] {"P2", getExternalResourcePath("externalLib.abc")}));
946 IJavaProject p2 = createJavaProject(
947 "P2",
948 new String[] {},
949 new String[] {"org.eclipse.jdt.core.tests.model.TEST_CONTAINER"},
950 "");
951 IPackageFragmentRoot root = p2.getPackageFragmentRoot(getExternalResourcePath("externalLib.abc"));
952 assertTrue(getExternalResourcePath("externalLib.abc") + " should exist", root.exists());
953 } finally {
954 stopDeltas();
955 deleteExternalResource("externalLib.abc");
956 deleteProject("P1");
957 deleteProject("P2");
958 }
959 }
960
testContainerInitializer23()961 public void testContainerInitializer23() throws CoreException {
962 try {
963 createProject("P1");
964 IFile lib = createFile("/P1/internalLib.abc", "");
965 ContainerInitializer.setInitializer(new DefaultContainerInitializer(new String[] {"P2", "/P1/internalLib.abc"}));
966 IJavaProject p2 = createJavaProject(
967 "P2",
968 new String[] {},
969 new String[] {"org.eclipse.jdt.core.tests.model.TEST_CONTAINER"},
970 "");
971 IPackageFragmentRoot root = p2.getPackageFragmentRoot(lib);
972 assertTrue("/P1/internalLib.abc should exist", root.exists());
973 } finally {
974 stopDeltas();
975 deleteExternalResource("externalLib.abc");
976 deleteProject("P1");
977 deleteProject("P2");
978 }
979 }
980
981 /*
982 * Ensures that the value of a resolved classpath is correct if another thread is resolving the classpath concurrently
983 * (regression test for https://bugs.eclipse.org/bugs/show_bug.cgi?id=232478 )
984 */
testContainerInitializer24()985 public void testContainerInitializer24() throws Exception {
986 BPThread.TIMEOUT = 30000; // wait 30s max
987 BPThread thread = new BPThread("getResolvedClasspath()");
988 ClasspathResolutionBreakpointListener listener = new ClasspathResolutionBreakpointListener(new BPThread[] {thread});
989 try {
990 createProject("P1");
991 createFile("/P1/lib.jar", "");
992 ContainerInitializer.setInitializer(new DefaultContainerInitializer(new String[] {"P2", "/P1/lib.jar"}));
993 final JavaProject project2 = (JavaProject) createJavaProject(
994 "P2",
995 new String[] {},
996 new String[] {"org.eclipse.jdt.core.tests.model.TEST_CONTAINER"},
997 "");
998 simulateExit();
999 try {
1000 deleteResource(JavaCore.getPlugin().getStateLocation().append("variablesAndContainers.dat").toFile());
1001 } finally {
1002 simulateRestart();
1003 }
1004
1005 JavaProject.addCPResolutionBPListener(listener);
1006 thread.start(new Runnable() {
1007 @Override
1008 public void run() {
1009 try {
1010 project2.getResolvedClasspath();
1011 } catch (JavaModelException e) {
1012 e.printStackTrace();
1013 }
1014 }
1015 });
1016 thread.runToBP(1);
1017 thread.runToBP(2);
1018 thread.runToBP(3);
1019
1020 IClasspathEntry[] classpath = project2.getResolvedClasspath();
1021 assertClasspathEquals(
1022 classpath,
1023 "/P1/lib.jar[CPE_LIBRARY][K_BINARY][isExported:false]"
1024 );
1025
1026 } finally {
1027 JavaProject.removeCPResolutionBPListener(listener);
1028 thread.runToEnd();
1029 deleteProjects(new String[] {"P1", "P2"});
1030 }
1031 }
1032
1033 /*
1034 * Ensures that the project references are updated on startup if the initializer gives a different value.
1035 */
testContainerInitializer25()1036 public void testContainerInitializer25() throws CoreException {
1037 try {
1038 createProject("P1");
1039 createFile("/P1/lib.jar", "");
1040 ContainerInitializer.setInitializer(new DefaultContainerInitializer(new String[] {"P2", "/P1/lib.jar"}));
1041 IJavaProject p2 = createJavaProject(
1042 "P2",
1043 new String[] {},
1044 new String[] {"org.eclipse.jdt.core.tests.model.TEST_CONTAINER"},
1045 "");
1046 ContainerInitializer.setInitializer(new DefaultContainerInitializer(new String[] {"P2", "/P1"}));
1047
1048 // simulate state on startup
1049 simulateExitRestart();
1050
1051 p2.getResolvedClasspath(true);
1052 assertResourcesEqual(
1053 "Unexpected project references on startup",
1054 "/P1",
1055 p2.getProject().getReferencedProjects());
1056 } finally {
1057 deleteProject("P1");
1058 deleteProject("P2");
1059 }
1060 }
1061
1062
1063 /*
1064 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=327471
1065 * [java.io.EOFException at java.io.DataInputStream.readInt(Unknown Source)]
1066 * This test ensures that there is no exception on a restart of eclipse after
1067 * the project is closed after the workspace save
1068 */
testContainerInitializer26()1069 public void testContainerInitializer26() throws CoreException {
1070 try {
1071 createProject("P1");
1072 createFile("/P1/lib.jar", "");
1073 ContainerInitializer.setInitializer(new DefaultContainerInitializer(new String[] {"P2", "/P1/lib.jar"}));
1074 IJavaProject p2 = createJavaProject(
1075 "P2",
1076 new String[] {},
1077 new String[] {"org.eclipse.jdt.core.tests.model.TEST_CONTAINER"},
1078 "");
1079 ContainerInitializer.setInitializer(new DefaultContainerInitializer(new String[] {"P2", "/P1"}));
1080
1081 waitForAutoBuild();
1082 getWorkspace().save(true/*full save*/, null/*no progress*/);
1083 p2.getProject().close(null); // close the project after the save and before the shutdown
1084 JavaModelManager.getJavaModelManager().shutdown();
1085
1086 startLogListening();
1087 simulateRestart();
1088 assertLogEquals(""); // no error should be logged
1089
1090 } finally {
1091 stopLogListening();
1092 deleteProject("P1");
1093 deleteProject("P2");
1094 }
1095 }
testVariableInitializer01()1096 public void testVariableInitializer01() throws CoreException {
1097 try {
1098 createProject("P1");
1099 createFile("/P1/lib.jar", "");
1100 VariablesInitializer.setInitializer(new DefaultVariableInitializer(new String[] {"TEST_LIB", "/P1/lib.jar"}));
1101 IJavaProject p2 = createJavaProject("P2", new String[] {}, new String[] {"TEST_LIB"}, "");
1102 IPackageFragmentRoot root = p2.getPackageFragmentRoot(getFile("/P1/lib.jar"));
1103 assertTrue("/P1/lib.jar should exist", root.exists());
1104 } finally {
1105 deleteProject("P1");
1106 deleteProject("P2");
1107 VariablesInitializer.reset();
1108 }
1109 }
testVariableInitializer02()1110 public void testVariableInitializer02() throws CoreException {
1111 try {
1112 createProject("P1");
1113 createFile("/P1/lib.jar", "");
1114 createFile("/P1/src.zip", "");
1115 VariablesInitializer.setInitializer(new DefaultVariableInitializer(new String[] {
1116 "TEST_LIB", "/P1/lib.jar",
1117 "TEST_SRC", "/P1/src.zip",
1118 "TEST_ROOT", "src",
1119 }));
1120 IJavaProject p2 = createJavaProject("P2", new String[] {}, new String[] {"TEST_LIB,TEST_SRC,TEST_ROOT"}, "");
1121 IPackageFragmentRoot root = p2.getPackageFragmentRoot(getFile("/P1/lib.jar"));
1122 assertEquals("Unexpected source attachment path", "/P1/src.zip", root.getSourceAttachmentPath().toString());
1123 assertEquals("Unexpected source attachment root path", "src", root.getSourceAttachmentRootPath().toString());
1124 } finally {
1125 deleteProject("P1");
1126 deleteProject("P2");
1127 VariablesInitializer.reset();
1128 }
1129 }
testVariableInitializer03()1130 public void testVariableInitializer03() throws CoreException {
1131 try {
1132 createProject("P1");
1133 createFile("/P1/lib.jar", "");
1134 createFile("/P1/src.zip", "");
1135 String[] variableValues = new String[] {
1136 "TEST_LIB", "/P1/lib.jar",
1137 "TEST_SRC", "/P1/src.zip",
1138 "TEST_ROOT", "src",
1139 };
1140 VariablesInitializer.setInitializer(new DefaultVariableInitializer(variableValues));
1141 createJavaProject("P2", new String[] {}, new String[] {"TEST_LIB,TEST_SRC,TEST_ROOT"}, "");
1142
1143 // simulate state on startup
1144 simulateExitRestart();
1145
1146 startDeltas();
1147 //JavaModelManager.CP_RESOLVE_VERBOSE=true;
1148 getJavaProject("P2").getResolvedClasspath(true);
1149
1150 assertDeltas(
1151 "Unexpected delta on startup",
1152 ""
1153 );
1154 } finally {
1155 //JavaModelManager.CP_RESOLVE_VERBOSE=false;
1156 stopDeltas();
1157 deleteProject("P1");
1158 deleteProject("P2");
1159 VariablesInitializer.reset();
1160 }
1161 }
testVariableInitializer04()1162 public void testVariableInitializer04() throws CoreException {
1163 try {
1164 final StringBuffer buffer = new StringBuffer();
1165 VariablesInitializer.setInitializer(new VariablesInitializer.ITestInitializer() {
1166 @Override
1167 public void initialize(String variable) throws JavaModelException {
1168 buffer.append("Initializing " + variable + "\n");
1169 IPath path = new Path(variable.toLowerCase());
1170 buffer.append("Setting variable " + variable + " to " + path + "\n");
1171 JavaCore.setClasspathVariable(variable, path, null);
1172 }
1173 });
1174 createJavaProject("P", new String[] {}, new String[] {"TEST_LIB,TEST_SRC,TEST_ROOT"}, "");
1175 assertEquals(
1176 "Initializing TEST_LIB\n" +
1177 "Setting variable TEST_LIB to test_lib\n",
1178 buffer.toString());
1179 } finally {
1180 deleteProject("P");
1181 VariablesInitializer.reset();
1182 }
1183 }
testVariableInitializer05()1184 public void testVariableInitializer05() throws CoreException {
1185 try {
1186 final StringBuffer buffer = new StringBuffer();
1187 VariablesInitializer.setInitializer(new VariablesInitializer.ITestInitializer() {
1188 @Override
1189 public void initialize(String variable) throws JavaModelException {
1190 buffer.append("Initializing " + variable + "\n");
1191 IPath path = new Path(variable.toLowerCase());
1192 JavaCore.getClasspathVariable("TEST_SRC");
1193 buffer.append("Setting variable " + variable + " to " + path + "\n");
1194 JavaCore.setClasspathVariable(variable, path, null);
1195 }
1196 });
1197 createJavaProject("P", new String[] {}, new String[] {"TEST_LIB,TEST_SRC,TEST_ROOT"}, "");
1198 assertEquals(
1199 "Initializing TEST_LIB\n" +
1200 "Initializing TEST_SRC\n" +
1201 "Setting variable TEST_SRC to test_src\n" +
1202 "Setting variable TEST_LIB to test_lib\n",
1203 buffer.toString());
1204 } finally {
1205 deleteProject("P");
1206 VariablesInitializer.reset();
1207 }
1208 }
1209 /*
1210 * Ensures that if the initializer doesn't initialize a variable, it can be
1211 * initialized later on.
1212 */
testVariableInitializer06()1213 public void testVariableInitializer06() throws CoreException {
1214 try {
1215 final StringBuffer buffer = new StringBuffer();
1216 VariablesInitializer.setInitializer(new VariablesInitializer.ITestInitializer() {
1217 @Override
1218 public void initialize(String variable) {
1219 // do nothing
1220 buffer.append("Ignoring request to initialize");
1221 }
1222 });
1223 IPath path = JavaCore.getClasspathVariable("TEST_SRC");
1224 assertEquals(
1225 "Unexpected value of TEST_SRC after initializer was called",
1226 null,
1227 path);
1228 IPath varValue = new Path("src.zip");
1229 JavaCore.setClasspathVariable("TEST_SRC", varValue, null);
1230 path = JavaCore.getClasspathVariable("TEST_SRC");
1231 assertEquals(
1232 "Unexpected value of TEST_SRC after setting it",
1233 varValue,
1234 path);
1235 } finally {
1236 VariablesInitializer.reset();
1237 }
1238 }
testVariableInitializer07()1239 public void testVariableInitializer07() throws CoreException {
1240 try {
1241 createProject("P1");
1242 createFile("/P1/lib.jar", "");
1243 createFile("/P1/src.zip", "");
1244 String[] variableValues = new String[] {
1245 "TEST_LIB", "/P1/lib.jar",
1246 "TEST_SRC", "/P1/src.zip",
1247 "TEST_ROOT", "src",
1248 };
1249 VariablesInitializer.setInitializer(new DefaultVariableInitializer(variableValues));
1250 createJavaProject("P2", new String[] {}, new String[] {"TEST_LIB,TEST_SRC,TEST_ROOT"}, "");
1251
1252 // change value of TEST_LIB
1253 createFile("/P1/lib2.jar", "");
1254 VariablesInitializer.setInitializer(new DefaultVariableInitializer(new String[] {
1255 "TEST_LIB", "/P1/lib2.jar",
1256 "TEST_SRC", "/P1/src.zip",
1257 "TEST_ROOT", "src",
1258 }));
1259
1260 // simulate state on startup
1261 simulateExitRestart();
1262
1263 startDeltas();
1264 //JavaModelManager.CP_RESOLVE_VERBOSE=true;
1265 getJavaProject("P2").getResolvedClasspath(true);
1266
1267 assertDeltas(
1268 "Unexpected delta on startup",
1269 "P2[*]: {CHILDREN | RESOLVED CLASSPATH CHANGED}\n" +
1270 " /P1/lib.jar[*]: {REMOVED FROM CLASSPATH}\n" +
1271 " /P1/lib2.jar[*]: {ADDED TO CLASSPATH}"
1272 );
1273 } finally {
1274 //JavaModelManager.CP_RESOLVE_VERBOSE=false;
1275 stopDeltas();
1276 deleteProject("P1");
1277 deleteProject("P2");
1278 VariablesInitializer.reset();
1279 }
1280 }
1281 /*
1282 * Ensure that an OperationCanceledException goes through
1283 * (regression test for bug 59363 Should surface cancellation exceptions)
1284 */
1285
testVariableInitializer08()1286 public void testVariableInitializer08() throws CoreException {
1287 try {
1288 boolean gotException = false;
1289 try {
1290 VariablesInitializer.setInitializer(new DefaultVariableInitializer(new String[] {"TEST_LIB", "/P1/lib.jar"}) {
1291 @Override
1292 public void initialize(String variable) throws JavaModelException {
1293 throw new OperationCanceledException("test");
1294 }
1295 });
1296 IJavaProject p1 = createJavaProject("P1", new String[] {}, new String[] {"TEST_LIB"}, "");
1297 p1.getResolvedClasspath(true);
1298 } catch (OperationCanceledException e) {
1299 gotException = true;
1300 }
1301 assertTrue("Should get an OperationCanceledException", gotException);
1302 } finally {
1303 deleteProject("P1");
1304 VariablesInitializer.reset();
1305 }
1306 }
1307
1308 /*
1309 * Ensure that removing a classpath variable while initializing it doesn't throw a StackOverFlowError
1310 * (regression test for bug 112609 StackOverflow when initializing Java Core)
1311 */
testVariableInitializer09()1312 public void testVariableInitializer09() throws CoreException {
1313 try {
1314 VariablesInitializer.setInitializer(new DefaultVariableInitializer(new String[] {"TEST_LIB", "/P1/lib.jar"}) {
1315 @Override
1316 public void initialize(String variable) throws JavaModelException {
1317 JavaCore.removeClasspathVariable("TEST_LIB", null);
1318 }
1319 });
1320 IJavaProject p1 = createJavaProject("P1", new String[] {}, new String[] {"TEST_LIB"}, "");
1321 IClasspathEntry[] resolvedClasspath = p1.getResolvedClasspath(true);
1322 assertClasspathEquals(
1323 resolvedClasspath,
1324 ""
1325 );
1326 } finally {
1327 deleteProject("P1");
1328 VariablesInitializer.reset();
1329 }
1330 }
1331 /*
1332 * Ensures that not initializing a classpath variable and asking for its value returns null
1333 * (regression test for bug 113110 TestFailures in DebugSuite)
1334 */
testVariableInitializer10()1335 public void testVariableInitializer10() throws CoreException {
1336 try {
1337 VariablesInitializer.setInitializer(new DefaultVariableInitializer(new String[] {"TEST_LIB", "/P1/lib.jar"}) {
1338 @Override
1339 public void initialize(String variable) throws JavaModelException {
1340 // don't initialize
1341 }
1342 });
1343 // force resolution
1344 JavaCore.getClasspathVariable("TEST_LIB");
1345 // second call should still be null
1346 assertEquals("TEST_LIB should be null", null, JavaCore.getClasspathVariable("TEST_LIB"));
1347 } finally {
1348 deleteProject("P1");
1349 VariablesInitializer.reset();
1350 }
1351 }
1352 /**
1353 * Bug 125965: [prefs] "Export/Import preferences" should let user to choose wich preference to export/import
1354 * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=125965"
1355 */
testVariableInitializer11()1356 public void testVariableInitializer11() throws CoreException {
1357 try {
1358 // Create initializer
1359 String varName = "TEST_LIB";
1360 String initialValue = "/P1/lib.jar";
1361 String newValue = "/tmp/file.jar";
1362 VariablesInitializer.setInitializer(new DefaultVariableInitializer(new String[] {varName, initialValue}));
1363 assertEquals("JavaCore classpath value should have been initialized", JavaCore.getClasspathVariable(varName).toString(), initialValue);
1364
1365 // Modify preference
1366 JavaModelManager manager = JavaModelManager.getJavaModelManager();
1367 IEclipsePreferences preferences = manager.getInstancePreferences();
1368 preferences.put(JavaModelManager.CP_VARIABLE_PREFERENCES_PREFIX+varName, newValue);
1369
1370 // verify that JavaCore preferences have been reset
1371 assertEquals("JavaCore classpath value should be unchanged", JavaCore.getClasspathVariable(varName).toString(), initialValue);
1372 assertEquals("JavaCore preferences value should be unchanged", preferences.get(varName, "X"), initialValue);
1373 } finally {
1374 VariablesInitializer.reset();
1375 }
1376 }
1377
1378 /**
1379 * @bug 138599: [model][classpath] Need a way to mark a classpath variable as deprecated
1380 * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=138599"
1381 */
testVariableInitializerDeprecated()1382 public void testVariableInitializerDeprecated() throws CoreException, IOException {
1383 try {
1384 // Create initializer
1385 String varName = "TEST_DEPRECATED";
1386 String filePath = "/P1/lib.jar";
1387 VariablesInitializer.setInitializer(new DefaultVariableInitializer(new String[] {varName, filePath}));
1388 assertEquals("JavaCore classpath value should have been initialized", JavaCore.getClasspathVariable(varName).toString(), filePath);
1389
1390 // Verify that Classpath Variable is deprecated
1391 assertEquals("JavaCore classpath variable should be deprecated", "Test deprecated flag", JavaCore.getClasspathVariableDeprecationMessage(varName));
1392
1393 // Create project
1394 IJavaProject project = createJavaProject("P1");
1395 addLibrary(project, "lib.jar", null, new String[0],
1396 new String[]{"META-INF/MANIFEST.MF",
1397 "Manifest-Version: 1.0\n"} ,
1398 JavaCore.VERSION_1_4);
1399 IClasspathEntry variable = JavaCore.newVariableEntry(new Path("TEST_DEPRECATED"), null, null);
1400 IJavaModelStatus status = JavaConventions.validateClasspathEntry(project, variable, false);
1401 assertStatus("Classpath variable 'TEST_DEPRECATED' in project 'P1' is deprecated: Test deprecated flag", status);
1402 assertFalse("Status should not be OK", status.isOK());
1403 assertEquals("Status should have WARNING severity", IStatus.WARNING, status.getSeverity());
1404 assertEquals("Status should have deprecated code", IJavaModelStatusConstants.DEPRECATED_VARIABLE, status.getCode());
1405 } finally {
1406 VariablesInitializer.reset();
1407 deleteProject("P1");
1408 }
1409 }
testVariableInitializerUnboundAndDeprecated()1410 public void testVariableInitializerUnboundAndDeprecated() throws CoreException {
1411 try {
1412 // Create initializer
1413 String varName = "TEST_DEPRECATED";
1414 String filePath = "/P1/lib.jar";
1415 VariablesInitializer.setInitializer(new DefaultVariableInitializer(new String[] {varName, filePath}));
1416 assertEquals("JavaCore classpath value should have been initialized", JavaCore.getClasspathVariable(varName).toString(), filePath);
1417
1418 // Verify that Classpath Variable is deprecated
1419 assertEquals("JavaCore classpath variable should be deprecated", "Test deprecated flag", JavaCore.getClasspathVariableDeprecationMessage(varName));
1420
1421 // Create project
1422 IJavaProject project = createJavaProject("P1");
1423 IClasspathEntry variable = JavaCore.newVariableEntry(new Path("TEST_DEPRECATED"), null, null);
1424 IJavaModelStatus status = JavaConventions.validateClasspathEntry(project, variable, false);
1425 assertStatus("Project 'P1' is missing required library: 'lib.jar'", status);
1426 assertFalse("Status should not be OK", status.isOK());
1427 assertEquals("Status should have WARNING severity", IStatus.ERROR, status.getSeverity());
1428 assertEquals("Status should have deprecated code", IJavaModelStatusConstants.INVALID_CLASSPATH, status.getCode());
1429 } finally {
1430 VariablesInitializer.reset();
1431 deleteProject("P1");
1432 }
1433 }
1434
1435 /**
1436 * @bug 156226: [model][classpath] Allow classpath variable to be marked as non modifiable
1437 * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=156226"
1438 */
testVariableInitializerReadOnly()1439 public void testVariableInitializerReadOnly() throws CoreException, IOException {
1440 try {
1441 // Create initializer
1442 String varName = "TEST_READ_ONLY";
1443 String path = "/P1/lib.jar";
1444 VariablesInitializer.setInitializer(new DefaultVariableInitializer(new String[] { varName, path }));
1445 assertEquals("JavaCore classpath value should have been initialized", JavaCore.getClasspathVariable(varName).toString(), path);
1446
1447 // verify that Classpath Variable is read-only
1448 assertTrue("JavaCore classpath variable should be read-only", JavaCore.isClasspathVariableReadOnly(varName));
1449
1450 // Create project
1451 IJavaProject project = createJavaProject("P1");
1452 addLibrary(project, "lib.jar", null, new String[0],
1453 new String[]{"META-INF/MANIFEST.MF",
1454 "Manifest-Version: 1.0\n"} ,
1455 JavaCore.VERSION_1_4);
1456 IClasspathEntry variable = JavaCore.newVariableEntry(new Path("TEST_READ_ONLY"), null, null);
1457 IJavaModelStatus status = JavaConventions.validateClasspathEntry(project, variable, false);
1458 assertStatus("OK", status);
1459 assertTrue("Status should be OK", status.isOK());
1460 assertEquals("Status should be VERIFIED_OK", JavaModelStatus.VERIFIED_OK, status);
1461 } finally {
1462 VariablesInitializer.reset();
1463 deleteProject("P1");
1464 }
1465 }
testVariableInitializerDeprecatedAndReadOnly()1466 public void testVariableInitializerDeprecatedAndReadOnly() throws CoreException, IOException {
1467 try {
1468 // Create initializer
1469 String varName = "TEST_DEPRECATED_READ_ONLY";
1470 String path = "/P1/lib.jar";
1471 VariablesInitializer.setInitializer(new DefaultVariableInitializer(new String[] { varName, path }));
1472 assertEquals("JavaCore classpath value should have been initialized", JavaCore.getClasspathVariable(varName).toString(), path);
1473
1474 // verify that Classpath Variable is read-only
1475 assertEquals("JavaCore classpath variable should be deprecated", "A deprecated and read-only initializer", JavaCore.getClasspathVariableDeprecationMessage(varName));
1476 assertTrue("JavaCore classpath variable should be read-only", JavaCore.isClasspathVariableReadOnly(varName));
1477
1478 // Create project
1479 IJavaProject project = createJavaProject("P1");
1480 addLibrary(project, "lib.jar", null, new String[0],
1481 new String[]{"META-INF/MANIFEST.MF",
1482 "Manifest-Version: 1.0\n"} ,
1483 JavaCore.VERSION_1_4);
1484 IClasspathEntry variable = JavaCore.newVariableEntry(new Path("TEST_DEPRECATED_READ_ONLY"), null, null);
1485 IJavaModelStatus status = JavaConventions.validateClasspathEntry(project, variable, false);
1486 assertStatus("Classpath variable 'TEST_DEPRECATED_READ_ONLY' in project 'P1' is deprecated: A deprecated and read-only initializer", status);
1487 assertFalse("Status should not be OK", status.isOK());
1488 assertEquals("Status should have WARNING severity", IStatus.WARNING, status.getSeverity());
1489 assertEquals("Status should have deprecated code", IJavaModelStatusConstants.DEPRECATED_VARIABLE, status.getCode());
1490 } finally {
1491 VariablesInitializer.reset();
1492 deleteProject("P1");
1493 }
1494 }
1495
1496 /**
1497 * @bug 172207: [model] Marker for deprecated classpath variable should always have WARNING severity
1498 * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=172207"
1499 */
testVariableInitializerBug172207()1500 public void testVariableInitializerBug172207() throws CoreException, IOException {
1501 try {
1502 // Create initializer
1503 String varName = "TEST_DEPRECATED_READ_ONLY";
1504 String path = "/P1/lib.jar";
1505 VariablesInitializer.setInitializer(new DefaultVariableInitializer(new String[] { varName, path }));
1506 assertEquals("JavaCore classpath value should have been initialized", JavaCore.getClasspathVariable(varName).toString(), path);
1507
1508 // verify that Classpath Variable is read-only
1509 assertEquals("JavaCore classpath variable should be deprecated", "A deprecated and read-only initializer", JavaCore.getClasspathVariableDeprecationMessage(varName));
1510 assertTrue("JavaCore classpath variable should be read-only", JavaCore.isClasspathVariableReadOnly(varName));
1511
1512 // Create project
1513 IJavaProject project = createJavaProject("P1");
1514 addLibrary(project, "lib.jar", null, new String[0],
1515 new String[]{"META-INF/MANIFEST.MF",
1516 "Manifest-Version: 1.0\n"} ,
1517 JavaCore.VERSION_1_4);
1518 IClasspathEntry variable = JavaCore.newVariableEntry(new Path("TEST_DEPRECATED_READ_ONLY"), null, null);
1519 IClasspathEntry[] entries = project.getRawClasspath();
1520 int length = entries.length;
1521 System.arraycopy(entries, 0, entries = new IClasspathEntry[length+1], 0, length);
1522 entries[length] = variable;
1523 project.setRawClasspath(entries, null);
1524
1525 // verify markers
1526 waitForAutoBuild();
1527 IMarker[] markers = project.getProject().findMarkers(IJavaModelMarker.BUILDPATH_PROBLEM_MARKER, false, IResource.DEPTH_ZERO);
1528 sortMarkers(markers);
1529 assertMarkers("Unexpected marker(s)",
1530 "Classpath variable 'TEST_DEPRECATED_READ_ONLY' in project 'P1' is deprecated: A deprecated and read-only initializer",
1531 markers);
1532 assertEquals("Marker on deprecated variable should be a WARNING", IMarker.SEVERITY_WARNING, markers[0].getAttribute(IMarker.SEVERITY, -1));
1533 } finally {
1534 VariablesInitializer.reset();
1535 deleteProject("P1");
1536 }
1537 }
1538
1539 /**
1540 * @bug 186113: [model] classpath variable deprecation messages not initialized when called
1541 * @test a) Verify that deprecation message can be get through {@link JavaCore#getClasspathVariableDeprecationMessage(String)}
1542 * even if the variable initializer was not called before
1543 * b) Verify that message is not stored in cache when variable is not initialized (othwerise we could not free it up...)
1544 * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=186113"
1545 */
testVariableInitializerBug186113a()1546 public void testVariableInitializerBug186113a() throws CoreException {
1547 assertEquals("Invalid deprecation message!",
1548 "Test deprecated flag",
1549 JavaCore.getClasspathVariableDeprecationMessage("TEST_DEPRECATED")
1550 );
1551 }
testVariableInitializerBug186113b()1552 public void testVariableInitializerBug186113b() throws CoreException {
1553 JavaCore.getClasspathVariableDeprecationMessage("TEST_DEPRECATED");
1554 assertNull("Deprecation message should not have been stored!", JavaModelManager.getJavaModelManager().deprecatedVariables.get("TEST_DEPRECATED"));
1555 }
1556
1557 /**
1558 * @bug 200449: [model] classpath variable deprecation messages not initialized when called
1559 * @test a) Verify that deprecation message is well stored in cache when variable is iniatialized
1560 * b) Verify that deprecation message is well removed in cache when variable is removed
1561 * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=200449"
1562 */
testVariableInitializerBug200449()1563 public void testVariableInitializerBug200449() throws CoreException {
1564 try {
1565 // Create initializer
1566 String varName = "TEST_DEPRECATED";
1567 String filePath = "/P1/lib.jar";
1568 VariablesInitializer.setInitializer(new DefaultVariableInitializer(new String[] {varName, filePath}));
1569 JavaCore.getClasspathVariable(varName); // init variable
1570
1571 // Verify that deprecation message has been stored
1572 assertNotNull("Deprecation message should have been stored!", JavaModelManager.getJavaModelManager().deprecatedVariables.get("TEST_DEPRECATED"));
1573 } finally {
1574 VariablesInitializer.reset();
1575 deleteProject("P1");
1576 }
1577 }
testVariableInitializerBug200449b()1578 public void testVariableInitializerBug200449b() throws CoreException {
1579 // Verify that deprecated variable has been removed
1580 assertNull("Deprecation message should have been removed!", JavaModelManager.getJavaModelManager().deprecatedVariables.get("TEST_DEPRECATED"));
1581 }
1582
1583 /**
1584 * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=61872"
1585 */
testUserLibraryInitializer1()1586 public void testUserLibraryInitializer1() throws Exception {
1587 try {
1588 // Create new user library "SWT"
1589 ClasspathContainerInitializer initializer= JavaCore.getClasspathContainerInitializer(JavaCore.USER_LIBRARY_CONTAINER_ID);
1590 String libraryName = "SWT";
1591 IPath containerPath = new Path(JavaCore.USER_LIBRARY_CONTAINER_ID);
1592 UserLibraryClasspathContainer containerSuggestion = new UserLibraryClasspathContainer(libraryName);
1593 initializer.requestClasspathContainerUpdate(containerPath.append(libraryName), null, containerSuggestion);
1594
1595 // Create java project
1596 createJavaProject("p61872");
1597 IFile jarFile = createFile("/p61872/swt.jar", "");
1598 IFile srcFile = createFile("/p61872/swtsrc.zip", "");
1599
1600 // Modify user library
1601 IEclipsePreferences preferences = InstanceScope.INSTANCE.getNode(JavaCore.PLUGIN_ID);
1602 String propertyName = JavaModelManager.CP_USERLIBRARY_PREFERENCES_PREFIX+"SWT";
1603 StringBuffer propertyValue = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<userlibrary systemlibrary=\"false\" version=\"1\">\r\n<archive");
1604 String jarFullPath = getWorkspaceRoot().getLocation().append(jarFile.getFullPath()).toString();
1605 propertyValue.append(" path=\""+jarFullPath);
1606 propertyValue.append("\"/>\r\n</userlibrary>\r\n");
1607 preferences.put(propertyName, propertyValue.toString());
1608 preferences.flush();
1609
1610 // Modify project classpath
1611 editFile(
1612 "/p61872/.classpath",
1613 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
1614 "<classpath>\n" +
1615 " <classpathentry kind=\"con\" path=\"org.eclipse.jdt.USER_LIBRARY/SWT\"/>\n" +
1616 " <classpathentry kind=\"output\" path=\"\"/>\n" +
1617 "</classpath>"
1618 );
1619
1620 // Verify
1621 IClasspathEntry[] entries = getJavaProject("p61872").getResolvedClasspath(true);
1622 assertEquals("Invalid entries number in resolved classpath for project p61872!", 1, entries.length);
1623 assertEquals("Invalid path for project 61872 classpath entry!", jarFullPath.toLowerCase(), entries[0].getPath().toString().toLowerCase());
1624 assertNull("Project 61872 classpath entry should not have any source attached!", entries[0].getSourceAttachmentPath());
1625
1626 // Modify user library
1627 propertyValue = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<userlibrary systemlibrary=\"false\" version=\"1\">\r\n<archive");
1628 String srcFullPath = getWorkspaceRoot().getLocation().append(srcFile.getFullPath()).toString();
1629 propertyValue.append(" sourceattachment=\""+srcFullPath);
1630 propertyValue.append("\" path=\""+jarFullPath);
1631 propertyValue.append("\"/>\r\n</userlibrary>\r\n");
1632 preferences.put(propertyName, propertyValue.toString());
1633 preferences.flush();
1634
1635 // Verify
1636 entries = getJavaProject("p61872").getResolvedClasspath(true);
1637 assertEquals("Invalid entries number in resolved classpath for project p61872!", 1, entries.length);
1638 assertEquals("Invalid path for project 61872 classpath entry!", jarFullPath.toLowerCase(), entries[0].getPath().toString().toLowerCase());
1639 assertEquals("Invalid source attachement path for project 61872 classpath entry!", srcFullPath.toLowerCase(), entries[0].getSourceAttachmentPath().toString().toLowerCase());
1640 } finally {
1641 deleteProject("p61872");
1642 }
1643 }
1644 /**
1645 * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=346002"
1646 * @throws Exception
1647 */
testBug346002()1648 public void testBug346002() throws Exception {
1649 ClasspathContainerInitializer initializer = JavaCore.getClasspathContainerInitializer(JavaCore.USER_LIBRARY_CONTAINER_ID);
1650 String libraryName = "TEST";
1651 IPath containerPath = new Path(JavaCore.USER_LIBRARY_CONTAINER_ID);
1652 UserLibraryClasspathContainer containerSuggestion = new UserLibraryClasspathContainer(libraryName);
1653 initializer.requestClasspathContainerUpdate(containerPath.append(libraryName), null, containerSuggestion);
1654
1655 String libPath = "C:/test/test.jar";
1656
1657 IEclipsePreferences preferences = InstanceScope.INSTANCE.getNode(JavaCore.PLUGIN_ID);
1658 String propertyName = JavaModelManager.CP_USERLIBRARY_PREFERENCES_PREFIX+ "TEST";
1659
1660 StringBuffer propertyValue = new StringBuffer(
1661 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<userlibrary systemlibrary=\"false\" version=\"2\">\r\n<archive");
1662 propertyValue.append(" path=\"" + libPath + "\"/>\r\n");
1663 propertyValue.append("</userlibrary>\r\n");
1664 preferences.put(propertyName, propertyValue.toString());
1665
1666 propertyName = JavaModelManager.CP_USERLIBRARY_PREFERENCES_PREFIX + "INVALID";
1667 propertyValue = new StringBuffer(
1668 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<userlibrary systemlibrary=\"false\" version=\"2\">\r\n<archive");
1669 propertyValue.append(" path=\"\"/>");
1670 propertyValue.append("</userlibrary>\r\n");
1671 preferences.put(propertyName, propertyValue.toString());
1672 preferences.flush();
1673
1674 try {
1675 simulateExitRestart();
1676
1677 UserLibrary userLibrary = JavaModelManager.getUserLibraryManager().getUserLibrary(libraryName);
1678 assertNotNull(userLibrary);
1679 IPath entryPath = userLibrary.getEntries()[0].getPath();
1680 assertEquals("Path should be absolute", true, entryPath.isAbsolute());
1681
1682 userLibrary = JavaModelManager.getUserLibraryManager().getUserLibrary("INVALID");
1683 assertNull(userLibrary);
1684 }
1685 catch (ClasspathEntry.AssertionFailedException e) {
1686 fail("Should not throw AssertionFailedException");
1687 }
1688 }
1689
1690 /*
1691 * Ensures that when multiple threads enter the batch container initialization,
1692 * a second thread does not initialize a container if the first thread has already completed it
1693 */
testBug525597()1694 public void testBug525597() throws CoreException {
1695 try {
1696 createProject("P1");
1697 createFile("/P1/lib.jar", "");
1698 ContainerInitializer.setInitializer(new DefaultContainerInitializer(new String[] {"P2", "/P1/lib.jar", "P3", "/P1/lib.jar"}));
1699 createJavaProject(
1700 "P2",
1701 new String[] {},
1702 new String[] {"org.eclipse.jdt.core.tests.model.TEST_CONTAINER"},
1703 "");
1704 createJavaProject(
1705 "P3",
1706 new String[] {},
1707 new String[] {"org.eclipse.jdt.core.tests.model.TEST_CONTAINER"},
1708 "");
1709 createJavaProject(
1710 "P4",
1711 new String[] {},
1712 new String[] {"org.eclipse.jdt.core.tests.model.TEST_CONTAINER"},
1713 "");
1714
1715 // simulate state on startup
1716 simulateExitRestart();
1717
1718 Thread helperThread = new Thread() {
1719 @Override
1720 public void run() {
1721 try {
1722 JavaModelManager javaModelManager = JavaModelManager.getJavaModelManager();
1723 javaModelManager.containerRemove(null);
1724 javaModelManager.forceBatchInitializations(false);
1725 javaModelManager.getClasspathContainer(Path.EMPTY, null);
1726 } catch (JavaModelException e) {
1727 e.printStackTrace();
1728 }
1729 }
1730 };
1731 helperThread.setName("ClasspathInitializerTests Helper");
1732 AtomicInteger p3Counter=new AtomicInteger(0);
1733 Thread mainThread=Thread.currentThread();
1734 Semaphore s1=new Semaphore(0);
1735 Semaphore s2=new Semaphore(0);
1736
1737 ContainerInitializer.setInitializer(new DefaultContainerInitializer(new String[] {"P2", "/P1/lib.jar", "P3", "/P1/lib.jar"}) {
1738 @Override
1739 public void initialize(IPath containerPath, IJavaProject project) throws CoreException {
1740 if (Thread.currentThread() == helperThread) {
1741 if (project.getElementName().equals("P2")) {
1742 s1.release();
1743 try {
1744 s2.acquire(10000);
1745 } catch (TimeOutException e) {
1746 // ignore
1747 }
1748 } else if (project.getElementName().equals("P3")) {
1749 p3Counter.incrementAndGet();
1750 }
1751 } else if (Thread.currentThread() == mainThread) {
1752 if (project.getElementName().equals("P3")) {
1753 p3Counter.incrementAndGet();
1754 } else if (project.getElementName().equals("P4")) {
1755 // this point is reached when helperThread is still waiting in P2
1756 // and already has P3 on its TODO list.
1757 s2.release();
1758 }
1759 }
1760 super.initialize(containerPath, project);
1761 }
1762 });
1763 helperThread.start();
1764 // wait till helperThread has reached initializer
1765 try {
1766 s1.acquire(10000);
1767 } catch (TimeOutException e1) {
1768 // ignore
1769 }
1770 JavaModelManager.getJavaModelManager().getClasspathContainer(Path.EMPTY, null);
1771 try {
1772 helperThread.join();
1773 } catch (InterruptedException e) {
1774 e.printStackTrace();
1775 }
1776 assertEquals("P3 initialized more than once.", 1, p3Counter.get());
1777 } finally {
1778 deleteProject("P1");
1779 deleteProject("P2");
1780 deleteProject("P3");
1781 deleteProject("P4");
1782 }
1783 }
1784 /*
1785 * Ensures that when multiple threads enter the batch container initialization,
1786 * and two threads both initialize a container, only one result is used.
1787 */
testBug525597B()1788 public void testBug525597B() throws CoreException {
1789 try {
1790 createProject("P1");
1791 createFile("/P1/lib.jar", "");
1792 ContainerInitializer.setInitializer(new DefaultContainerInitializer(new String[] {"P2", "/P1/lib.jar", "P3", "/P1/lib.jar"}));
1793 createJavaProject(
1794 "P2",
1795 new String[] {},
1796 new String[] {"org.eclipse.jdt.core.tests.model.TEST_CONTAINER"},
1797 "");
1798 createJavaProject(
1799 "P3",
1800 new String[] {},
1801 new String[] {"org.eclipse.jdt.core.tests.model.TEST_CONTAINER"},
1802 "");
1803
1804 // simulate state on startup
1805 simulateExitRestart();
1806
1807 Thread helperThread = new Thread() {
1808 @Override
1809 public void run() {
1810 try {
1811 JavaModelManager javaModelManager = JavaModelManager.getJavaModelManager();
1812 javaModelManager.containerRemove(null);
1813 javaModelManager.forceBatchInitializations(false);
1814 javaModelManager.getClasspathContainer(Path.EMPTY, null);
1815 } catch (JavaModelException e) {
1816 e.printStackTrace();
1817 }
1818 }
1819 };
1820 helperThread.setName("ClasspathInitializerTests Helper");
1821 AtomicInteger p2Counter=new AtomicInteger(0);
1822 AtomicReference<IClasspathContainer> helperContainer=new AtomicReference<>();
1823 AtomicReference<IClasspathContainer> mainContainer=new AtomicReference<>();
1824 Thread mainThread=Thread.currentThread();
1825 Semaphore s1=new Semaphore(0);
1826 Semaphore s2=new Semaphore(0);
1827 Semaphore s3=new Semaphore(0);
1828 Semaphore s4=new Semaphore(0);
1829 AtomicReference<IJavaProject> p2Project=new AtomicReference<>();
1830
1831 ContainerInitializer.setInitializer(new DefaultContainerInitializer(new String[] {"P2", "/P1/lib.jar", "P3", "/P1/lib.jar"}) {
1832 @Override
1833 public void initialize(IPath containerPath, IJavaProject project) throws CoreException {
1834 if (Thread.currentThread() == helperThread) {
1835 if (project.getElementName().equals("P2")) {
1836 p2Project.set(project);
1837 s1.release();
1838 try {
1839 s2.acquire(10000);
1840 } catch (TimeOutException e) {
1841 // ignore
1842 }
1843 } else if (project.getElementName().equals("P3")) {
1844 s3.release();
1845 try {
1846 s4.acquire(10000);
1847 } catch (TimeOutException e) {
1848 // ignore
1849 }
1850 if (JavaModelManager.getJavaModelManager().containerBeingInitializedGet(p2Project.get(),
1851 containerPath) != null) {
1852 p2Counter.incrementAndGet();
1853 }
1854 helperContainer.set(JavaModelManager.getJavaModelManager().getClasspathContainer(containerPath, p2Project.get()));
1855 }
1856 } else if (Thread.currentThread() == mainThread) {
1857 if (project.getElementName().equals("P2")) {
1858 // this point is reached when helperThread is also still waiting in P2
1859 s2.release();
1860 } else if (project.getElementName().equals("P3")) {
1861 try {
1862 s3.acquire(10000);
1863 } catch (TimeOutException e) {
1864 // ignore
1865 }
1866 s4.release();
1867 if (JavaModelManager.getJavaModelManager().containerBeingInitializedGet(p2Project.get(),
1868 containerPath) != null) {
1869 p2Counter.incrementAndGet();
1870 }
1871 mainContainer.set(JavaModelManager.getJavaModelManager().getClasspathContainer(containerPath, p2Project.get()));
1872 }
1873 }
1874 super.initialize(containerPath, project);
1875 }
1876 });
1877 helperThread.start();
1878 // wait till helperThread has reached initializer
1879 try {
1880 s1.acquire(10000);
1881 } catch (TimeOutException e1) {
1882 // ignore
1883 }
1884 JavaModelManager.getJavaModelManager().getClasspathContainer(Path.EMPTY, null);
1885 try {
1886 helperThread.join();
1887 } catch (InterruptedException e) {
1888 e.printStackTrace();
1889 }
1890 assertEquals("more than one result for P2 used.", 1, p2Counter.get());
1891 assertEquals("main and helper threads did not see the same container.", helperContainer.get(), mainContainer.get());
1892 } finally {
1893 deleteProject("P1");
1894 deleteProject("P2");
1895 deleteProject("P3");
1896 }
1897 }
1898
1899 }
1900