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

Collapse All | Expand All

(-)a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/Util.java (+21 lines)
Lines 1348-1353 Link Here
1348
        }
1348
        }
1349
    }
1349
    }
1350
}
1350
}
1351
public static void zipFiles(File[] files, String zipPath) throws IOException {
1352
	File zipFile = new File(zipPath);
1353
    if (zipFile.exists()) {
1354
    	if (!delete(zipFile))
1355
        	throw new IOException("Could not delete " + zipPath);
1356
    	 // ensure the new zip file has a different timestamp than the previous one
1357
    	int timeToWait = 1000; // some platform (like Linux) have a 1s granularity)
1358
        waitAtLeast(timeToWait);
1359
    } else {
1360
    	zipFile.getParentFile().mkdirs();
1361
    }
1362
	ZipOutputStream zip = new ZipOutputStream(new FileOutputStream(zipFile));
1363
	for (int i = 0, length = files.length; i < length; i++) {
1364
        File file = files[i];
1365
        ZipEntry entry = new ZipEntry(file.getName());
1366
        zip.putNextEntry(entry);
1367
        zip.write(org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(file));
1368
        zip.closeEntry();
1369
    }
1370
	zip.close();
1371
}
1351
/**
1372
/**
1352
 * Returns the compilation errors / warnings for the given CompilationResult.
1373
 * Returns the compilation errors / warnings for the given CompilationResult.
1353
 *
1374
 *
(-)a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaIndexTests.java (+775 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2011 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.core.tests.model;
12
13
import java.io.File;
14
import java.io.IOException;
15
import java.net.URL;
16
17
import junit.framework.Test;
18
19
import org.eclipse.core.resources.IProject;
20
import org.eclipse.core.runtime.CoreException;
21
import org.eclipse.core.runtime.IPath;
22
import org.eclipse.core.runtime.Path;
23
import org.eclipse.jdt.core.IClasspathAttribute;
24
import org.eclipse.jdt.core.IClasspathEntry;
25
import org.eclipse.jdt.core.IJavaElement;
26
import org.eclipse.jdt.core.IJavaProject;
27
import org.eclipse.jdt.core.JavaCore;
28
import org.eclipse.jdt.core.index.*;
29
import org.eclipse.jdt.core.search.SearchEngine;
30
import org.eclipse.jdt.core.tests.util.Util;
31
import org.eclipse.jdt.internal.core.JavaModelManager;
32
33
public class JavaIndexTests extends AbstractJavaSearchTests  {
34
35
	static {
36
		// TESTS_NAMES = new String[] {"testMultipleProjects"};
37
	}
38
	public JavaIndexTests(String name) {
39
		super(name);
40
	}
41
42
	public static Test suite() {
43
		return buildModelTestSuite(JavaIndexTests.class);
44
	}
45
	// Test that the index file is really generated.
46
	public void testGenerateIndex() throws IOException {
47
		String indexFilePath = getExternalResourcePath("Test.index");
48
		String jarFilePath = getExternalResourcePath("Test.jar");
49
		try {
50
			createJar(new String[] {
51
					"pkg/Test.java",
52
					"package pkg;\n" +
53
					"public class Test {\n" +
54
					"  protected Test(int i) {}\n" +
55
					"}"}, jarFilePath);
56
			
57
			JavaIndexer.generateIndexForJar(jarFilePath, indexFilePath);
58
			assertTrue(new File(indexFilePath).exists());
59
		} finally {
60
			new File(indexFilePath).delete();
61
			new File(jarFilePath).delete();
62
		}
63
	}
64
	
65
	// Test that the index file and the jar in held after the index is created
66
	public void testDeleteIndexedFile() {
67
		String indexFilePath = getExternalResourcePath("Test.index");
68
		String jarFilePath = getExternalResourcePath("Test.jar");
69
		try {
70
			createJar(new String[] {
71
					"pkg/Test.java",
72
					"package pkg;\n" +
73
					"public class Test {\n" +
74
					"  protected Test(int i) {}\n" +
75
					"}"}, jarFilePath);
76
			JavaIndexer.generateIndexForJar(jarFilePath, indexFilePath);
77
			assertTrue("Could not delete the index file", new File(indexFilePath).delete());
78
			assertTrue("Could not delete the jar file", new File(jarFilePath).delete());
79
		} catch (IOException e) {
80
			assertFalse("Test failed", true);
81
		}
82
	}
83
	
84
	// Test that search works fine with the index file
85
	public void testUseIndex() throws CoreException, IOException {
86
		String indexFilePath = getExternalResourcePath("Test.index");
87
		String jarFilePath = getExternalResourcePath("Test.jar");
88
		try {
89
			createJar(new String[] {
90
					"pkg/Test.java",
91
					"package pkg;\n" +
92
					"public class Test {\n" +
93
					"  protected Test(int i) {}\n" +
94
					"}"}, jarFilePath);
95
			JavaIndexer.generateIndexForJar(jarFilePath, indexFilePath);
96
			long modified = new File(indexFilePath).lastModified();
97
			
98
			IJavaProject p = createJavaProject("P");
99
			Path libPath = new Path(jarFilePath);
100
			IClasspathAttribute attribute = JavaCore.newClasspathAttribute(IClasspathAttribute.INDEX_LOCATION_ATTRIBUTE_NAME, "file:///"+indexFilePath);
101
			IClasspathEntry entry = JavaCore.newLibraryEntry(libPath, null, null, null, new IClasspathAttribute[]{attribute}, false);
102
			setClasspath(p, new IClasspathEntry[] {entry});
103
			
104
			waitUntilIndexesReady();
105
			
106
			// Test that specified index file is really used
107
			java.io.File indexFile = JavaModelManager.getIndexManager().getIndex(libPath, false, false).getIndexFile();
108
			assertEquals("Specified index file is not being used", indexFilePath,indexFile.toString());
109
			
110
			// Test that search works properly 
111
			search("Test", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
112
			assertSearchResults(getExternalPath() + "Test.jar pkg.Test");
113
			
114
			// Ensure that the index file is not modified
115
			assertEquals(modified, new File(indexFilePath).lastModified());
116
		} finally {
117
			deleteProject("P");
118
			new File(indexFilePath).delete();
119
			new File(jarFilePath).delete();
120
		}
121
	}
122
	
123
	// Test that the same index file is used even after restarting
124
	public void testUseIndexAfterRestart() throws IOException, CoreException {
125
		String indexFilePath = getExternalResourcePath("Test.index");
126
		String jarFilePath = getExternalResourcePath("Test.jar");
127
		try {
128
			createJar(new String[] {
129
					"pkg/Test.java",
130
					"package pkg;\n" +
131
					"public class Test {\n" +
132
					"  protected Test(int i) {}\n" +
133
					"}"}, jarFilePath);
134
			JavaIndexer.generateIndexForJar(jarFilePath, indexFilePath);
135
			long modified = new File(indexFilePath).lastModified();
136
			IJavaProject p = createJavaProject("P");
137
			Path libPath = new Path(jarFilePath);
138
			IClasspathAttribute attribute = JavaCore.newClasspathAttribute(IClasspathAttribute.INDEX_LOCATION_ATTRIBUTE_NAME, "file:///"+indexFilePath);
139
			IClasspathEntry entry = JavaCore.newLibraryEntry(libPath, null, null, null, new IClasspathAttribute[]{attribute}, false);
140
			setClasspath(p, new IClasspathEntry[] {entry});
141
			waitUntilIndexesReady();
142
			
143
			search("Test", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
144
			assertSearchResults(getExternalPath() + "Test.jar pkg.Test");
145
			
146
			simulateExitRestart();
147
			getJavaModel().refreshExternalArchives(null, null);
148
			waitUntilIndexesReady();
149
			
150
			this.resultCollector = new JavaSearchResultCollector();
151
			search("Test", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
152
			assertSearchResults(getExternalPath() + "Test.jar pkg.Test");
153
			
154
			java.io.File indexFile = JavaModelManager.getIndexManager().getIndex(libPath, false, false).getIndexFile();
155
			assertEquals(indexFilePath,indexFile.toString());
156
			// Ensure that the file is not modified
157
			assertEquals(modified, new File(indexFilePath).lastModified());
158
		} finally {
159
			deleteProject("P");
160
			new File(indexFilePath).delete();
161
			new File(jarFilePath).delete();
162
		}
163
	}
164
	
165
	// Test that the same index file is used even after restarting
166
	public void testUseIndexInternalJarAfterRestart() throws IOException, CoreException {
167
		String indexFilePath = getExternalResourcePath("Test.index");
168
		String jarFilePath = "/P/Test.jar";
169
		try {
170
			IJavaProject p = createJavaProject("P");
171
			createJar(new String[] {
172
					"pkg/Test.java",
173
					"package pkg;\n" +
174
					"public class Test {\n" +
175
					"  protected Test(int i) {}\n" +
176
					"}"}, jarFilePath);
177
			JavaIndexer.generateIndexForJar(jarFilePath, indexFilePath);
178
			long modified = new File(indexFilePath).lastModified();
179
			IPath libPath = new Path(jarFilePath);
180
			IClasspathAttribute attribute = JavaCore.newClasspathAttribute(IClasspathAttribute.INDEX_LOCATION_ATTRIBUTE_NAME, "file:///"+indexFilePath);
181
			IClasspathEntry entry = JavaCore.newLibraryEntry(libPath, null, null, null, new IClasspathAttribute[]{attribute}, false);
182
			setClasspath(p, new IClasspathEntry[] {entry});
183
			waitUntilIndexesReady();
184
			
185
			search("Test", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
186
			assertSearchResults("\\P\\Test.jar pkg.Test");
187
			
188
			simulateExitRestart();
189
			getJavaModel().refreshExternalArchives(null, null);
190
			waitUntilIndexesReady();
191
			
192
			this.resultCollector = new JavaSearchResultCollector();
193
			search("Test", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
194
			assertSearchResults("\\P\\Test.jar pkg.Test");
195
			
196
			java.io.File indexFile = JavaModelManager.getIndexManager().getIndex(libPath, false, false).getIndexFile();
197
			assertEquals(indexFilePath,indexFile.toString());
198
			// Ensure that the file is not modified
199
			assertEquals(modified, new File(indexFilePath).lastModified());
200
		} finally {
201
			deleteProject("P");
202
			new File(indexFilePath).delete();
203
		}
204
	}
205
	
206
	// Test that a jar file that gets modified after the index is created doesn't return new changes. 
207
	// This behavior might have to be modified but.. 
208
	public void testModifyJarAfterIndex() throws CoreException, IOException {
209
		String indexFilePath = getExternalResourcePath("Test.index");
210
		String jarFilePath = getExternalResourcePath("Test.jar");
211
		try {
212
			createJar(new String[] {
213
					"pkg/Test.java",
214
					"package pkg;\n" +
215
					"public class Test {\n" +
216
					"  protected Test(int i) {}\n" +
217
					"}"}, jarFilePath);
218
			JavaIndexer.generateIndexForJar(jarFilePath, indexFilePath);
219
			createJar(new String[] {
220
					"pkg/Test.java",
221
					"package pkg;\n" +
222
					"public class Test {\n" +
223
					"  protected Test(int i) {}\n" +
224
					"}", 
225
					"pkg/NewTest.java",
226
					"package pkg;\n" +
227
					"public class NewTest {\n" +
228
					"  protected NewTest(int i) {}\n" +
229
					"}"}, jarFilePath);
230
			IJavaProject p = createJavaProject("P");
231
			Path libPath = new Path(jarFilePath);
232
			IClasspathAttribute attribute = JavaCore.newClasspathAttribute(IClasspathAttribute.INDEX_LOCATION_ATTRIBUTE_NAME, "file:///"+indexFilePath);
233
			IClasspathEntry entry = JavaCore.newLibraryEntry(libPath, null, null, null, new IClasspathAttribute[]{attribute}, false);
234
			setClasspath(p, new IClasspathEntry[] {entry});
235
			waitUntilIndexesReady();
236
			search("NewTest", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
237
			assertSearchResults("");
238
		} finally {
239
			deleteProject("P");
240
			new File(indexFilePath).delete();
241
			new File(jarFilePath).delete();
242
		}
243
	}
244
245
	// test a non-existent index
246
	public void testNonExistentIndex() throws CoreException, IOException {
247
		String indexFilePath = getExternalResourcePath("Test.index");
248
		String jarFilePath = getExternalResourcePath("Test.jar");
249
		try {
250
			createJar(new String[] {
251
					"pkg/Test.java",
252
					"package pkg;\n" +
253
					"public class Test {\n" +
254
					"  protected Test(int i) {}\n" +
255
					"}"}, jarFilePath);
256
			IJavaProject p = createJavaProject("P");
257
			Path libPath = new Path(jarFilePath);
258
			new File(indexFilePath).delete();
259
			IClasspathAttribute attribute = JavaCore.newClasspathAttribute(IClasspathAttribute.INDEX_LOCATION_ATTRIBUTE_NAME, "file:///"+indexFilePath);
260
			IClasspathEntry entry = JavaCore.newLibraryEntry(libPath, null, null, null, new IClasspathAttribute[]{attribute}, false);
261
			setClasspath(p, new IClasspathEntry[] {entry});
262
			waitUntilIndexesReady();
263
			search("Test", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
264
			assertSearchResults(getExternalPath() + "Test.jar pkg.Test");
265
			
266
		} finally {
267
			deleteProject("P");
268
			new File(indexFilePath).delete();
269
			new File(jarFilePath).delete();
270
		}
271
	}
272
	
273
	// test a non-existent index
274
	public void testNonExistentIndexRestart() throws CoreException, IOException {
275
		String indexFilePath = getExternalResourcePath("Test.index");
276
		String jarFilePath = getExternalResourcePath("Test.jar");
277
		try {
278
			createJar(new String[] {
279
					"pkg/Test.java",
280
					"package pkg;\n" +
281
					"public class Test {\n" +
282
					"  protected Test(int i) {}\n" +
283
					"}"}, jarFilePath);
284
			
285
			new File(indexFilePath).delete();
286
			
287
			IJavaProject p = createJavaProject("P");
288
			Path libPath = new Path(jarFilePath);
289
			IClasspathAttribute attribute = JavaCore.newClasspathAttribute(IClasspathAttribute.INDEX_LOCATION_ATTRIBUTE_NAME, "file:///"+indexFilePath);
290
			IClasspathEntry entry = JavaCore.newLibraryEntry(libPath, null, null, null, new IClasspathAttribute[]{attribute}, false);
291
			setClasspath(p, new IClasspathEntry[] {entry});
292
			waitUntilIndexesReady();
293
			
294
			search("Test", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
295
			assertSearchResults(getExternalPath() + "Test.jar pkg.Test");
296
			
297
			java.io.File indexFile = JavaModelManager.getIndexManager().getIndex(libPath, false, false).getIndexFile();
298
			long modified = indexFile.lastModified();
299
			assertEquals(modified, indexFile.lastModified());
300
			
301
			simulateExitRestart();
302
			getJavaModel().refreshExternalArchives(null,null);
303
			waitUntilIndexesReady();
304
			
305
			this.resultCollector = new JavaSearchResultCollector();
306
			search("Test", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
307
			assertSearchResults(getExternalPath() + "Test.jar pkg.Test");
308
			
309
			indexFile = JavaModelManager.getIndexManager().getIndex(libPath, false, false).getIndexFile();
310
			assertEquals("Index File should not have got modified",modified, indexFile.lastModified());
311
		} finally {
312
			deleteProject("P");
313
			new File(indexFilePath).delete();
314
			new File(jarFilePath).delete();
315
		}
316
	}
317
	
318
	// test that if the index is not existent after restart, it should build up a new index
319
	public void testNonExistentIndexAfterRestart() throws CoreException, IOException {
320
		String indexFilePath = getExternalResourcePath("Test.index");
321
		String jarFilePath = getExternalResourcePath("Test.jar");
322
		try {
323
			createJar(new String[] {
324
					"pkg/Test.java",
325
					"package pkg;\n" + 
326
					"public class Test {\n" +
327
					"protected Test(int i) {}\n" + "}" 
328
					},jarFilePath);
329
			JavaIndexer.generateIndexForJar(jarFilePath, indexFilePath);
330
			
331
			IJavaProject p = createJavaProject("P");
332
			Path libPath = new Path(jarFilePath);
333
			IClasspathAttribute attribute = JavaCore.newClasspathAttribute(IClasspathAttribute.INDEX_LOCATION_ATTRIBUTE_NAME, "file:///"+indexFilePath);
334
			IClasspathEntry entry = JavaCore.newLibraryEntry(libPath, null, null, null, new IClasspathAttribute[]{attribute}, false);
335
			setClasspath(p, new IClasspathEntry[] {entry});
336
			waitUntilIndexesReady();
337
			
338
			search("Test", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
339
			assertSearchResults(getExternalPath() + "Test.jar pkg.Test");
340
			
341
			simulateExitRestart();
342
			File indexFile = new File(indexFilePath);
343
			indexFile.delete();
344
			assertTrue(!indexFile.exists());
345
			getJavaModel().refreshExternalArchives(null,null);
346
			waitUntilIndexesReady();
347
			
348
			this.resultCollector = new JavaSearchResultCollector();
349
			search("Test", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
350
			assertSearchResults(getExternalPath() + "Test.jar pkg.Test");
351
			
352
		} finally {
353
			deleteProject("P");
354
			new File(indexFilePath).delete();
355
			new File(jarFilePath).delete();
356
		}
357
	}
358
	
359
	// test a non-existent index which becomes existent after restart
360
	public void testExistentIndexAfterRestart() throws CoreException, IOException {
361
		String indexFilePath = getExternalResourcePath("Test.index");
362
		String jarFilePath = getExternalResourcePath("Test.jar");
363
		try {
364
			createJar(new String[] {
365
					"pkg/Test.java",
366
					"package pkg;\n" +
367
					"public class Test {\n" +
368
					"  protected Test(int i) {}\n" +
369
					"}"}, jarFilePath);
370
			
371
			File indexFile = new File(indexFilePath);
372
			indexFile.delete();
373
			assertTrue(!indexFile.exists());
374
			
375
			IJavaProject p = createJavaProject("P");
376
			Path libPath = new Path(jarFilePath);
377
			IClasspathAttribute attribute = JavaCore.newClasspathAttribute(IClasspathAttribute.INDEX_LOCATION_ATTRIBUTE_NAME, "file:///"+indexFilePath);
378
			IClasspathEntry entry = JavaCore.newLibraryEntry(libPath, null, null, null, new IClasspathAttribute[]{attribute}, false);
379
			setClasspath(p, new IClasspathEntry[] {entry});
380
			waitUntilIndexesReady();
381
			
382
			search("Test", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
383
			assertSearchResults(getExternalPath() + "Test.jar pkg.Test");
384
			
385
			JavaIndexer.generateIndexForJar(jarFilePath, indexFilePath);
386
			simulateExitRestart();
387
			getJavaModel().refreshExternalArchives(null,null);
388
			waitUntilIndexesReady();
389
			
390
			this.resultCollector = new JavaSearchResultCollector();
391
			search("Test", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
392
			assertSearchResults(getExternalPath() + "Test.jar pkg.Test");
393
			
394
			indexFile = JavaModelManager.getIndexManager().getIndex(libPath, false, false).getIndexFile();
395
			assertEquals(indexFilePath,indexFile.toString());
396
		} finally {
397
			deleteProject("P");
398
			new File(indexFilePath).delete();
399
			new File(jarFilePath).delete();
400
		}
401
	}
402
	
403
	// Test that the index file is not deletes when the project is deleted
404
	public void testDeleteProject() throws CoreException, IOException {
405
		String indexFilePath = getExternalResourcePath("Test.index");
406
		String jarFilePath = getExternalResourcePath("Test.jar");
407
		try {
408
			createJar(new String[] {
409
					"pkg/Test.java",
410
					"package pkg;\n" +
411
					"public class Test {\n" +
412
					"  protected Test(int i) {}\n" +
413
					"}"}, jarFilePath);
414
			JavaIndexer.generateIndexForJar(jarFilePath, indexFilePath);
415
			IJavaProject p = createJavaProject("P");
416
			createExternalFolder("externalLib");
417
			Path libPath = new Path(jarFilePath);
418
			IClasspathAttribute attribute = JavaCore.newClasspathAttribute(IClasspathAttribute.INDEX_LOCATION_ATTRIBUTE_NAME, "file:///"+indexFilePath);
419
			IClasspathEntry entry = JavaCore.newLibraryEntry(libPath, null, null, null, new IClasspathAttribute[]{attribute}, false);
420
			setClasspath(p, new IClasspathEntry[] {entry});
421
			waitUntilIndexesReady();
422
			deleteProject("P");
423
			File f = new File(indexFilePath);
424
			assertTrue(f.exists());
425
		} finally {
426
			new File(indexFilePath).delete();
427
			new File(jarFilePath).delete();
428
		}
429
	}
430
	
431
	// Test that it works if the index file is in the jar file
432
	public void testIndexInJar() throws IOException, CoreException {
433
		String indexFilePath = getExternalResourcePath("Test.index");
434
		String jarFilePath = getExternalResourcePath("Test.jar");
435
		String indexZipPath =  getExternalResourcePath("TestIndex.zip");
436
		try {
437
			createJar(new String[] {
438
					"pkg/Test.java",
439
					"package pkg;\n" +
440
					"public class Test {\n" +
441
					"  protected Test(int i) {}\n" +
442
					"}"}, jarFilePath);
443
			
444
			JavaIndexer.generateIndexForJar(jarFilePath, indexFilePath);
445
			Util.zipFiles(new File[]{new File(indexFilePath)}, indexZipPath);
446
			
447
			IJavaProject p = createJavaProject("P");
448
			Path libPath = new Path(jarFilePath);
449
			String url = "jar:file:/"+indexZipPath+"!/Test.index";
450
			IClasspathAttribute attribute = JavaCore.newClasspathAttribute(IClasspathAttribute.INDEX_LOCATION_ATTRIBUTE_NAME, url);
451
			IClasspathEntry entry = JavaCore.newLibraryEntry(libPath, null, null, null, new IClasspathAttribute[]{attribute}, false);
452
			setClasspath(p, new IClasspathEntry[] {entry});
453
			waitUntilIndexesReady();
454
			
455
			assertEquals(url,JavaModelManager.getIndexManager().getIndex(libPath, false, false).getIndexLocation().getUrl().toString());
456
			
457
			search("Test", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
458
			assertSearchResults(getExternalPath() + "Test.jar pkg.Test");
459
			
460
			simulateExitRestart();
461
			getJavaModel().refreshExternalArchives(null,null);
462
			waitUntilIndexesReady();
463
			
464
			this.resultCollector = new JavaSearchResultCollector();
465
			assertEquals(url,JavaModelManager.getIndexManager().getIndex(libPath, false, false).getIndexLocation().getUrl().toString());
466
			search("Test", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
467
			assertSearchResults(getExternalPath() + "Test.jar pkg.Test");
468
		} finally {
469
			deleteProject("P");
470
			new File(indexZipPath).delete();
471
			new File(jarFilePath).delete();
472
		}
473
	}
474
	
475
	// Test index file in platform
476
	public void testPlatformIndexFile() throws CoreException, IOException {
477
		String indexFilePath = null;
478
		String jarFilePath = getExternalResourcePath("Test.jar");
479
		String indexUrl = "platform:/resource/P/Test.index";
480
		try {
481
			createJar(new String[] {
482
					"pkg/Test.java",
483
					"package pkg;\n" +
484
					"public class Test {\n" +
485
					"  protected Test(int i) {}\n" +
486
					"}"}, jarFilePath);
487
			
488
			IJavaProject p = createJavaProject("P");
489
			indexFilePath = p.getProject().getLocation().append("Test.index").toFile().getAbsolutePath();
490
			JavaIndexer.generateIndexForJar(jarFilePath, indexFilePath);
491
			long modified = new File(indexFilePath).lastModified();
492
			
493
			Path libPath = new Path(jarFilePath);
494
			IClasspathAttribute attribute = JavaCore.newClasspathAttribute(IClasspathAttribute.INDEX_LOCATION_ATTRIBUTE_NAME, indexUrl);
495
			IClasspathEntry entry = JavaCore.newLibraryEntry(libPath, null, null, null, new IClasspathAttribute[]{attribute}, false);
496
			setClasspath(p, new IClasspathEntry[] {entry});
497
			waitUntilIndexesReady();
498
			
499
			search("Test", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
500
			assertSearchResults(getExternalPath() + "Test.jar pkg.Test");
501
			
502
			URL url = JavaModelManager.getIndexManager().getIndex(libPath, false, false).getIndexLocation().getUrl();
503
			assertEquals(indexUrl, url.toString());
504
			
505
			simulateExitRestart();
506
			getJavaModel().refreshExternalArchives(null,null);
507
			waitUntilIndexesReady();
508
			
509
			this.resultCollector = new JavaSearchResultCollector();
510
			search("Test", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
511
			assertSearchResults(getExternalPath() + "Test.jar pkg.Test");
512
			
513
			url = JavaModelManager.getIndexManager().getIndex(libPath, false, false).getIndexLocation().getUrl();
514
			assertEquals(indexUrl, url.toString());
515
516
			assertEquals(modified, new File(indexFilePath).lastModified());
517
		} finally {
518
			deleteProject("P");
519
			if (indexFilePath != null) new File(indexFilePath).delete();
520
			new File(jarFilePath).delete();
521
		}
522
	}
523
	
524
	// Test index file in platform
525
	public void testPlatformJarIndexFile() throws CoreException, IOException {
526
		String indexFilePath = null;
527
		String jarFilePath = getExternalResourcePath("Test.jar");
528
		String indexUrl = "platform:/resource/ForIndex/Test.index.zip!/Test.index";
529
		try {
530
			createJar(new String[] {
531
					"pkg/Test.java",
532
					"package pkg;\n" +
533
					"public class Test {\n" +
534
					"  protected Test(int i) {}\n" +
535
					"}"}, jarFilePath);
536
			
537
			IProject indexProj = createProject("ForIndex");
538
			indexFilePath = indexProj.getProject().getLocation().append("Test.index").toFile().getAbsolutePath();
539
			JavaIndexer.generateIndexForJar(jarFilePath, indexFilePath);
540
			Util.zipFiles(new File[]{new File(indexFilePath)}, indexFilePath+".zip");
541
			
542
			IJavaProject p = createJavaProject("P");
543
			Path libPath = new Path(jarFilePath);
544
			IClasspathAttribute attribute = JavaCore.newClasspathAttribute(IClasspathAttribute.INDEX_LOCATION_ATTRIBUTE_NAME, indexUrl);
545
			IClasspathEntry entry = JavaCore.newLibraryEntry(libPath, null, null, null, new IClasspathAttribute[]{attribute}, false);
546
			setClasspath(p, new IClasspathEntry[] {entry});
547
			waitUntilIndexesReady();
548
			
549
			search("Test", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
550
			assertSearchResults(getExternalPath() + "Test.jar pkg.Test");
551
			
552
			URL url = JavaModelManager.getIndexManager().getIndex(libPath, false, false).getIndexLocation().getUrl();
553
			assertEquals(indexUrl, url.toString());
554
			
555
			simulateExitRestart();
556
			getJavaModel().refreshExternalArchives(null,null);
557
			waitUntilIndexesReady();
558
			
559
			this.resultCollector = new JavaSearchResultCollector();
560
			search("Test", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
561
			assertSearchResults(getExternalPath() + "Test.jar pkg.Test");
562
			
563
			url = JavaModelManager.getIndexManager().getIndex(libPath, false, false).getIndexLocation().getUrl();
564
			assertEquals(indexUrl, url.toString());
565
		} finally {
566
			deleteProject("P");
567
			if (indexFilePath != null) {
568
				new File(indexFilePath).delete();
569
				new File(indexFilePath+".zip").delete();
570
			}
571
			new File(jarFilePath).delete();
572
			deleteProject("ForIndex");
573
		}
574
	}
575
	
576
	public void testEditClasspath() throws CoreException, IOException {
577
		String indexFilePath = getExternalResourcePath("Test.index");
578
		String jarFilePath = getExternalResourcePath("Test.jar");
579
		try {
580
			createJar(new String[] {
581
					"pkg/Test.java",
582
					"package pkg;\n" +
583
					"public class Test {\n" +
584
					"  protected Test(int i) {}\n" +
585
					"}"}, jarFilePath);
586
			JavaIndexer.generateIndexForJar(jarFilePath, indexFilePath);
587
			File f = new File(indexFilePath);
588
			long modified = f.lastModified();
589
			IJavaProject p = this.createJavaProject("P", new String[] {}, "bin");
590
591
			String content = new String(
592
					"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
593
					+ "<classpath>\n"
594
					+ "<classpathentry kind=\"src\" path=\"src a\"/>\n"
595
					+ "<classpathentry kind=\"src\" path=\"src x\"/>\n"
596
					+ "<classpathentry kind=\"lib\" path=\""
597
					+ getExternalJCLPath()
598
					+ "\"/>\n"
599
					+ "<classpathentry kind=\"lib\" path=\""
600
					+ jarFilePath
601
					+ "\">"
602
					+ "<attributes>\n" 
603
					+ "	<attribute name=\"index_location\" value=\"file:///"
604
					+ indexFilePath
605
					+"\"/>\n" 
606
					+ "</attributes>\n"
607
					+ "</classpathentry>\n"
608
					+ "<classpathentry kind=\"output\" path=\"bin\"/>\n"
609
					+ "</classpath>\n");
610
611
			editFile("/P/.classpath", content);
612
			p.open(null);
613
			waitUntilIndexesReady();
614
			search("Test", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
615
			assertSearchResults(getExternalPath() + "Test.jar pkg.Test");
616
			java.io.File indexFile = JavaModelManager.getIndexManager().getIndex(new Path(jarFilePath), false, false).getIndexFile();
617
			assertEquals(indexFilePath,indexFile.toString());
618
			f = new File(indexFilePath);
619
			assertEquals(modified, f.lastModified());
620
		} finally {
621
			deleteProject("P");
622
			new File(indexFilePath).delete();
623
			new File(jarFilePath).delete();
624
		}
625
	}
626
	
627
	// Test changing the classpath	
628
	public void testChangeClasspath() throws CoreException, IOException {
629
		String indexFilePath = getExternalResourcePath("Test.index");
630
		String jarFilePath = getExternalResourcePath("Test.jar");
631
		try {
632
			createJar(new String[] {
633
					"pkg/Test.java",
634
					"package pkg;\n" +
635
					"public class Test {\n" +
636
					"  protected Test(int i) {}\n" +
637
					"}"}, jarFilePath);
638
			JavaIndexer.generateIndexForJar(jarFilePath, indexFilePath);
639
			createJar(new String[] {
640
					"pkg/Test.java",
641
					"package pkg;\n" +
642
					"public class Test {\n" +
643
					"  protected Test(int i) {}\n" +
644
					"}", 
645
					"pkg/NewTest.java",
646
					"package pkg;\n" +
647
					"public class NewTest {\n" +
648
					"  protected NewTest(int i) {}\n" +
649
					"}"}, jarFilePath);
650
			IJavaProject p = createJavaProject("P");
651
			Path libPath = new Path(jarFilePath);
652
			
653
			IClasspathEntry entry = JavaCore.newLibraryEntry(libPath, null, null, null, null, false);
654
			setClasspath(p, new IClasspathEntry[] {entry});
655
			waitUntilIndexesReady();
656
			search("NewTest", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
657
			assertSearchResults(getExternalPath() + "Test.jar pkg.NewTest");
658
			
659
			IClasspathAttribute attribute = JavaCore.newClasspathAttribute(IClasspathAttribute.INDEX_LOCATION_ATTRIBUTE_NAME, "file:///"+indexFilePath);
660
			entry = JavaCore.newLibraryEntry(libPath, null, null, null, new IClasspathAttribute[]{attribute}, false);
661
			setClasspath(p, new IClasspathEntry[] {entry});
662
			waitUntilIndexesReady();
663
			this.resultCollector = new JavaSearchResultCollector();
664
			search("NewTest", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
665
			assertSearchResults("");
666
			
667
			entry = JavaCore.newLibraryEntry(libPath, null, null, null, null, false);
668
			setClasspath(p, new IClasspathEntry[] {entry});
669
			waitUntilIndexesReady();
670
			this.resultCollector = new JavaSearchResultCollector();
671
			search("NewTest", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
672
			assertSearchResults(getExternalPath() + "Test.jar pkg.NewTest");
673
			
674
			
675
		} finally {
676
			deleteProject("P");
677
			new File(indexFilePath).delete();
678
			new File(jarFilePath).delete();
679
		}
680
	}
681
	
682
	// Test changing the classpath	
683
	public void testChangeClasspathForInternalJar() throws CoreException, IOException {
684
		String indexFilePath = getExternalResourcePath("Test.index");
685
		String jarFilePath = "/P/Test.jar";
686
		try {
687
			IJavaProject p = createJavaProject("P");
688
			createJar(new String[] {
689
					"pkg/Test.java",
690
					"package pkg;\n" +
691
					"public class Test {\n" +
692
					"  protected Test(int i) {}\n" +
693
					"}"}, jarFilePath);
694
			JavaIndexer.generateIndexForJar(jarFilePath, indexFilePath);
695
			createJar(new String[] {
696
					"pkg/Test.java",
697
					"package pkg;\n" +
698
					"public class Test {\n" +
699
					"  protected Test(int i) {}\n" +
700
					"}", 
701
					"pkg/NewTest.java",
702
					"package pkg;\n" +
703
					"public class NewTest {\n" +
704
					"  protected NewTest(int i) {}\n" +
705
					"}"}, jarFilePath);
706
			Path libPath = new Path(jarFilePath);
707
			
708
			IClasspathEntry entry = JavaCore.newLibraryEntry(libPath, null, null, null, null, false);
709
			setClasspath(p, new IClasspathEntry[] {entry});
710
			waitUntilIndexesReady();
711
			search("NewTest", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
712
			assertSearchResults("\\P\\Test.jar pkg.NewTest");
713
			
714
			IClasspathAttribute attribute = JavaCore.newClasspathAttribute(IClasspathAttribute.INDEX_LOCATION_ATTRIBUTE_NAME, "file:///"+indexFilePath);
715
			entry = JavaCore.newLibraryEntry(libPath, null, null, null, new IClasspathAttribute[]{attribute}, false);
716
			setClasspath(p, new IClasspathEntry[] {entry});
717
			waitUntilIndexesReady();
718
			this.resultCollector = new JavaSearchResultCollector();
719
			search("NewTest", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
720
			assertSearchResults("");
721
			
722
			entry = JavaCore.newLibraryEntry(libPath, null, null, null, null, false);
723
			setClasspath(p, new IClasspathEntry[] {entry});
724
			waitUntilIndexesReady();
725
			this.resultCollector = new JavaSearchResultCollector();
726
			search("NewTest", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
727
			assertSearchResults("\\P\\Test.jar pkg.NewTest");
728
			
729
			
730
		} finally {
731
			deleteProject("P");
732
			new File(indexFilePath).delete();
733
		}
734
	}
735
		
736
	public void testMultipleProjects() throws CoreException, IOException {
737
		String indexFilePath = getExternalResourcePath("Test.index");
738
		String jarFilePath = getExternalResourcePath("Test.jar");
739
		try {
740
			createJar(new String[] {
741
					"pkg/Test.java",
742
					"package pkg;\n" +
743
					"public class Test {\n" +
744
					"  protected Test(int i) {}\n" +
745
					"}"}, jarFilePath);
746
			JavaIndexer.generateIndexForJar(jarFilePath, indexFilePath);
747
			
748
			IJavaProject p1 = createJavaProject("P1");
749
			Path libPath = new Path(jarFilePath);
750
			IClasspathEntry entry = JavaCore.newLibraryEntry(libPath, null, null, null, null, false);
751
			setClasspath(p1, new IClasspathEntry[] {entry});
752
			waitUntilIndexesReady();
753
			
754
			IJavaProject p2 = createJavaProject("P2");
755
			IClasspathAttribute attribute = JavaCore.newClasspathAttribute(IClasspathAttribute.INDEX_LOCATION_ATTRIBUTE_NAME, "file:///"+indexFilePath);
756
			entry = JavaCore.newLibraryEntry(libPath, null, null, null, new IClasspathAttribute[]{attribute}, false);
757
			setClasspath(p2, new IClasspathEntry[] {entry});
758
			waitUntilIndexesReady();
759
			
760
			search("Test", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p1}));
761
			assertSearchResults(getExternalPath() + "Test.jar pkg.Test");
762
			
763
			File indexFile = JavaModelManager.getIndexManager().getIndex(libPath, false, false).getIndexFile();
764
			assertEquals(indexFilePath,indexFile.toString());
765
			
766
		} finally {
767
			deleteProject("P1");
768
			deleteProject("P2");
769
			new File(indexFilePath).delete();
770
			new File(jarFilePath).delete();
771
		}
772
	}
773
	
774
	// TODO SATYAM: Add test for containers
775
}
(-)a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchScopeTests.java (-2 / +2 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2008 IBM Corporation and others.
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 1025-1031 Link Here
1025
1025
1026
		// Index the output location as it is a library for the project
1026
		// Index the output location as it is a library for the project
1027
		IndexManager indexManager = JavaModelManager.getIndexManager();
1027
		IndexManager indexManager = JavaModelManager.getIndexManager();
1028
		indexManager.indexLibrary(new Path("/P1/bin"), project.getProject());
1028
		indexManager.indexLibrary(new Path("/P1/bin"), project.getProject(), null);
1029
		waitUntilIndexesReady();
1029
		waitUntilIndexesReady();
1030
1030
1031
		// Search for all types
1031
		// Search for all types
(-)a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/RunJavaSearchTests.java (-1 / +2 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2009 IBM Corporation and others.
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 62-67 Link Here
62
		allClasses.add(SearchTests.class);
62
		allClasses.add(SearchTests.class);
63
		allClasses.add(JavaSearchScopeTests.class);
63
		allClasses.add(JavaSearchScopeTests.class);
64
		allClasses.add(MatchingRegionsTest.class);
64
		allClasses.add(MatchingRegionsTest.class);
65
		allClasses.add(JavaIndexTests.class);
65
66
66
		// Reset forgotten subsets of tests
67
		// Reset forgotten subsets of tests
67
		TestCase.TESTS_PREFIX = null;
68
		TestCase.TESTS_PREFIX = null;
(-)a/org.eclipse.jdt.core/META-INF/MANIFEST.MF (+1 lines)
Lines 17-22 Link Here
17
 org.eclipse.jdt.core.jdom,
17
 org.eclipse.jdt.core.jdom,
18
 org.eclipse.jdt.core.search,
18
 org.eclipse.jdt.core.search,
19
 org.eclipse.jdt.core.util,
19
 org.eclipse.jdt.core.util,
20
 org.eclipse.jdt.core.index,
20
 org.eclipse.jdt.internal.codeassist;x-internal:=true,
21
 org.eclipse.jdt.internal.codeassist;x-internal:=true,
21
 org.eclipse.jdt.internal.codeassist.complete;x-internal:=true,
22
 org.eclipse.jdt.internal.codeassist.complete;x-internal:=true,
22
 org.eclipse.jdt.internal.codeassist.impl;x-internal:=true,
23
 org.eclipse.jdt.internal.codeassist.impl;x-internal:=true,
(-)a/org.eclipse.jdt.core/antadapter/org/eclipse/jdt/core/BuildJarIndex.java (+63 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2011 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.core;
12
13
import java.io.IOException;
14
15
import org.apache.tools.ant.BuildException;
16
import org.apache.tools.ant.Task;
17
import org.eclipse.jdt.core.index.JavaIndexer;
18
import org.eclipse.jdt.internal.antadapter.AntAdapterMessages;
19
20
/**
21
 * <p>
22
 * An Ant task to generate the index file for the given jar path.
23
 * </p>
24
 * <p>
25
 * <code>&lt;eclipse.buildJarIndex jarPath="Test.jar" indexPath="Test.index"/&gt;</code>
26
 * </p>
27
 * <p>
28
 * For more information on Ant check out the website at http://jakarta.apache.org/ant/ .
29
 * </p>
30
 * 
31
 * This is not intended to be subclassed by users.
32
 * 
33
 * @since 3.8
34
 */
35
public class BuildJarIndex extends Task {
36
37
	private String jarPath;
38
	private String indexPath;
39
40
	public void execute() throws BuildException {
41
		if (this.jarPath == null) {
42
			throw new BuildException(AntAdapterMessages.getString("buildJarIndex.jarFile.cannot.be.null")); //$NON-NLS-1$
43
		}
44
		if (this.indexPath == null) {
45
			throw new BuildException(AntAdapterMessages.getString("buildJarIndex.indexFile.cannot.be.null")); //$NON-NLS-1$
46
		}
47
48
		try {
49
			JavaIndexer.generateIndexForJar(this.jarPath, this.indexPath);
50
		} catch (IOException e) {
51
			throw new BuildException(AntAdapterMessages.getString("buildJarIndex.ioexception.occured", e.getLocalizedMessage())); //$NON-NLS-1$
52
		}
53
		setProject(getProject());
54
	}
55
56
	public void setJarPath(String path) {
57
		this.jarPath = path;
58
	}
59
60
	public void setIndexPath(String path) {
61
		this.indexPath = path;
62
	}
63
}
(-)a/org.eclipse.jdt.core/antadapter/org/eclipse/jdt/internal/antadapter/messages.properties (-1 / +5 lines)
Lines 1-5 Link Here
1
###############################################################################
1
###############################################################################
2
# Copyright (c) 2000, 2006 IBM Corporation and others.
2
# Copyright (c) 2000, 2011 IBM Corporation and others.
3
# All rights reserved. This program and the accompanying materials
3
# All rights reserved. This program and the accompanying materials
4
# are made available under the terms of the Eclipse Public License v1.0
4
# are made available under the terms of the Eclipse Public License v1.0
5
# which accompanies this distribution, and is available at
5
# which accompanies this distribution, and is available at
Lines 19-21 Link Here
19
checkDebugAttributes.property.argument.cannot.be.null=The property argument cannot be null
19
checkDebugAttributes.property.argument.cannot.be.null=The property argument cannot be null
20
checkDebugAttributes.ioexception.occured=IOException occurred while reading 
20
checkDebugAttributes.ioexception.occured=IOException occurred while reading 
21
checkDebugAttributes.file.argument.must.be.a.classfile.or.a.jarfile=The file argument must be a .class or a .jar file
21
checkDebugAttributes.file.argument.must.be.a.classfile.or.a.jarfile=The file argument must be a .class or a .jar file
22
23
buildJarIndex.jarFile.cannot.be.null=The jar file argument cannot be null
24
buildJarIndex.indexFile.cannot.be.null=The index file argument cannot be null
25
buildJarIndex.ioexception.occured=IOException - {0}
(-)a/org.eclipse.jdt.core/build.properties (-2 / +3 lines)
Lines 1-5 Link Here
1
###############################################################################
1
###############################################################################
2
# Copyright (c) 2000, 2010 IBM Corporation and others.
2
# Copyright (c) 2000, 2011 IBM Corporation and others.
3
# All rights reserved. This program and the accompanying materials
3
# All rights reserved. This program and the accompanying materials
4
# are made available under the terms of the Eclipse Public License v1.0
4
# are made available under the terms of the Eclipse Public License v1.0
5
# which accompanies this distribution, and is available at
5
# which accompanies this distribution, and is available at
Lines 24-30 Link Here
24
                   org.eclipse.jdt.core.jdom.*,\
24
                   org.eclipse.jdt.core.jdom.*,\
25
                   org.eclipse.jdt.core.dom.*,\
25
                   org.eclipse.jdt.core.dom.*,\
26
                   org.eclipse.jdt.core.dom.rewrite.*,\
26
                   org.eclipse.jdt.core.dom.rewrite.*,\
27
                   org.eclipse.jdt.core.search.*
27
                   org.eclipse.jdt.core.search.*,\
28
                   org.eclipse.jdt.core.index.*
28
source.. =   batch/,\
29
source.. =   batch/,\
29
	         codeassist/,\
30
	         codeassist/,\
30
	         compiler/,\
31
	         compiler/,\
(-)a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathAttribute.java (-1 / +11 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2010 IBM Corporation and others.
2
 * Copyright (c) 2005, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 58-63 Link Here
58
	 * @since 3.1
58
	 * @since 3.1
59
	 */
59
	 */
60
	String JAVADOC_LOCATION_ATTRIBUTE_NAME = "javadoc_location"; //$NON-NLS-1$
60
	String JAVADOC_LOCATION_ATTRIBUTE_NAME = "javadoc_location"; //$NON-NLS-1$
61
	
62
	/**
63
	 * Constant for the name of the index location attribute.
64
	 * 
65
	 * <p>The value for this attribute has to be the string representation of a URL.
66
	 * It should point to an existing index file in a folder or a jar. The URL also supports the platform protocol.</p>
67
	 * 
68
	 * @since 3.8
69
	 */
70
	String INDEX_LOCATION_ATTRIBUTE_NAME = "index_location"; //$NON-NLS-1$
61
71
62
	/**
72
	/**
63
	 * Constant for the name of the optional attribute. The possible values
73
	 * Constant for the name of the optional attribute. The possible values
(-)a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaElementDelta.java (+26 lines)
Lines 57-62 Link Here
57
 * <li>{@link #F_SOURCEDETACHED} - The source attachment path or the source attachment root path
57
 * <li>{@link #F_SOURCEDETACHED} - The source attachment path or the source attachment root path
58
 * of a classpath entry corresponding to the element was removed. This flag is only valid if the element is an
58
 * of a classpath entry corresponding to the element was removed. This flag is only valid if the element is an
59
 * {@link IPackageFragmentRoot}.</li>
59
 * {@link IPackageFragmentRoot}.</li>
60
 * <li>{@link #F_INDEXATTACHED} - The index path or the index root path
61
 * of a classpath entry corresponding to the element was added. This flag is only valid if the element is an
62
 * {@link IPackageFragmentRoot}.</li>
63
 * <li>{@link #F_INDEXDETACHED} - The index path or the index root path
64
 * of a classpath entry corresponding to the element was removed. This flag is only valid if the element is an
65
 * {@link IPackageFragmentRoot}.</li>
60
 * <li>{@link #F_SUPER_TYPES} - One of the supertypes of an {@link IType} has changed</li>.
66
 * <li>{@link #F_SUPER_TYPES} - One of the supertypes of an {@link IType} has changed</li>.
61
 * </ul>
67
 * </ul>
62
 * </li>
68
 * </li>
Lines 312-317 Link Here
312
	 * @since 3.4
318
	 * @since 3.4
313
	 */
319
	 */
314
	public int F_ANNOTATIONS = 0x400000;
320
	public int F_ANNOTATIONS = 0x400000;
321
	
322
	/**
323
	 * TODO SATYAM: We probably don't need this delta..
324
	 * 
325
	 * Change flag indicating that the index file of a classpath entry
326
	 * corresponding to the element was added. This flag is only valid if the element is an
327
	 * {@link IPackageFragmentRoot}.
328
	 * 
329
	 * @since 3.8
330
	 */
331
	public int F_INDEXATTACHED = 0x800000;
332
	
333
	/**
334
	 * Change flag indicating that the index file of a classpath entry
335
	 * corresponding to the element was removed. This flag is only valid if the element is an
336
	 * {@link IPackageFragmentRoot}.
337
	 * 
338
	 * @since 3.8
339
	 */
340
	public int F_INDEXDETACHED = 0x1000000;
315
341
316
	/**
342
	/**
317
	 * Returns deltas for the children that have been added.
343
	 * Returns deltas for the children that have been added.
(-)a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageFragmentRoot.java (-1 / +14 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2010 IBM Corporation and others.
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 18-23 Link Here
18
 *******************************************************************************/
18
 *******************************************************************************/
19
package org.eclipse.jdt.core;
19
package org.eclipse.jdt.core;
20
20
21
import java.net.URL;
21
import org.eclipse.core.runtime.IPath;
22
import org.eclipse.core.runtime.IPath;
22
import org.eclipse.core.runtime.IProgressMonitor;
23
import org.eclipse.core.runtime.IProgressMonitor;
23
24
Lines 243-248 Link Here
243
	 */
244
	 */
244
	void delete(int updateResourceFlags, int updateModelFlags, IProgressMonitor monitor) throws JavaModelException;
245
	void delete(int updateResourceFlags, int updateModelFlags, IProgressMonitor monitor) throws JavaModelException;
245
	/**
246
	/**
247
	 * Returns the URL to the index file attached to this package fragment root's binary archive.
248
	 *
249
	 * @return the URL to the corresponding index file,
250
	 *   or <code>null</code> if this package fragment root's binary archive
251
	 *   has no corresponding index file, or if this package fragment root
252
	 *   is not a binary archive
253
	 * @exception JavaModelException if this operation fails
254
	 * 
255
	 * @since 3.8
256
	 */
257
	URL getIndexPath() throws JavaModelException;
258
	/**
246
	 * Returns this package fragment root's kind encoded as an integer.
259
	 * Returns this package fragment root's kind encoded as an integer.
247
	 * A package fragment root can contain source files (i.e. files with one
260
	 * A package fragment root can contain source files (i.e. files with one
248
	 * of the {@link JavaCore#getJavaLikeExtensions() Java-like extensions},
261
	 * of the {@link JavaCore#getJavaLikeExtensions() Java-like extensions},
(-)a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathChange.java (-3 / +14 lines)
Lines 10-15 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.jdt.internal.core;
11
package org.eclipse.jdt.internal.core;
12
12
13
import java.net.URL;
13
import java.util.ArrayList;
14
import java.util.ArrayList;
14
import java.util.HashMap;
15
import java.util.HashMap;
15
import java.util.HashSet;
16
import java.util.HashSet;
Lines 335-340 Link Here
335
							boolean found = false;
336
							boolean found = false;
336
							for (int j = 0; j < accumulatedRoots.size(); j++) {
337
							for (int j = 0; j < accumulatedRoots.size(); j++) {
337
								IPackageFragmentRoot root = (IPackageFragmentRoot) accumulatedRoots.elementAt(j);
338
								IPackageFragmentRoot root = (IPackageFragmentRoot) accumulatedRoots.elementAt(j);
339
								// TODO SATYAM: Shouldn't the check be opposite?
338
								if (!root.getPath().equals(oldRoot.getPath())) {
340
								if (!root.getPath().equals(oldRoot.getPath())) {
339
									found = true;
341
									found = true;
340
									break;
342
									break;
Lines 511-517 Link Here
511
513
512
		for (int i = 0; i < newLength; i++) {
514
		for (int i = 0; i < newLength; i++) {
513
			int index = classpathContains(this.oldResolvedClasspath, newResolvedClasspath[i]);
515
			int index = classpathContains(this.oldResolvedClasspath, newResolvedClasspath[i]);
514
			if (index == -1) {
516
			if (index == -1 || newResolvedClasspath[i].getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
515
				// remote projects are not indexed in this project
517
				// remote projects are not indexed in this project
516
				if (newResolvedClasspath[i].getEntryKind() == IClasspathEntry.CPE_PROJECT){
518
				if (newResolvedClasspath[i].getEntryKind() == IClasspathEntry.CPE_PROJECT){
517
					continue;
519
					continue;
Lines 524-537 Link Here
524
						boolean pathHasChanged = true;
526
						boolean pathHasChanged = true;
525
						IPath newPath = newResolvedClasspath[i].getPath();
527
						IPath newPath = newResolvedClasspath[i].getPath();
526
						for (int j = 0; j < oldLength; j++) {
528
						for (int j = 0; j < oldLength; j++) {
529
							//TODO SATYAM: Isn't index == j?
527
							IClasspathEntry oldEntry = this.oldResolvedClasspath[j];
530
							IClasspathEntry oldEntry = this.oldResolvedClasspath[j];
528
							if (oldEntry.getPath().equals(newPath)) {
531
							if (oldEntry.getPath().equals(newPath)) {
529
								pathHasChanged = false;
532
								URL oldurl = ((ClasspathEntry)oldEntry).getLibraryIndexLocation();
533
								URL newurl = ((ClasspathEntry)newResolvedClasspath[i]).getLibraryIndexLocation();
534
								if (oldurl == null && newurl == null) {
535
									pathHasChanged = false;
536
								} else if (oldurl != null && newurl != null) {
537
									pathHasChanged = !(newurl.equals(oldurl));
538
								} else if (oldurl != null) {
539
									indexManager.removeIndex(newPath);
540
								}
530
								break;
541
								break;
531
							}
542
							}
532
						}
543
						}
533
						if (pathHasChanged) {
544
						if (pathHasChanged) {
534
							indexManager.indexLibrary(newPath, this.project.getProject());
545
							indexManager.indexLibrary(newPath, this.project.getProject(),((ClasspathEntry)newResolvedClasspath[i]).getLibraryIndexLocation());
535
						}
546
						}
536
						break;
547
						break;
537
					case IClasspathEntry.CPE_SOURCE:
548
					case IClasspathEntry.CPE_SOURCE:
(-)a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java (-1 / +30 lines)
Lines 17-22 Link Here
17
import java.io.InputStream;
17
import java.io.InputStream;
18
import java.io.OutputStreamWriter;
18
import java.io.OutputStreamWriter;
19
import java.io.UnsupportedEncodingException;
19
import java.io.UnsupportedEncodingException;
20
import java.net.MalformedURLException;
21
import java.net.URL;
20
import java.util.ArrayList;
22
import java.util.ArrayList;
21
import java.util.HashMap;
23
import java.util.HashMap;
22
import java.util.HashSet;
24
import java.util.HashSet;
Lines 1524-1529 Link Here
1524
1526
1525
		return JavaCore.getResolvedClasspathEntry(this);
1527
		return JavaCore.getResolvedClasspathEntry(this);
1526
	}
1528
	}
1529
	
1530
	/**
1531
	 * This function computes the URL of the index location for this classpath entry. It returns null if the URL is
1532
	 * invalid.
1533
	 */
1534
	public URL getLibraryIndexLocation() {
1535
		switch(getEntryKind()) {
1536
			case IClasspathEntry.CPE_LIBRARY :
1537
			case IClasspathEntry.CPE_VARIABLE :
1538
				break;
1539
			default :
1540
				return null;
1541
		}
1542
1543
		for (int i= 0; i < this.extraAttributes.length; i++) {
1544
			IClasspathAttribute attrib= this.extraAttributes[i];
1545
			if (IClasspathAttribute.INDEX_LOCATION_ATTRIBUTE_NAME.equals(attrib.getName())) {
1546
				String value = attrib.getValue();
1547
				try {
1548
					return new URL(value);
1549
				} catch (MalformedURLException e) {
1550
					return null;
1551
				}
1552
			}
1553
		}
1554
		return null;
1555
	}	
1527
1556
1528
	/**
1557
	/**
1529
	 * Validate a given classpath and output location for a project, using the following rules:
1558
	 * Validate a given classpath and output location for a project, using the following rules:
Lines 2191-2195 Link Here
2191
			}
2220
			}
2192
		}
2221
		}
2193
		return JavaModelStatus.VERIFIED_OK;
2222
		return JavaModelStatus.VERIFIED_OK;
2194
	}
2223
	}	
2195
}
2224
}
(-)a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java (-4 / +9 lines)
Lines 13-18 Link Here
13
package org.eclipse.jdt.internal.core;
13
package org.eclipse.jdt.internal.core;
14
14
15
import java.io.File;
15
import java.io.File;
16
import java.net.URL;
16
import java.util.*;
17
import java.util.*;
17
18
18
import org.eclipse.core.resources.IContainer;
19
import org.eclipse.core.resources.IContainer;
Lines 997-1004 Link Here
997
									// first remove the index so that it is forced to be re-indexed
998
									// first remove the index so that it is forced to be re-indexed
998
									this.manager.indexManager.removeIndex(entryPath);
999
									this.manager.indexManager.removeIndex(entryPath);
999
									// then index the jar
1000
									// then index the jar
1000
									this.manager.indexManager.indexLibrary(entryPath, project.getProject());
1001
									this.manager.indexManager.indexLibrary(entryPath, project.getProject(), ((ClasspathEntry)entries[j]).getLibraryIndexLocation());
1001
								} else {
1002
								} else {
1003
									URL indexLocation = ((ClasspathEntry)entries[j]).getLibraryIndexLocation();
1004
									if (indexLocation != null) { // force reindexing, this could be faster rather than maintaining the list
1005
										this.manager.indexManager.indexLibrary(entryPath, project.getProject(), ((ClasspathEntry)entries[j]).getLibraryIndexLocation());
1006
									}
1002
									externalArchivesStatus.put(entryPath, EXTERNAL_JAR_UNCHANGED);
1007
									externalArchivesStatus.put(entryPath, EXTERNAL_JAR_UNCHANGED);
1003
								}
1008
								}
1004
							} else {
1009
							} else {
Lines 1009-1015 Link Here
1009
									this.state.getExternalLibTimeStamps().put(entryPath, new Long(newTimeStamp));
1014
									this.state.getExternalLibTimeStamps().put(entryPath, new Long(newTimeStamp));
1010
									// index the new jar
1015
									// index the new jar
1011
									this.manager.indexManager.removeIndex(entryPath);
1016
									this.manager.indexManager.removeIndex(entryPath);
1012
									this.manager.indexManager.indexLibrary(entryPath, project.getProject());
1017
									this.manager.indexManager.indexLibrary(entryPath, project.getProject(), ((ClasspathEntry)entries[j]).getLibraryIndexLocation());
1013
								}
1018
								}
1014
							}
1019
							}
1015
						} else { // internal JAR
1020
						} else { // internal JAR
Lines 2629-2641 Link Here
2629
					switch (delta.getKind()) {
2634
					switch (delta.getKind()) {
2630
						case IResourceDelta.ADDED:
2635
						case IResourceDelta.ADDED:
2631
							// index the new jar
2636
							// index the new jar
2632
							indexManager.indexLibrary(jarPath, root.getJavaProject().getProject());
2637
							indexManager.indexLibrary(jarPath, root.getJavaProject().getProject(), root.getIndexPath() );
2633
							break;
2638
							break;
2634
						case IResourceDelta.CHANGED:
2639
						case IResourceDelta.CHANGED:
2635
							// first remove the index so that it is forced to be re-indexed
2640
							// first remove the index so that it is forced to be re-indexed
2636
							indexManager.removeIndex(jarPath);
2641
							indexManager.removeIndex(jarPath);
2637
							// then index the jar
2642
							// then index the jar
2638
							indexManager.indexLibrary(jarPath, root.getJavaProject().getProject());
2643
							indexManager.indexLibrary(jarPath, root.getJavaProject().getProject(), root.getIndexPath());
2639
							break;
2644
							break;
2640
						case IResourceDelta.REMOVED:
2645
						case IResourceDelta.REMOVED:
2641
							// the jar was physically removed: remove the index
2646
							// the jar was physically removed: remove the index
(-)a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementDelta.java (-1 / +24 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2010 IBM Corporation and others.
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 569-574 Link Here
569
	detachedDelta.changed(F_SOURCEDETACHED);
569
	detachedDelta.changed(F_SOURCEDETACHED);
570
	insertDeltaTree(element, detachedDelta);
570
	insertDeltaTree(element, detachedDelta);
571
}
571
}
572
573
/**
574
 * Creates the nested deltas resulting from a change operation.
575
 * Convenience method for creating change deltas.
576
 * The constructor should be used to create the root delta
577
 * and then a change operation should call this method.
578
 */
579
public void indexAttached(IJavaElement element) {
580
	JavaElementDelta attachedDelta = new JavaElementDelta(element);
581
	attachedDelta.changed(F_INDEXATTACHED);
582
	insertDeltaTree(element, attachedDelta);
583
}
584
/**
585
 * Creates the nested deltas resulting from a change operation.
586
 * Convenience method for creating change deltas.
587
 * The constructor should be used to create the root delta
588
 * and then a change operation should call this method.
589
 */
590
public void indexDetached(IJavaElement element) {
591
	JavaElementDelta detachedDelta = new JavaElementDelta(element);
592
	detachedDelta.changed(F_INDEXDETACHED);
593
	insertDeltaTree(element, detachedDelta);
594
}
572
/**
595
/**
573
 * Returns a string representation of this delta's
596
 * Returns a string representation of this delta's
574
 * structure suitable for debug purposes.
597
 * structure suitable for debug purposes.
(-)a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java (-1 / +14 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2010 IBM Corporation and others.
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 10-15 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.jdt.internal.core;
11
package org.eclipse.jdt.internal.core;
12
12
13
import java.net.URL;
13
import java.util.ArrayList;
14
import java.util.ArrayList;
14
import java.util.Enumeration;
15
import java.util.Enumeration;
15
import java.util.Map;
16
import java.util.Map;
Lines 807-810 Link Here
807
	}
808
	}
808
}
809
}
809
810
811
public URL getIndexPath() {
812
	try {
813
		if (getKind() != K_BINARY) return null;
814
815
		IClasspathEntry entry = ((JavaProject) getParent()).getClasspathEntryFor(getPath());
816
		if (entry != null) return ((ClasspathEntry)entry).getLibraryIndexLocation();	
817
	} catch (JavaModelException e) {
818
		// ignore exception
819
	}
820
	return null;
821
}
822
810
}
823
}
(-)a/org.eclipse.jdt.core/plugin.xml (-1 / +17 lines)
Lines 1-7 Link Here
1
<?xml version="1.0" encoding="UTF-8"?>
1
<?xml version="1.0" encoding="UTF-8"?>
2
<?eclipse version="3.0"?>
2
<?eclipse version="3.0"?>
3
<!--
3
<!--
4
    Copyright (c) 2004, 2010 IBM Corporation and others.
4
    Copyright (c) 2004, 2011 IBM Corporation and others.
5
    All rights reserved. This program and the accompanying materials
5
    All rights reserved. This program and the accompanying materials
6
    are made available under the terms of the Eclipse Public License v1.0
6
    are made available under the terms of the Eclipse Public License v1.0
7
    which accompanies this distribution, and is available at
7
    which accompanies this distribution, and is available at
Lines 158-163 Link Here
158
		class="org.eclipse.jdt.core.CheckDebugAttributes"
158
		class="org.eclipse.jdt.core.CheckDebugAttributes"
159
		library="jdtCompilerAdapter.jar">
159
		library="jdtCompilerAdapter.jar">
160
	</antTask>
160
	</antTask>
161
	<antTask
162
		name="eclipse.buildJarIndex"
163
		class="org.eclipse.jdt.core.BuildJarIndex"
164
		library="jdtCompilerAdapter.jar">
165
	</antTask>
161
</extension>
166
</extension>
162
      
167
      
163
<!-- =================================================================================== -->
168
<!-- =================================================================================== -->
Lines 196-201 Link Here
196
</extension>
201
</extension>
197
202
198
<!-- =================================================================================== -->
203
<!-- =================================================================================== -->
204
<!-- Extension: Java Generate Indexer                                                    -->
205
<!-- =================================================================================== -->
206
<extension
207
      id="JavaIndexer"
208
      point="org.eclipse.core.runtime.applications">
209
   		<application>
210
      		<run class="org.eclipse.jdt.core.index.JavaIndexerApplication" />
211
   		</application>
212
</extension>
213
214
<!-- =================================================================================== -->
199
<!-- Extension: Java Content Types                                                       -->
215
<!-- Extension: Java Content Types                                                       -->
200
<!-- =================================================================================== -->
216
<!-- =================================================================================== -->
201
<extension point="org.eclipse.core.contenttype.contentTypes">
217
<extension point="org.eclipse.core.contenttype.contentTypes">
(-)a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/index/JavaIndexer.java (+32 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2011 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.core.index;
12
13
import java.io.IOException;
14
import org.eclipse.jdt.internal.core.search.indexing.DefaultJavaIndexer;
15
16
/**
17
 * TODO SATYAM: Write a proper javadoc
18
 * @since 3.8
19
 */
20
public class JavaIndexer {
21
22
	/**
23
	 * TODO SATYAM: Write a javadoc
24
	 * @param pathToJar
25
	 * @param pathToIndexFile
26
	 * @throws IOException
27
	 */
28
	public static void generateIndexForJar(String pathToJar, String pathToIndexFile) throws IOException {
29
		new DefaultJavaIndexer().generateIndexForJar(pathToJar, pathToIndexFile);
30
	}
31
32
}
(-)a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/index/JavaIndexerApplication.java (+154 lines)
Added Link Here
1
/*******************************************************************************
2
 *  Copyright (c) 2011 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.core.index;
12
13
import java.io.File;
14
import java.io.IOException;
15
import java.text.MessageFormat;
16
import java.util.ArrayList;
17
18
import org.eclipse.equinox.app.IApplication;
19
import org.eclipse.equinox.app.IApplicationContext;
20
import org.eclipse.osgi.util.NLS;
21
22
/**
23
 * Implements an Eclipse Application for org.eclipse.jdt.core.JavaIndexer.
24
 * 
25
 * TODO SATYAM: Improve the javadoc to include the arguments.
26
 * <p>
27
 * On MacOS, when invoked using the Eclipse executable, the "user.dir" property is set to the folder in which the
28
 * eclipse.ini file is located. This makes it harder to use relative paths to point to the files to be formatted or the
29
 * configuration file to use to set the code formatter's options.
30
 * </p>
31
 * 
32
 * 
33
 * @since 3.8
34
 * @noinstantiate This class is not intended to be instantiated by clients.
35
 * @noextend This class is not intended to be subclassed by clients.
36
 */
37
public class JavaIndexerApplication implements IApplication {
38
39
	private final static class Messages extends NLS {
40
		private static final String MESSAGES_NAME = "org.eclipse.jdt.core.index.messages";//$NON-NLS-1$
41
42
		public static String CommandLineProcessing;
43
		public static String CommandLineUsage;
44
		public static String CommandLineOnlyOutputError;
45
		public static String CommandLineOnlyOneJarError;
46
		public static String CommandLineJarNotSpecified;
47
		public static String CommandLineIndexFileNotSpecified;
48
		public static String CaughtException;
49
		public static String CommandLineJarFileNotExist;
50
51
		static {
52
			NLS.initializeMessages(MESSAGES_NAME, Messages.class);
53
		}
54
55
		public static String bind(String message) {
56
			return bind(message, null);
57
		}
58
59
		public static String bind(String message, Object binding) {
60
			return bind(message, new Object[] { binding });
61
		}
62
63
		public static String bind(String message, Object binding1, Object binding2) {
64
			return bind(message, new Object[] { binding1, binding2 });
65
		}
66
67
		public static String bind(String message, Object[] bindings) {
68
			return MessageFormat.format(message, bindings);
69
		}
70
	}
71
72
	private String jarToIndex;
73
	private String indexFile;
74
	private boolean verbose = false;
75
	private static final String PDE_LAUNCH = "-pdelaunch"; //$NON-NLS-1$
76
	private static final String ARG_HELP = "-help"; //$NON-NLS-1$
77
	private static final String ARG_VERBOSE = "-verbose"; //$NON-NLS-1$
78
	private static final String ARG_OUTPUT = "-output"; //$NON-NLS-1$
79
80
	private void displayHelp() {
81
		System.out.println(Messages.bind(Messages.CommandLineUsage));
82
	}
83
84
	private void displayError(String message) {
85
		System.err.println(message);
86
		System.out.println();
87
		displayHelp();
88
	}
89
90
	private boolean processCommandLine(String[] argsArray) {
91
		ArrayList args = new ArrayList();
92
		for (int i = 0, max = argsArray.length; i < max; i++) {
93
			args.add(argsArray[i]);
94
		}
95
		int index = 0;
96
		final int argCount = argsArray.length;
97
98
		loop: while (index < argCount) {
99
			String currentArg = argsArray[index++];
100
			if (PDE_LAUNCH.equals(currentArg)) {
101
				continue loop;
102
			} else if (ARG_HELP.equals(currentArg)) {
103
				displayHelp();
104
				return false;
105
			} else if (ARG_VERBOSE.equals(currentArg)) {
106
				this.verbose = true;
107
				continue loop;
108
			} else if (ARG_OUTPUT.equals(currentArg)) {
109
				if (this.indexFile != null || index == argCount) {
110
					displayError(Messages.bind(Messages.CommandLineOnlyOutputError));
111
					return false;
112
				}
113
				this.indexFile = argsArray[index++];
114
			} else {
115
				if (this.jarToIndex != null) {
116
					displayError(Messages.bind(Messages.CommandLineOnlyOneJarError));
117
					return false;
118
				}
119
				this.jarToIndex = currentArg;
120
			}
121
		}
122
		return true;
123
	}
124
125
	public Object start(IApplicationContext context) throws Exception {
126
		boolean execute = processCommandLine((String[]) context.getArguments().get(IApplicationContext.APPLICATION_ARGS));
127
		if (execute) {
128
			if (this.jarToIndex != null && this.indexFile != null) {
129
				File f = new File(this.jarToIndex);
130
				if (!f.exists()) {
131
					System.out.println(Messages.bind(Messages.CommandLineJarFileNotExist, this.jarToIndex));
132
				}
133
				if (this.verbose) {
134
					System.out.println(Messages.bind(Messages.CommandLineProcessing, this.jarToIndex, this.indexFile));
135
				}
136
				try {
137
					JavaIndexer.generateIndexForJar(this.jarToIndex, this.indexFile);
138
				} catch (IOException e) {
139
					System.out.println(Messages.bind(Messages.CaughtException, "IOException", e.getLocalizedMessage())); //$NON-NLS-1$
140
				}
141
			} else if (this.jarToIndex == null) {
142
				System.out.println(Messages.bind(Messages.CommandLineJarNotSpecified));
143
			} else if (this.indexFile == null) {
144
				System.out.println(Messages.bind(Messages.CommandLineIndexFileNotSpecified));
145
			}
146
		}
147
		return IApplication.EXIT_OK;
148
	}
149
150
	public void stop() {
151
		// do nothing
152
	}
153
154
}
(-)a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/index/messages.properties (+28 lines)
Added Link Here
1
###############################################################################
2
# Copyright (c) 2000, 2006 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
CommandLineUsage=Usage: eclipse -application org.eclipse.jdt.core.JavaCodeGenerateIndex [ OPTIONS ] -output <indexFile> <jarfile>\n\
12
\n\
13
\   -output <indexFile> The index file to be generated.\n\
14
\
15
\   <jarfile>   Jar file for which index needs to be generated.\n\
16
\
17
\n\
18
\ OPTIONS:\n\
19
\n\
20
\   -help                Display this message.\n\
21
\   -verbose             Be verbose about the job.
22
CommandLineProcessing=Generating index {1} for the jar {0}.
23
CommandLineOnlyOutputError=Only one output need to be specified.
24
CommandLineOnlyOneJarError=Only one jar file need to be specified.
25
CommandLineJarNotSpecified=No jar file is specified.
26
CommandLineIndexFileNotSpecified=No index file is specified.
27
CaughtException=Exception {0} - {1}.
28
CommandLineJarFileNotExist={0} does not exist.
(-)a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchParticipant.java (-5 / +9 lines)
Lines 14-19 Link Here
14
import org.eclipse.core.runtime.*;
14
import org.eclipse.core.runtime.*;
15
import org.eclipse.jdt.internal.core.JavaModel;
15
import org.eclipse.jdt.internal.core.JavaModel;
16
import org.eclipse.jdt.internal.core.JavaModelManager;
16
import org.eclipse.jdt.internal.core.JavaModelManager;
17
import org.eclipse.jdt.internal.core.index.FlatFileIndex;
18
import org.eclipse.jdt.internal.core.index.IndexLocation;
17
import org.eclipse.jdt.internal.core.search.indexing.IndexManager;
19
import org.eclipse.jdt.internal.core.search.indexing.IndexManager;
18
20
19
/**
21
/**
Lines 192-200 Link Here
192
	 * </p>
194
	 * </p>
193
	 *
195
	 *
194
	 * @param document the document to index
196
	 * @param document the document to index
195
	 * @param indexLocation the location on the file system of the index
197
	 * @param indexPath the location on the file system of the index
196
	 */
198
	 */
197
	public final void scheduleDocumentIndexing(SearchDocument document, IPath indexLocation) {
199
	public final void scheduleDocumentIndexing(SearchDocument document, IPath indexPath) {
198
		IPath documentPath = new Path(document.getPath());
200
		IPath documentPath = new Path(document.getPath());
199
		Object file = JavaModel.getTarget(documentPath, true);
201
		Object file = JavaModel.getTarget(documentPath, true);
200
		IPath containerPath = documentPath;
202
		IPath containerPath = documentPath;
Lines 205-215 Link Here
205
		}
207
		}
206
		IndexManager manager = JavaModelManager.getIndexManager();
208
		IndexManager manager = JavaModelManager.getIndexManager();
207
		// TODO (frederic) should not have to create index manually, should expose API that recreates index instead
209
		// TODO (frederic) should not have to create index manually, should expose API that recreates index instead
210
		IndexLocation indexLocation;
211
		indexLocation = new FlatFileIndex(indexPath.toFile());
208
		manager.ensureIndexExists(indexLocation, containerPath);
212
		manager.ensureIndexExists(indexLocation, containerPath);
209
		manager.scheduleDocumentIndexing(document, containerPath, indexLocation, this);
213
		manager.scheduleDocumentIndexing(document, containerPath, indexLocation, this);
210
		if (!indexLocation.equals(this.lastIndexLocation)) {
214
		if (!indexPath.equals(this.lastIndexLocation)) {
211
			manager.updateParticipant(indexLocation, containerPath);
215
			manager.updateParticipant(indexPath, containerPath);
212
			this.lastIndexLocation = indexLocation;
216
			this.lastIndexLocation = indexPath;
213
		}
217
		}
214
	}
218
	}
215
219
(-)a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/DiskIndex.java (-33 / +39 lines)
Lines 23-29 Link Here
23
23
24
public class DiskIndex {
24
public class DiskIndex {
25
25
26
File indexFile;
26
IndexLocation indexFile;
27
27
28
private int headerInfoOffset;
28
private int headerInfoOffset;
29
private int numberOfChunks;
29
private int numberOfChunks;
Lines 82-93 Link Here
82
}
82
}
83
83
84
84
85
DiskIndex(String fileName) {
85
DiskIndex() {
86
	if (fileName == null)
87
		throw new java.lang.IllegalArgumentException();
88
	this.indexFile = new File(fileName);
89
90
	// clear cached items
91
	this.headerInfoOffset = -1;
86
	this.headerInfoOffset = -1;
92
	this.numberOfChunks = -1;
87
	this.numberOfChunks = -1;
93
	this.sizeOfLastChunk = -1;
88
	this.sizeOfLastChunk = -1;
Lines 99-104 Link Here
99
	this.cachedCategoryName = null;
94
	this.cachedCategoryName = null;
100
	this.categoryOffsets = null;
95
	this.categoryOffsets = null;
101
	this.categoryEnds = null;
96
	this.categoryEnds = null;
97
}
98
DiskIndex(IndexLocation location) throws IOException {
99
	this();
100
	if (location == null) {
101
		throw new IllegalArgumentException();
102
	}
103
	this.indexFile = location;
102
}
104
}
103
SimpleSet addDocumentNames(String substring, MemoryIndex memoryIndex) throws IOException {
105
SimpleSet addDocumentNames(String substring, MemoryIndex memoryIndex) throws IOException {
104
	// must skip over documents which have been added/changed/deleted in the memory index
106
	// must skip over documents which have been added/changed/deleted in the memory index
Lines 230-236 Link Here
230
private void cacheDocumentNames() throws IOException {
232
private void cacheDocumentNames() throws IOException {
231
	// will need all document names so get them now
233
	// will need all document names so get them now
232
	this.cachedChunks = new String[this.numberOfChunks][];
234
	this.cachedChunks = new String[this.numberOfChunks][];
233
	FileInputStream stream = new FileInputStream(this.indexFile);
235
	InputStream stream = this.indexFile.getInputStream();
234
	try {
236
	try {
235
		if (this.numberOfChunks > 5) BUFFER_READ_SIZE <<= 1;
237
		if (this.numberOfChunks > 5) BUFFER_READ_SIZE <<= 1;
236
		int offset = this.chunkOffsets[0];
238
		int offset = this.chunkOffsets[0];
Lines 372-378 Link Here
372
void initialize(boolean reuseExistingFile) throws IOException {
374
void initialize(boolean reuseExistingFile) throws IOException {
373
	if (this.indexFile.exists()) {
375
	if (this.indexFile.exists()) {
374
		if (reuseExistingFile) {
376
		if (reuseExistingFile) {
375
			FileInputStream stream = new FileInputStream(this.indexFile);
377
			InputStream stream = this.indexFile.getInputStream();
376
			this.streamBuffer = new byte[BUFFER_READ_SIZE];
378
			this.streamBuffer = new byte[BUFFER_READ_SIZE];
377
			this.bufferIndex = 0;
379
			this.bufferIndex = 0;
378
			this.bufferEnd = stream.read(this.streamBuffer, 0, 128);
380
			this.bufferEnd = stream.read(this.streamBuffer, 0, 128);
Lines 400-406 Link Here
400
		}
402
		}
401
	}
403
	}
402
	if (this.indexFile.createNewFile()) {
404
	if (this.indexFile.createNewFile()) {
403
		FileOutputStream stream = new FileOutputStream(this.indexFile, false);
405
		FileOutputStream stream = new FileOutputStream(this.indexFile.getIndexFile(), false);
404
		try {
406
		try {
405
			this.streamBuffer = new byte[BUFFER_READ_SIZE];
407
			this.streamBuffer = new byte[BUFFER_READ_SIZE];
406
			this.bufferIndex = 0;
408
			this.bufferIndex = 0;
Lines 500-505 Link Here
500
DiskIndex mergeWith(MemoryIndex memoryIndex) throws IOException {
502
DiskIndex mergeWith(MemoryIndex memoryIndex) throws IOException {
501
 	// assume write lock is held
503
 	// assume write lock is held
502
	// compute & write out new docNames
504
	// compute & write out new docNames
505
	if (this.indexFile == null) {
506
		throw new IOException("Pre-built index file not writeable");  //$NON-NLS-1$
507
	}
503
	String[] docNames = readAllDocumentNames();
508
	String[] docNames = readAllDocumentNames();
504
	int previousLength = docNames.length;
509
	int previousLength = docNames.length;
505
	int[] positions = new int[previousLength]; // keeps track of the position of each document in the new sorted docNames
510
	int[] positions = new int[previousLength]; // keeps track of the position of each document in the new sorted docNames
Lines 509-523 Link Here
509
		if (previousLength == 0) return this; // nothing to do... memory index contained deleted documents that had never been saved
514
		if (previousLength == 0) return this; // nothing to do... memory index contained deleted documents that had never been saved
510
515
511
		// index is now empty since all the saved documents were removed
516
		// index is now empty since all the saved documents were removed
512
		DiskIndex newDiskIndex = new DiskIndex(this.indexFile.getPath());
517
		DiskIndex newDiskIndex = new DiskIndex(this.indexFile);
513
		newDiskIndex.initialize(false);
518
		newDiskIndex.initialize(false);
514
		return newDiskIndex;
519
		return newDiskIndex;
515
	}
520
	}
516
521
	File oldIndexFile = this.indexFile.getIndexFile();
517
	DiskIndex newDiskIndex = new DiskIndex(this.indexFile.getPath() + ".tmp"); //$NON-NLS-1$
522
	DiskIndex newDiskIndex = new DiskIndex(new FlatFileIndex(new File(oldIndexFile.getPath() + ".tmp"))); //$NON-NLS-1$
523
	File newIndexFile = newDiskIndex.indexFile.getIndexFile();
518
	try {
524
	try {
519
		newDiskIndex.initializeFrom(this, newDiskIndex.indexFile);
525
		newDiskIndex.initializeFrom(this, newIndexFile);
520
		FileOutputStream stream = new FileOutputStream(newDiskIndex.indexFile, false);
526
		FileOutputStream stream = new FileOutputStream(newIndexFile, false);
521
		int offsetToHeader = -1;
527
		int offsetToHeader = -1;
522
		try {
528
		try {
523
			newDiskIndex.writeAllDocumentNames(docNames, stream);
529
			newDiskIndex.writeAllDocumentNames(docNames, stream);
Lines 549-566 Link Here
549
		newDiskIndex.writeOffsetToHeader(offsetToHeader);
555
		newDiskIndex.writeOffsetToHeader(offsetToHeader);
550
556
551
		// rename file by deleting previous index file & renaming temp one
557
		// rename file by deleting previous index file & renaming temp one
552
		if (this.indexFile.exists() && !this.indexFile.delete()) {
558
		if (oldIndexFile.exists() && !oldIndexFile.delete()) {
553
			if (DEBUG)
559
			if (DEBUG)
554
				System.out.println("mergeWith - Failed to delete " + this.indexFile); //$NON-NLS-1$
560
				System.out.println("mergeWith - Failed to delete " + this.indexFile); //$NON-NLS-1$
555
			throw new IOException("Failed to delete index file " + this.indexFile); //$NON-NLS-1$
561
			throw new IOException("Failed to delete index file " + this.indexFile); //$NON-NLS-1$
556
		}
562
		}
557
		if (!newDiskIndex.indexFile.renameTo(this.indexFile)) {
563
		if (!newIndexFile.renameTo(oldIndexFile)) {
558
			if (DEBUG)
564
			if (DEBUG)
559
				System.out.println("mergeWith - Failed to rename " + this.indexFile); //$NON-NLS-1$
565
				System.out.println("mergeWith - Failed to rename " + this.indexFile); //$NON-NLS-1$
560
			throw new IOException("Failed to rename index file " + this.indexFile); //$NON-NLS-1$
566
			throw new IOException("Failed to rename index file " + this.indexFile); //$NON-NLS-1$
561
		}
567
		}
562
	} catch (IOException e) {
568
	} catch (IOException e) {
563
		if (newDiskIndex.indexFile.exists() && !newDiskIndex.indexFile.delete())
569
		if (newIndexFile.exists() && !newIndexFile.delete())
564
			if (DEBUG)
570
			if (DEBUG)
565
				System.out.println("mergeWith - Failed to delete temp index " + newDiskIndex.indexFile); //$NON-NLS-1$
571
				System.out.println("mergeWith - Failed to delete temp index " + newDiskIndex.indexFile); //$NON-NLS-1$
566
		throw e;
572
		throw e;
Lines 573-579 Link Here
573
	if (this.numberOfChunks <= 0)
579
	if (this.numberOfChunks <= 0)
574
		return CharOperation.NO_STRINGS;
580
		return CharOperation.NO_STRINGS;
575
581
576
	FileInputStream stream = new FileInputStream(this.indexFile);
582
	InputStream stream = this.indexFile.getInputStream();
577
	try {
583
	try {
578
		int offset = this.chunkOffsets[0];
584
		int offset = this.chunkOffsets[0];
579
		stream.skip(offset);
585
		stream.skip(offset);
Lines 612-618 Link Here
612
		}
618
		}
613
	}
619
	}
614
620
615
	FileInputStream stream = new FileInputStream(this.indexFile);
621
	InputStream stream = this.indexFile.getInputStream();
616
	HashtableOfObject categoryTable = null;
622
	HashtableOfObject categoryTable = null;
617
	char[][] matchingWords = null;
623
	char[][] matchingWords = null;
618
	int count = 0;
624
	int count = 0;
Lines 678-684 Link Here
678
	}
684
	}
679
685
680
	if (matchingWords != null && count > 0) {
686
	if (matchingWords != null && count > 0) {
681
		stream = new FileInputStream(this.indexFile);
687
		stream = this.indexFile.getInputStream();
682
		try {
688
		try {
683
			stream.skip(firstOffset);
689
			stream.skip(firstOffset);
684
			this.bufferIndex = 0;
690
			this.bufferIndex = 0;
Lines 696-702 Link Here
696
	this.streamBuffer = null;
702
	this.streamBuffer = null;
697
	return categoryTable;
703
	return categoryTable;
698
}
704
}
699
private void readChunk(String[] docNames, FileInputStream stream, int index, int size) throws IOException {
705
private void readChunk(String[] docNames, InputStream stream, int index, int size) throws IOException {
700
	String current = new String(readStreamChars(stream));
706
	String current = new String(readStreamChars(stream));
701
	docNames[index++] = current;
707
	docNames[index++] = current;
702
	for (int i = 1; i < size; i++) {
708
	for (int i = 1; i < size; i++) {
Lines 734-740 Link Here
734
			throw new IllegalArgumentException();
740
			throw new IllegalArgumentException();
735
		this.streamBuffer = new byte[numberOfBytes];
741
		this.streamBuffer = new byte[numberOfBytes];
736
		this.bufferIndex = 0;
742
		this.bufferIndex = 0;
737
		FileInputStream file = new FileInputStream(this.indexFile);
743
		InputStream file = this.indexFile.getInputStream();
738
		try {
744
		try {
739
			file.skip(start);
745
			file.skip(start);
740
			if (file.read(this.streamBuffer, 0, numberOfBytes) != numberOfBytes)
746
			if (file.read(this.streamBuffer, 0, numberOfBytes) != numberOfBytes)
Lines 763-769 Link Here
763
	if (arrayOffset instanceof int[])
769
	if (arrayOffset instanceof int[])
764
		return (int[]) arrayOffset;
770
		return (int[]) arrayOffset;
765
771
766
	FileInputStream stream = new FileInputStream(this.indexFile);
772
	InputStream stream = this.indexFile.getInputStream();
767
	try {
773
	try {
768
		int offset = ((Integer) arrayOffset).intValue();
774
		int offset = ((Integer) arrayOffset).intValue();
769
		stream.skip(offset);
775
		stream.skip(offset);
Lines 776-790 Link Here
776
		this.streamBuffer = null;
782
		this.streamBuffer = null;
777
	}
783
	}
778
}
784
}
779
private void readHeaderInfo(FileInputStream stream) throws IOException {
785
private void readHeaderInfo(InputStream stream) throws IOException {
780
786
781
	// must be same order as writeHeaderInfo()
787
	// must be same order as writeHeaderInfo()
782
	this.numberOfChunks = readStreamInt(stream);
788
	this.numberOfChunks = readStreamInt(stream);
783
	this.sizeOfLastChunk = this.streamBuffer[this.bufferIndex++] & 0xFF;
789
	this.sizeOfLastChunk = this.streamBuffer[this.bufferIndex++] & 0xFF;
784
	this.documentReferenceSize = this.streamBuffer[this.bufferIndex++] & 0xFF;
790
	this.documentReferenceSize = this.streamBuffer[this.bufferIndex++] & 0xFF;
785
	this.separator = (char) (this.streamBuffer[this.bufferIndex++] & 0xFF);
791
	this.separator = (char) (this.streamBuffer[this.bufferIndex++] & 0xFF);
786
	long fileLength = this.indexFile.length();
792
	long length = this.indexFile.length();
787
	if (this.numberOfChunks > fileLength ) {
793
	if (length != -1 && this.numberOfChunks > length) {
788
		// not an accurate check, but good enough https://bugs.eclipse.org/bugs/show_bug.cgi?id=350612
794
		// not an accurate check, but good enough https://bugs.eclipse.org/bugs/show_bug.cgi?id=350612
789
		if (DEBUG)
795
		if (DEBUG)
790
			System.out.println("Index file is corrupted " + this.indexFile); //$NON-NLS-1$
796
			System.out.println("Index file is corrupted " + this.indexFile); //$NON-NLS-1$
Lines 799-805 Link Here
799
	int size = readStreamInt(stream);
805
	int size = readStreamInt(stream);
800
	this.categoryOffsets = new HashtableOfIntValues(size);
806
	this.categoryOffsets = new HashtableOfIntValues(size);
801
	this.categoryEnds = new HashtableOfIntValues(size);
807
	this.categoryEnds = new HashtableOfIntValues(size);
802
	if (size > fileLength) {
808
	if (length != -1 && this.numberOfChunks > length) {
803
		//  not an accurate check, but good enough  https://bugs.eclipse.org/bugs/show_bug.cgi?id=350612
809
		//  not an accurate check, but good enough  https://bugs.eclipse.org/bugs/show_bug.cgi?id=350612
804
		if (DEBUG)
810
		if (DEBUG)
805
			System.out.println("Index file is corrupted " + this.indexFile); //$NON-NLS-1$
811
			System.out.println("Index file is corrupted " + this.indexFile); //$NON-NLS-1$
Lines 840-846 Link Here
840
		}
846
		}
841
	}
847
	}
842
}
848
}
843
private void readStreamBuffer(FileInputStream stream) throws IOException {
849
private void readStreamBuffer(InputStream stream) throws IOException {
844
	// if we're about to read a known amount at the end of the existing buffer, but it does not completely fit
850
	// if we're about to read a known amount at the end of the existing buffer, but it does not completely fit
845
	// so we need to shift the remaining bytes to be read, and fill the buffer from the stream
851
	// so we need to shift the remaining bytes to be read, and fill the buffer from the stream
846
	if (this.bufferEnd < this.streamBuffer.length)
852
	if (this.bufferEnd < this.streamBuffer.length)
Lines 872-878 Link Here
872
 * @exception  UTFDataFormatException  if the bytes do not represent a
878
 * @exception  UTFDataFormatException  if the bytes do not represent a
873
 *               valid UTF-8 encoding of a Unicode string.
879
 *               valid UTF-8 encoding of a Unicode string.
874
 */
880
 */
875
private char[] readStreamChars(FileInputStream stream) throws IOException {
881
private char[] readStreamChars(InputStream stream) throws IOException {
876
	// read chars array length
882
	// read chars array length
877
	if (stream != null && this.bufferIndex + 2 >= this.bufferEnd)
883
	if (stream != null && this.bufferIndex + 2 >= this.bufferEnd)
878
		readStreamBuffer(stream);
884
		readStreamBuffer(stream);
Lines 931-937 Link Here
931
	}
937
	}
932
	return word;
938
	return word;
933
}
939
}
934
private int[] readStreamDocumentArray(FileInputStream stream, int arraySize) throws IOException {
940
private int[] readStreamDocumentArray(InputStream stream, int arraySize) throws IOException {
935
	int[] indexes = new int[arraySize];
941
	int[] indexes = new int[arraySize];
936
	if (arraySize == 0) return indexes;
942
	if (arraySize == 0) return indexes;
937
943
Lines 972-978 Link Here
972
	}
978
	}
973
	return indexes;
979
	return indexes;
974
}
980
}
975
private int readStreamInt(FileInputStream stream) throws IOException {
981
private int readStreamInt(InputStream stream) throws IOException {
976
	if (this.bufferIndex + 4 >= this.bufferEnd) {
982
	if (this.bufferIndex + 4 >= this.bufferEnd) {
977
		readStreamBuffer(stream);
983
		readStreamBuffer(stream);
978
	}
984
	}
Lines 1182-1188 Link Here
1182
}
1188
}
1183
private void writeOffsetToHeader(int offsetToHeader) throws IOException {
1189
private void writeOffsetToHeader(int offsetToHeader) throws IOException {
1184
	if (offsetToHeader > 0) {
1190
	if (offsetToHeader > 0) {
1185
		RandomAccessFile file = new RandomAccessFile(this.indexFile, "rw"); //$NON-NLS-1$
1191
		RandomAccessFile file = new RandomAccessFile(this.indexFile.getIndexFile(), "rw"); //$NON-NLS-1$
1186
		try {
1192
		try {
1187
			file.seek(this.headerInfoOffset); // offset to position in header
1193
			file.seek(this.headerInfoOffset); // offset to position in header
1188
			file.writeInt(offsetToHeader);
1194
			file.writeInt(offsetToHeader);
(-)a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/FlatFileIndex.java (+82 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2011 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.core.index;
12
13
import java.io.File;
14
import java.io.FileInputStream;
15
import java.io.IOException;
16
import java.io.InputStream;
17
import java.net.URL;
18
19
public class FlatFileIndex extends IndexLocation {
20
	File indexFile;
21
22
	public FlatFileIndex(File file) {
23
		super(file);
24
		this.indexFile = file;
25
	}
26
27
	public FlatFileIndex(URL url, File file) {
28
		super(url);
29
		this.indexFile = file;
30
	}
31
32
	public boolean createNewFile() throws IOException {
33
		return this.indexFile.createNewFile();
34
	}
35
36
	public boolean delete() {
37
		return this.indexFile.delete();
38
	}
39
40
	public boolean equals(Object other) {
41
		if (!(other instanceof FlatFileIndex)) return false;
42
		return this.indexFile.equals(((FlatFileIndex) other).indexFile);
43
	}
44
45
	public boolean exists() {
46
		return this.indexFile.exists();
47
	}
48
49
	public String fileName() {
50
		return this.indexFile.getName();
51
	}
52
	
53
	public File getIndexFile() {
54
		return this.indexFile;
55
	}
56
57
	InputStream getInputStream() throws IOException {
58
		return new FileInputStream(this.indexFile);
59
	}
60
61
	public String getFilePath() {
62
		try {
63
			return this.indexFile.getCanonicalPath();
64
		} catch (IOException e) {
65
			// ignore
66
		}
67
		return null;
68
	}
69
70
	public int hashCode() {
71
		return this.indexFile.hashCode();
72
	}
73
74
	public long lastModified() {
75
		return this.indexFile.lastModified();
76
	}
77
78
	public long length() {
79
		return this.indexFile.length();
80
	}
81
82
}
(-)a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/Index.java (-5 / +11 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2009 IBM Corporation and others.
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 88-99 Link Here
88
}
88
}
89
89
90
90
91
public Index(String fileName, String containerPath, boolean reuseExistingFile) throws IOException {
91
public Index(IndexLocation location, String containerPath, boolean reuseExistingFile) throws IOException {
92
	this.containerPath = containerPath;
92
	this.containerPath = containerPath;
93
	this.monitor = new ReadWriteMonitor();
93
	this.monitor = new ReadWriteMonitor();
94
94
95
	this.memoryIndex = new MemoryIndex();
95
	this.memoryIndex = new MemoryIndex();
96
	this.diskIndex = new DiskIndex(fileName);
96
	this.diskIndex = new DiskIndex(location);
97
	this.diskIndex.initialize(reuseExistingFile);
97
	this.diskIndex.initialize(reuseExistingFile);
98
	if (reuseExistingFile) this.separator = this.diskIndex.separator;
98
	if (reuseExistingFile) this.separator = this.diskIndex.separator;
99
}
99
}
Lines 109-116 Link Here
109
	}
109
	}
110
	return documentPath.substring(index + 1);
110
	return documentPath.substring(index + 1);
111
}
111
}
112
public File getIndexFile() {
112
public IndexLocation getIndexLocation() {
113
	return this.diskIndex == null ? null : this.diskIndex.indexFile;
113
	return this.diskIndex == null ? null : this.diskIndex.indexFile;
114
}
115
public File getIndexFile() {
116
	return this.diskIndex == null ? null : this.diskIndex.indexFile.getIndexFile();
117
}
118
public long getIndexLastModified() {
119
	return this.diskIndex == null? -1 : this.diskIndex.indexFile.lastModified();
114
}
120
}
115
public boolean hasChanged() {
121
public boolean hasChanged() {
116
	return this.memoryIndex.hasChanged();
122
	return this.memoryIndex.hasChanged();
Lines 180-186 Link Here
180
 */
186
 */
181
public void reset() throws IOException {
187
public void reset() throws IOException {
182
	this.memoryIndex = new MemoryIndex();
188
	this.memoryIndex = new MemoryIndex();
183
	this.diskIndex = new DiskIndex(this.diskIndex.indexFile.getCanonicalPath());
189
	this.diskIndex = new DiskIndex(this.diskIndex.indexFile);
184
	this.diskIndex.initialize(false/*do not reuse the index file*/);
190
	this.diskIndex.initialize(false/*do not reuse the index file*/);
185
}
191
}
186
public void save() throws IOException {
192
public void save() throws IOException {
(-)a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/IndexLocation.java (+99 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2011 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.core.index;
12
13
import java.io.File;
14
import java.io.IOException;
15
import java.io.InputStream;
16
17
import java.net.MalformedURLException;
18
import java.net.URL;
19
20
import org.eclipse.core.runtime.FileLocator;
21
22
/**
23
 * TODO SATYAM: Write a comment about this file
24
 * 
25
 */
26
public abstract class IndexLocation {
27
	private final URL url;
28
	private boolean participantIndex;
29
30
	public IndexLocation(File file) {
31
		URL tempUrl = null;
32
		try {
33
			tempUrl = file.toURI().toURL();
34
		} catch (MalformedURLException e) {
35
			// should not happen
36
		}
37
		this.url = tempUrl;
38
	}
39
	
40
	public static IndexLocation createIndexLocation(URL url) {
41
		URL localUrl;
42
		try {
43
			localUrl = FileLocator.resolve(url);
44
		} catch (IOException e) {
45
			return null;
46
		}
47
		if (localUrl.getProtocol().equals("file")) { //$NON-NLS-1$
48
			return new FlatFileIndex(url, new File(localUrl.getPath()));
49
		}
50
		return new JarEntryIndex(url, localUrl);
51
	}
52
	
53
	public IndexLocation(URL url) {
54
		this.url = url;
55
	}
56
57
	public abstract boolean createNewFile() throws IOException;
58
59
	public void close() {
60
		// default nothing to do
61
	}
62
63
	public abstract boolean delete();
64
65
	public abstract boolean exists();
66
	
67
	public abstract String fileName();
68
69
	public abstract File getIndexFile();
70
71
	abstract InputStream getInputStream() throws IOException;
72
73
	public abstract String getFilePath();
74
75
	public URL getUrl() {
76
		return this.url;
77
	}
78
79
	public int hashCode() {
80
		return this.url.hashCode();
81
	}
82
83
	public boolean isParticipantIndex() {
84
		return this.participantIndex;
85
	}
86
87
	public void setParticipantIndex() {
88
		this.participantIndex = true;
89
	}
90
91
	public abstract long lastModified();
92
93
	public abstract long length();
94
95
	public String toString() {
96
		return this.url.toString();
97
	}
98
99
}
(-)a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/JarEntryIndex.java (+101 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2011 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.core.index;
12
13
import java.io.File;
14
import java.io.IOException;
15
import java.io.InputStream;
16
import java.net.JarURLConnection;
17
import java.net.URL;
18
import java.util.jar.JarEntry;
19
import java.util.jar.JarFile;
20
21
public class JarEntryIndex extends IndexLocation {
22
	private JarFile jarFile = null;
23
	private JarEntry jarEntry = null;
24
	private URL localUrl;
25
26
	public JarEntryIndex(URL url, URL localUrl2) {
27
		super(url);
28
		this.localUrl = localUrl2;
29
	}
30
31
	public boolean createNewFile() throws IOException {
32
		return false;
33
	}
34
35
	public void close() {
36
		if (this.jarFile != null) {
37
			try {
38
				this.jarFile.close();
39
			} catch (IOException e) {
40
				// ignore
41
			}
42
			this.jarFile = null;
43
		}
44
	}
45
46
	public boolean delete() {
47
		return false;
48
	}
49
50
	public boolean equals(Object other) {
51
		if (!(other instanceof JarEntryIndex)) return false;
52
		return this.localUrl.equals(((JarEntryIndex) other).localUrl);
53
	}
54
55
	public boolean exists() {
56
		try {
57
			if (this.jarFile == null) {
58
				JarURLConnection connection = (JarURLConnection) this.localUrl.openConnection();
59
				JarFile file = connection.getJarFile();
60
				if (file == null)
61
					return false;
62
				file.close();
63
			}
64
		} catch (IOException e) {
65
			return false;
66
		}
67
		return true;
68
	}
69
70
	public String fileName() {
71
		return null;
72
	}
73
74
	public File getIndexFile() {
75
		return null;
76
	}
77
78
	InputStream getInputStream() throws IOException {
79
		if (this.jarFile == null) {
80
			JarURLConnection connection = (JarURLConnection) this.localUrl.openConnection();
81
			this.jarFile = connection.getJarFile();
82
			this.jarEntry = connection.getJarEntry();
83
		}
84
		if (this.jarFile == null || this.jarEntry == null)
85
			return null;
86
		return this.jarFile.getInputStream(this.jarEntry);
87
	}
88
89
	public String getFilePath() {
90
		return null;
91
	}
92
93
	public long lastModified() {
94
		return -1;
95
	}
96
97
	public long length() {
98
		return -1;
99
	}
100
101
}
(-)a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/IndexSelector.java (-3 / +4 lines)
Lines 27-32 Link Here
27
import org.eclipse.jdt.internal.core.JavaProject;
27
import org.eclipse.jdt.internal.core.JavaProject;
28
import org.eclipse.jdt.internal.core.builder.ReferenceCollection;
28
import org.eclipse.jdt.internal.core.builder.ReferenceCollection;
29
import org.eclipse.jdt.internal.core.builder.State;
29
import org.eclipse.jdt.internal.core.builder.State;
30
import org.eclipse.jdt.internal.core.index.IndexLocation;
30
import org.eclipse.jdt.internal.core.search.indexing.IndexManager;
31
import org.eclipse.jdt.internal.core.search.indexing.IndexManager;
31
import org.eclipse.jdt.internal.core.search.matching.MatchLocator;
32
import org.eclipse.jdt.internal.core.search.matching.MatchLocator;
32
import org.eclipse.jdt.internal.core.search.matching.MethodPattern;
33
import org.eclipse.jdt.internal.core.search.matching.MethodPattern;
Lines 38-44 Link Here
38
public class IndexSelector {
39
public class IndexSelector {
39
	IJavaSearchScope searchScope;
40
	IJavaSearchScope searchScope;
40
	SearchPattern pattern;
41
	SearchPattern pattern;
41
	IPath[] indexLocations; // cache of the keys for looking index up
42
	IndexLocation[] indexLocations; // cache of the keys for looking index up
42
43
43
public IndexSelector(
44
public IndexSelector(
44
		IJavaSearchScope searchScope,
45
		IJavaSearchScope searchScope,
Lines 267-276 Link Here
267
	}
268
	}
268
269
269
	locations.remove(null); // Ensure no nulls
270
	locations.remove(null); // Ensure no nulls
270
	this.indexLocations = (IPath[]) locations.toArray(new IPath[locations.size()]);
271
	this.indexLocations = (IndexLocation[]) locations.toArray(new IndexLocation[locations.size()]);
271
}
272
}
272
273
273
public IPath[] getIndexLocations() {
274
public IndexLocation[] getIndexLocations() {
274
	if (this.indexLocations == null) {
275
	if (this.indexLocations == null) {
275
		initializeIndexLocations();
276
		initializeIndexLocations();
276
	}
277
	}
(-)a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaSearchParticipant.java (+15 lines)
Lines 10-17 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.jdt.internal.core.search;
11
package org.eclipse.jdt.internal.core.search;
12
12
13
13
import org.eclipse.core.runtime.*;
14
import org.eclipse.core.runtime.*;
14
import org.eclipse.jdt.core.search.*;
15
import org.eclipse.jdt.core.search.*;
16
import org.eclipse.jdt.internal.core.index.IndexLocation;
15
import org.eclipse.jdt.internal.core.search.indexing.BinaryIndexer;
17
import org.eclipse.jdt.internal.core.search.indexing.BinaryIndexer;
16
import org.eclipse.jdt.internal.core.search.indexing.SourceIndexer;
18
import org.eclipse.jdt.internal.core.search.indexing.SourceIndexer;
17
import org.eclipse.jdt.internal.core.search.matching.MatchLocator;
19
import org.eclipse.jdt.internal.core.search.matching.MatchLocator;
Lines 98-104 Link Here
98
	 * @see org.eclipse.jdt.core.search.SearchParticipant#selectIndexes(org.eclipse.jdt.core.search.SearchQuery, org.eclipse.jdt.core.search.SearchContext)
100
	 * @see org.eclipse.jdt.core.search.SearchParticipant#selectIndexes(org.eclipse.jdt.core.search.SearchQuery, org.eclipse.jdt.core.search.SearchContext)
99
	 */
101
	 */
100
	public IPath[] selectIndexes(SearchPattern pattern, IJavaSearchScope scope) {
102
	public IPath[] selectIndexes(SearchPattern pattern, IJavaSearchScope scope) {
103
		IndexSelector selector = (IndexSelector) this.indexSelector.get();
104
		if (selector == null) {
105
			selector = new IndexSelector(scope, pattern);
106
			this.indexSelector.set(selector);
107
		}
108
		IndexLocation[] urls = selector.getIndexLocations();
109
		IPath[] paths = new IPath[urls.length];
110
		for (int i = 0; i < urls.length; i++) {
111
			paths[i] = new Path(urls[i].getIndexFile().getPath());
112
		}
113
		return paths;
114
	}
101
115
116
	public IndexLocation[] selectIndexURLs(SearchPattern pattern, IJavaSearchScope scope) {
102
		IndexSelector selector = (IndexSelector) this.indexSelector.get();
117
		IndexSelector selector = (IndexSelector) this.indexSelector.get();
103
		if (selector == null) {
118
		if (selector == null) {
104
			selector = new IndexSelector(scope, pattern);
119
			selector = new IndexSelector(scope, pattern);
(-)a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/PatternSearchJob.java (-2 / +16 lines)
Lines 17-23 Link Here
17
import org.eclipse.core.runtime.OperationCanceledException;
17
import org.eclipse.core.runtime.OperationCanceledException;
18
import org.eclipse.jdt.core.search.*;
18
import org.eclipse.jdt.core.search.*;
19
import org.eclipse.jdt.internal.core.JavaModelManager;
19
import org.eclipse.jdt.internal.core.JavaModelManager;
20
import org.eclipse.jdt.internal.core.index.FlatFileIndex;
20
import org.eclipse.jdt.internal.core.index.Index;
21
import org.eclipse.jdt.internal.core.index.Index;
22
import org.eclipse.jdt.internal.core.index.IndexLocation;
21
import org.eclipse.jdt.internal.core.search.indexing.ReadWriteMonitor;
23
import org.eclipse.jdt.internal.core.search.indexing.ReadWriteMonitor;
22
import org.eclipse.jdt.internal.core.search.matching.MatchLocator;
24
import org.eclipse.jdt.internal.core.search.matching.MatchLocator;
23
import org.eclipse.jdt.internal.core.search.processing.IJob;
25
import org.eclipse.jdt.internal.core.search.processing.IJob;
Lines 76-83 Link Here
76
}
78
}
77
public Index[] getIndexes(IProgressMonitor progressMonitor) {
79
public Index[] getIndexes(IProgressMonitor progressMonitor) {
78
	// acquire the in-memory indexes on the fly
80
	// acquire the in-memory indexes on the fly
79
	IPath[] indexLocations = this.participant.selectIndexes(this.pattern, this.scope);
81
	IndexLocation[] indexLocations;
80
	int length = indexLocations.length;
82
	int length;
83
	if (this.participant instanceof JavaSearchParticipant) {
84
		indexLocations = ((JavaSearchParticipant)this.participant).selectIndexURLs(this.pattern, this.scope);
85
		length = indexLocations.length;
86
	} else {
87
		IPath[] paths = this.participant.selectIndexes(this.pattern, this.scope);
88
		length =paths.length;
89
		indexLocations = new IndexLocation[paths.length];
90
		for (int i = 0; i < paths.length; i++) {
91
			indexLocations[i] = new FlatFileIndex(paths[i].toFile());
92
			indexLocations[i].setParticipantIndex();
93
		}
94
	}
81
	Index[] indexes = JavaModelManager.getIndexManager().getIndexes(indexLocations, progressMonitor);
95
	Index[] indexes = JavaModelManager.getIndexManager().getIndexes(indexLocations, progressMonitor);
82
	this.areIndexesReady = indexes.length == length;
96
	this.areIndexesReady = indexes.length == length;
83
	return indexes;
97
	return indexes;
(-)a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AddJarFileToIndex.java (-5 / +19 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2010 IBM Corporation and others.
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 34-39 Link Here
34
import org.eclipse.jdt.internal.compiler.util.Util;
34
import org.eclipse.jdt.internal.compiler.util.Util;
35
import org.eclipse.jdt.internal.core.JavaModelManager;
35
import org.eclipse.jdt.internal.core.JavaModelManager;
36
import org.eclipse.jdt.internal.core.index.Index;
36
import org.eclipse.jdt.internal.core.index.Index;
37
import org.eclipse.jdt.internal.core.index.IndexLocation;
37
import org.eclipse.jdt.internal.core.search.JavaSearchDocument;
38
import org.eclipse.jdt.internal.core.search.JavaSearchDocument;
38
import org.eclipse.jdt.internal.core.search.processing.JobManager;
39
import org.eclipse.jdt.internal.core.search.processing.JobManager;
39
40
Lines 42-55 Link Here
42
	private static final char JAR_SEPARATOR = IJavaSearchScope.JAR_FILE_ENTRY_SEPARATOR.charAt(0);
43
	private static final char JAR_SEPARATOR = IJavaSearchScope.JAR_FILE_ENTRY_SEPARATOR.charAt(0);
43
	IFile resource;
44
	IFile resource;
44
	Scanner scanner;
45
	Scanner scanner;
46
	private IndexLocation indexFileURL;
45
47
46
	public AddJarFileToIndex(IFile resource, IndexManager manager) {
48
	public AddJarFileToIndex(IFile resource, IndexLocation indexFile, IndexManager manager) {
47
		super(resource.getFullPath(), manager);
49
		super(resource.getFullPath(), manager);
48
		this.resource = resource;
50
		this.resource = resource;
51
		this.indexFileURL = indexFile;
49
	}
52
	}
50
	public AddJarFileToIndex(IPath jarPath, IndexManager manager) {
53
	public AddJarFileToIndex(IPath jarPath, IndexLocation indexFile, IndexManager manager) {
51
		// external JAR scenario - no resource
54
		// external JAR scenario - no resource
52
		super(jarPath, manager);
55
		super(jarPath, manager);
56
		this.indexFileURL = indexFile;
53
	}
57
	}
54
	public boolean equals(Object o) {
58
	public boolean equals(Object o) {
55
		if (o instanceof AddJarFileToIndex) {
59
		if (o instanceof AddJarFileToIndex) {
Lines 70-75 Link Here
70
	public boolean execute(IProgressMonitor progressMonitor) {
74
	public boolean execute(IProgressMonitor progressMonitor) {
71
75
72
		if (this.isCancelled || progressMonitor != null && progressMonitor.isCanceled()) return true;
76
		if (this.isCancelled || progressMonitor != null && progressMonitor.isCanceled()) return true;
77
78
		if (this.indexFileURL != null) {
79
			boolean added = this.manager.addIndex(this.containerPath, this.indexFileURL);
80
			if (added) return true;	
81
			this.indexFileURL = null;
82
		}
73
83
74
		try {
84
		try {
75
			// if index is already cached, then do not perform any check
85
			// if index is already cached, then do not perform any check
Lines 192-198 Link Here
192
					return false;
202
					return false;
193
				}
203
				}
194
				index.separator = JAR_SEPARATOR;
204
				index.separator = JAR_SEPARATOR;
195
205
				IPath indexPath = null;
206
				IndexLocation indexLocation;
207
				if ((indexLocation = index.getIndexLocation()) != null) {
208
					indexPath = new Path(indexLocation.getFilePath());
209
				}
196
				for (Enumeration e = zip.entries(); e.hasMoreElements();) {
210
				for (Enumeration e = zip.entries(); e.hasMoreElements();) {
197
					if (this.isCancelled) {
211
					if (this.isCancelled) {
198
						if (JobManager.VERBOSE)
212
						if (JobManager.VERBOSE)
Lines 208-214 Link Here
208
						// index only classes coming from valid packages - https://bugs.eclipse.org/bugs/show_bug.cgi?id=293861
222
						// index only classes coming from valid packages - https://bugs.eclipse.org/bugs/show_bug.cgi?id=293861
209
						final byte[] classFileBytes = org.eclipse.jdt.internal.compiler.util.Util.getZipEntryByteContent(ze, zip);
223
						final byte[] classFileBytes = org.eclipse.jdt.internal.compiler.util.Util.getZipEntryByteContent(ze, zip);
210
						JavaSearchDocument entryDocument = new JavaSearchDocument(ze, zipFilePath, classFileBytes, participant);
224
						JavaSearchDocument entryDocument = new JavaSearchDocument(ze, zipFilePath, classFileBytes, participant);
211
						this.manager.indexDocument(entryDocument, participant, index, this.containerPath);
225
						this.manager.indexDocument(entryDocument, participant, index, indexPath);
212
					}
226
					}
213
				}
227
				}
214
				this.manager.saveIndex(index);
228
				this.manager.saveIndex(index);
(-)a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/DefaultJavaIndexer.java (+51 lines)
Added Link Here
1
package org.eclipse.jdt.internal.core.search.indexing;
2
3
import java.io.File;
4
import java.io.FileNotFoundException;
5
import java.io.IOException;
6
import java.util.Enumeration;
7
import java.util.zip.ZipEntry;
8
import java.util.zip.ZipFile;
9
10
import org.eclipse.core.runtime.Path;
11
import org.eclipse.jdt.core.search.IJavaSearchScope;
12
import org.eclipse.jdt.core.search.SearchEngine;
13
import org.eclipse.jdt.core.search.SearchParticipant;
14
import org.eclipse.jdt.internal.compiler.util.Util;
15
import org.eclipse.jdt.internal.core.index.FlatFileIndex;
16
import org.eclipse.jdt.internal.core.index.Index;
17
import org.eclipse.jdt.internal.core.index.IndexLocation;
18
import org.eclipse.jdt.internal.core.search.JavaSearchDocument;
19
20
public class DefaultJavaIndexer {
21
	private static final char JAR_SEPARATOR = IJavaSearchScope.JAR_FILE_ENTRY_SEPARATOR.charAt(0);
22
	
23
	public void generateIndexForJar(String pathToJar, String pathToIndexFile) throws IOException {
24
		File f = new File(pathToJar); 
25
		if (!f.exists()) {
26
			throw new FileNotFoundException(pathToJar + "not found"); //$NON-NLS-1$
27
		}
28
		IndexLocation indexLocation = new FlatFileIndex(new File(pathToIndexFile));
29
		Index index = new Index(indexLocation, pathToJar, false /*reuse index file*/);
30
		SearchParticipant participant = SearchEngine.getDefaultSearchParticipant();
31
		index.separator = JAR_SEPARATOR;
32
		ZipFile zip = new ZipFile(pathToJar);
33
		for (Enumeration e = zip.entries(); e.hasMoreElements();) {
34
			// iterate each entry to index it
35
			ZipEntry ze = (ZipEntry) e.nextElement();
36
			String zipEntryName = ze.getName();
37
			if (Util.isClassFileName(zipEntryName)) {
38
				final byte[] classFileBytes = org.eclipse.jdt.internal.compiler.util.Util.getZipEntryByteContent(ze, zip);
39
				JavaSearchDocument entryDocument = new JavaSearchDocument(ze, new Path(pathToJar), classFileBytes, participant);
40
				entryDocument.setIndex(index);
41
				if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(entryDocument.getPath())) {
42
					new BinaryIndexer(entryDocument).indexDocument();
43
				}
44
			}
45
		}
46
		zip.close();
47
		index.save();
48
		return;
49
	}
50
51
}
(-)a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexAllProject.java (-3 / +3 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2009 IBM Corporation and others.
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 77-83 Link Here
77
					if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY && entry.getPath().equals(projectPath)) {
77
					if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY && entry.getPath().equals(projectPath)) {
78
						// the project is also a library folder (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=89815)
78
						// the project is also a library folder (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=89815)
79
						// ensure a job exists to index it as a binary folder
79
						// ensure a job exists to index it as a binary folder
80
						this.manager.indexLibrary(projectPath, this.project);
80
						this.manager.indexLibrary(projectPath, this.project, ((ClasspathEntry)entry).getLibraryIndexLocation());
81
						return true;
81
						return true;
82
					}
82
					}
83
				}
83
				}
Lines 107-113 Link Here
107
				for (int i = 0; i < max; i++)
107
				for (int i = 0; i < max; i++)
108
					indexedFileNames.put(paths[i], DELETED);
108
					indexedFileNames.put(paths[i], DELETED);
109
			}
109
			}
110
			final long indexLastModified = max == 0 ? 0L : index.getIndexFile().lastModified();
110
			final long indexLastModified = max == 0 ? 0L : index.getIndexLastModified();
111
111
112
			IWorkspaceRoot root = this.project.getWorkspace().getRoot();
112
			IWorkspaceRoot root = this.project.getWorkspace().getRoot();
113
			for (int i = 0; i < sourceEntriesNumber; i++) {
113
			for (int i = 0; i < sourceEntriesNumber; i++) {
(-)a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexBinaryFolder.java (-1 / +1 lines)
Lines 80-86 Link Here
80
				for (int i = 0; i < max; i++) {
80
				for (int i = 0; i < max; i++) {
81
					indexedFileNames.put(paths[i], DELETED);
81
					indexedFileNames.put(paths[i], DELETED);
82
				}
82
				}
83
				final long indexLastModified = index.getIndexFile().lastModified();
83
				final long indexLastModified = index.getIndexLastModified();
84
				this.folder.accept(
84
				this.folder.accept(
85
					new IResourceProxyVisitor() {
85
					new IResourceProxyVisitor() {
86
						public boolean visit(IResourceProxy proxy) throws CoreException {
86
						public boolean visit(IResourceProxy proxy) throws CoreException {
(-)a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexManager.java (-88 / +123 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2010 IBM Corporation and others.
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 11-16 Link Here
11
package org.eclipse.jdt.internal.core.search.indexing;
11
package org.eclipse.jdt.internal.core.search.indexing;
12
12
13
import java.io.*;
13
import java.io.*;
14
import java.net.URL;
14
import java.util.*;
15
import java.util.*;
15
import java.util.zip.CRC32;
16
import java.util.zip.CRC32;
16
17
Lines 59-64 Link Here
59
	public static final Integer UPDATING_STATE = new Integer(1);
60
	public static final Integer UPDATING_STATE = new Integer(1);
60
	public static final Integer UNKNOWN_STATE = new Integer(2);
61
	public static final Integer UNKNOWN_STATE = new Integer(2);
61
	public static final Integer REBUILDING_STATE = new Integer(3);
62
	public static final Integer REBUILDING_STATE = new Integer(3);
63
	public static final Integer REUSE_STATE = new Integer(4);
62
	
64
	
63
	// search participants who register indexes with the index manager
65
	// search participants who register indexes with the index manager
64
	private SimpleLookupTable participantsContainers = null;
66
	private SimpleLookupTable participantsContainers = null;
Lines 70-79 Link Here
70
	public synchronized void aboutToUpdateIndex(IPath containerPath, Integer newIndexState) {
72
	public synchronized void aboutToUpdateIndex(IPath containerPath, Integer newIndexState) {
71
	// newIndexState is either UPDATING_STATE or REBUILDING_STATE
73
	// newIndexState is either UPDATING_STATE or REBUILDING_STATE
72
	// must tag the index as inconsistent, in case we exit before the update job is started
74
	// must tag the index as inconsistent, in case we exit before the update job is started
73
	IPath indexLocation = computeIndexLocation(containerPath);
75
	IndexLocation indexLocation = computeIndexLocation(containerPath);
74
	Object state = getIndexStates().get(indexLocation);
76
	Object state = getIndexStates().get(indexLocation);
75
	Integer currentIndexState = state == null ? UNKNOWN_STATE : (Integer) state;
77
	Integer currentIndexState = state == null ? UNKNOWN_STATE : (Integer) state;
76
	if (currentIndexState.equals(REBUILDING_STATE)) return; // already rebuilding the index
78
	if (currentIndexState.compareTo(REBUILDING_STATE) >= 0) return; // already rebuilding the index
77
79
78
	int compare = newIndexState.compareTo(currentIndexState);
80
	int compare = newIndexState.compareTo(currentIndexState);
79
	if (compare > 0) {
81
	if (compare > 0) {
Lines 92-98 Link Here
92
	if (JavaCore.getPlugin() == null) return;
94
	if (JavaCore.getPlugin() == null) return;
93
	SearchParticipant participant = SearchEngine.getDefaultSearchParticipant();
95
	SearchParticipant participant = SearchEngine.getDefaultSearchParticipant();
94
	SearchDocument document = participant.getDocument(resource.getFullPath().toString());
96
	SearchDocument document = participant.getDocument(resource.getFullPath().toString());
95
	IPath indexLocation = computeIndexLocation(containerPath);
97
	IndexLocation indexLocation = computeIndexLocation(containerPath);
96
	scheduleDocumentIndexing(document, containerPath, indexLocation, participant);
98
	scheduleDocumentIndexing(document, containerPath, indexLocation, participant);
97
}
99
}
98
/**
100
/**
Lines 104-110 Link Here
104
	SearchParticipant participant = SearchEngine.getDefaultSearchParticipant();
106
	SearchParticipant participant = SearchEngine.getDefaultSearchParticipant();
105
	SearchDocument document = participant.getDocument(resource.getFullPath().toString());
107
	SearchDocument document = participant.getDocument(resource.getFullPath().toString());
106
	document.setParser(parser);
108
	document.setParser(parser);
107
	IPath indexLocation = computeIndexLocation(containerPath);
109
	IndexLocation indexLocation = computeIndexLocation(containerPath);
108
	scheduleDocumentIndexing(document, containerPath, indexLocation, participant);
110
	scheduleDocumentIndexing(document, containerPath, indexLocation, participant);
109
}
111
}
110
/*
112
/*
Lines 116-132 Link Here
116
	PatternSearchJob job = new PatternSearchJob(null, SearchEngine.getDefaultSearchParticipant(), scope, null);
118
	PatternSearchJob job = new PatternSearchJob(null, SearchEngine.getDefaultSearchParticipant(), scope, null);
117
	Index[] selectedIndexes = job.getIndexes(null);
119
	Index[] selectedIndexes = job.getIndexes(null);
118
	for (int i = 0, l = selectedIndexes.length; i < l; i++) {
120
	for (int i = 0, l = selectedIndexes.length; i < l; i++) {
119
		String path = selectedIndexes[i].getIndexFile().getAbsolutePath();
121
		IndexLocation IndexLocation = selectedIndexes[i].getIndexLocation();
120
		knownPaths.add(path);
122
		knownPaths.add(IndexLocation);
121
	}
123
	}
122
124
123
	if (this.indexStates != null) {
125
	if (this.indexStates != null) {
124
		Object[] keys = this.indexStates.keyTable;
126
		Object[] keys = this.indexStates.keyTable;
125
		IPath[] locations = new IPath[this.indexStates.elementSize];
127
		IndexLocation[] locations = new IndexLocation[this.indexStates.elementSize];
126
		int count = 0;
128
		int count = 0;
127
		for (int i = 0, l = keys.length; i < l; i++) {
129
		for (int i = 0, l = keys.length; i < l; i++) {
128
			IPath key = (IPath) keys[i];
130
			IndexLocation key = (IndexLocation) keys[i];
129
			if (key != null && !knownPaths.includes(key.toOSString()))
131
			if (key != null && !knownPaths.includes(key))
130
				locations[count++] = key;
132
				locations[count++] = key;
131
		}
133
		}
132
		if (count > 0)
134
		if (count > 0)
Lines 134-141 Link Here
134
	}
136
	}
135
	deleteIndexFiles(knownPaths);
137
	deleteIndexFiles(knownPaths);
136
}
138
}
137
public synchronized IPath computeIndexLocation(IPath containerPath) {
139
public synchronized IndexLocation computeIndexLocation(IPath containerPath) {
138
	IPath indexLocation = (IPath) this.indexLocations.get(containerPath);
140
	IndexLocation indexLocation = (IndexLocation) this.indexLocations.get(containerPath);
139
	if (indexLocation == null) {
141
	if (indexLocation == null) {
140
		String pathString = containerPath.toOSString();
142
		String pathString = containerPath.toOSString();
141
		CRC32 checksumCalculator = new CRC32();
143
		CRC32 checksumCalculator = new CRC32();
Lines 144-150 Link Here
144
		if (VERBOSE)
146
		if (VERBOSE)
145
			Util.verbose("-> index name for " + pathString + " is " + fileName); //$NON-NLS-1$ //$NON-NLS-2$
147
			Util.verbose("-> index name for " + pathString + " is " + fileName); //$NON-NLS-1$ //$NON-NLS-2$
146
		// to share the indexLocation between the indexLocations and indexStates tables, get the key from the indexStates table
148
		// to share the indexLocation between the indexLocations and indexStates tables, get the key from the indexStates table
147
		indexLocation = (IPath) getIndexStates().getKey(getJavaPluginWorkingLocation().append(fileName));
149
		indexLocation = (IndexLocation) getIndexStates().getKey(new FlatFileIndex(new File(getSavedIndexesDirectory(), fileName)));
148
		this.indexLocations.put(containerPath, indexLocation);
150
		this.indexLocations.put(containerPath, indexLocation);
149
	}
151
	}
150
	return indexLocation;
152
	return indexLocation;
Lines 161-167 Link Here
161
163
162
	for (int i = 0, l = indexesFiles.length; i < l; i++) {
164
	for (int i = 0, l = indexesFiles.length; i < l; i++) {
163
		String fileName = indexesFiles[i].getAbsolutePath();
165
		String fileName = indexesFiles[i].getAbsolutePath();
164
		if (pathsToKeep != null && pathsToKeep.includes(fileName)) continue;
166
		if (pathsToKeep != null && pathsToKeep.includes(new FlatFileIndex(indexesFiles[i]))) continue;
165
		String suffix = ".index"; //$NON-NLS-1$
167
		String suffix = ".index"; //$NON-NLS-1$
166
		if (fileName.regionMatches(true, fileName.length() - suffix.length(), suffix, 0, suffix.length())) {
168
		if (fileName.regionMatches(true, fileName.length() - suffix.length(), suffix, 0, suffix.length())) {
167
			if (VERBOSE || DEBUG)
169
			if (VERBOSE || DEBUG)
Lines 173-179 Link Here
173
/*
175
/*
174
 * Creates an empty index at the given location, for the given container path, if none exist.
176
 * Creates an empty index at the given location, for the given container path, if none exist.
175
 */
177
 */
176
public synchronized void ensureIndexExists(IPath indexLocation, IPath containerPath) {
178
public synchronized void ensureIndexExists(IndexLocation indexLocation, IPath containerPath) {
177
	SimpleLookupTable states = getIndexStates();
179
	SimpleLookupTable states = getIndexStates();
178
	Object state = states.get(indexLocation);
180
	Object state = states.get(indexLocation);
179
	if (state == null) {
181
	if (state == null) {
Lines 207-213 Link Here
207
 * @param indexLocation The path of the index file
209
 * @param indexLocation The path of the index file
208
 * @return The corresponding index or <code>null</code> if not found
210
 * @return The corresponding index or <code>null</code> if not found
209
 */
211
 */
210
public synchronized Index getIndex(IPath indexLocation) {
212
public synchronized Index getIndex(IndexLocation indexLocation) {
211
	return (Index) this.indexes.get(indexLocation); // is null if unknown, call if the containerPath must be computed
213
	return (Index) this.indexes.get(indexLocation); // is null if unknown, call if the containerPath must be computed
212
}
214
}
213
/**
215
/**
Lines 219-225 Link Here
219
 * Warning: Does not check whether index is consistent (not being used)
221
 * Warning: Does not check whether index is consistent (not being used)
220
 */
222
 */
221
public synchronized Index getIndex(IPath containerPath, boolean reuseExistingFile, boolean createIfMissing) {
223
public synchronized Index getIndex(IPath containerPath, boolean reuseExistingFile, boolean createIfMissing) {
222
	IPath indexLocation = computeIndexLocation(containerPath);
224
	IndexLocation indexLocation = computeIndexLocation(containerPath);
223
	return getIndex(containerPath, indexLocation, reuseExistingFile, createIfMissing);
225
	return getIndex(containerPath, indexLocation, reuseExistingFile, createIfMissing);
224
}
226
}
225
/**
227
/**
Lines 230-236 Link Here
230
 *
232
 *
231
 * Warning: Does not check whether index is consistent (not being used)
233
 * Warning: Does not check whether index is consistent (not being used)
232
 */
234
 */
233
public synchronized Index getIndex(IPath containerPath, IPath indexLocation, boolean reuseExistingFile, boolean createIfMissing) {
235
public synchronized Index getIndex(IPath containerPath, IndexLocation indexLocation, boolean reuseExistingFile, boolean createIfMissing) {
234
	// Path is already canonical per construction
236
	// Path is already canonical per construction
235
	Index index = getIndex(indexLocation);
237
	Index index = getIndex(indexLocation);
236
	if (index == null) {
238
	if (index == null) {
Lines 245-263 Link Here
245
247
246
		// index isn't cached, consider reusing an existing index file
248
		// index isn't cached, consider reusing an existing index file
247
		String containerPathString = containerPath.getDevice() == null ? containerPath.toString() : containerPath.toOSString();
249
		String containerPathString = containerPath.getDevice() == null ? containerPath.toString() : containerPath.toOSString();
248
		String indexLocationString = indexLocation.toOSString();
249
		if (reuseExistingFile) {
250
		if (reuseExistingFile) {
250
			File indexFile = new File(indexLocationString);
251
			if (indexLocation.exists()) { // check before creating index so as to avoid creating a new empty index if file is missing
251
			if (indexFile.exists()) { // check before creating index so as to avoid creating a new empty index if file is missing
252
				try {
252
				try {
253
					index = new Index(indexLocationString, containerPathString, true /*reuse index file*/);
253
					index = new Index(indexLocation, containerPathString, true /*reuse index file*/);
254
					this.indexes.put(indexLocation, index);
254
					this.indexes.put(indexLocation, index);
255
					return index;
255
					return index;
256
				} catch (IOException e) {
256
				} catch (IOException e) {
257
					// failed to read the existing file or its no longer compatible
257
					// failed to read the existing file or its no longer compatible
258
					if (currentIndexState != REBUILDING_STATE) { // rebuild index if existing file is corrupt, unless the index is already being rebuilt
258
					if (currentIndexState != REBUILDING_STATE || currentIndexState != REUSE_STATE) { // rebuild index if existing file is corrupt, unless the index is already being rebuilt
259
						if (VERBOSE)
259
						if (VERBOSE)
260
							Util.verbose("-> cannot reuse existing index: "+indexLocationString+" path: "+containerPathString); //$NON-NLS-1$ //$NON-NLS-2$
260
							Util.verbose("-> cannot reuse existing index: "+indexLocation+" path: "+containerPathString); //$NON-NLS-1$ //$NON-NLS-2$
261
						rebuildIndex(indexLocation, containerPath);
261
						rebuildIndex(indexLocation, containerPath);
262
						return null;
262
						return null;
263
					}
263
					}
Lines 268-285 Link Here
268
				rebuildIndex(indexLocation, containerPath);
268
				rebuildIndex(indexLocation, containerPath);
269
				return null;
269
				return null;
270
			}
270
			}
271
			if (currentIndexState == REUSE_STATE) {
272
				// supposed to be in reuse state but error in the index file, so reindex.
273
				if (VERBOSE)
274
					Util.verbose("-> cannot reuse given index: "+indexLocation+" path: "+containerPathString); //$NON-NLS-1$ //$NON-NLS-2$
275
				this.indexLocations.put(containerPath, null);
276
				indexLocation = computeIndexLocation(containerPath);
277
				rebuildIndex(indexLocation, containerPath);
278
				return null;
279
			}
271
		}
280
		}
272
		// index wasn't found on disk, consider creating an empty new one
281
		// index wasn't found on disk, consider creating an empty new one
273
		if (createIfMissing) {
282
		if (createIfMissing) {
274
			try {
283
			try {
275
				if (VERBOSE)
284
				if (VERBOSE)
276
					Util.verbose("-> create empty index: "+indexLocationString+" path: "+containerPathString); //$NON-NLS-1$ //$NON-NLS-2$
285
					Util.verbose("-> create empty index: "+indexLocation+" path: "+containerPathString); //$NON-NLS-1$ //$NON-NLS-2$
277
				index = new Index(indexLocationString, containerPathString, false /*do not reuse index file*/);
286
				index = new Index(indexLocation, containerPathString, false /*do not reuse index file*/);
278
				this.indexes.put(indexLocation, index);
287
				this.indexes.put(indexLocation, index);
279
				return index;
288
				return index;
280
			} catch (IOException e) {
289
			} catch (IOException e) {
281
				if (VERBOSE)
290
				if (VERBOSE)
282
					Util.verbose("-> unable to create empty index: "+indexLocationString+" path: "+containerPathString); //$NON-NLS-1$ //$NON-NLS-2$
291
					Util.verbose("-> unable to create empty index: "+indexLocation+" path: "+containerPathString); //$NON-NLS-1$ //$NON-NLS-2$
283
				// The file could not be created. Possible reason: the project has been deleted.
292
				// The file could not be created. Possible reason: the project has been deleted.
284
				return null;
293
				return null;
285
			}
294
			}
Lines 295-301 Link Here
295
 * @param locations The list of of the index files path
304
 * @param locations The list of of the index files path
296
 * @return The corresponding indexes list.
305
 * @return The corresponding indexes list.
297
 */
306
 */
298
public Index[] getIndexes(IPath[] locations, IProgressMonitor progressMonitor) {
307
public Index[] getIndexes(IndexLocation[] locations, IProgressMonitor progressMonitor) {
299
	// acquire the in-memory indexes on the fly
308
	// acquire the in-memory indexes on the fly
300
	int length = locations.length;
309
	int length = locations.length;
301
	Index[] locatedIndexes = new Index[length];
310
	Index[] locatedIndexes = new Index[length];
Lines 308-314 Link Here
308
			throw new OperationCanceledException();
317
			throw new OperationCanceledException();
309
		}
318
		}
310
		// may trigger some index recreation work
319
		// may trigger some index recreation work
311
		IPath indexLocation = locations[i];
320
		IndexLocation indexLocation = locations[i];
312
		Index index = getIndex(indexLocation);
321
		Index index = getIndex(indexLocation);
313
		if (index == null) {
322
		if (index == null) {
314
			// only need containerPath if the index must be built
323
			// only need containerPath if the index must be built
Lines 330-347 Link Here
330
					index = null;
339
					index = null;
331
				}
340
				}
332
			} else {
341
			} else {
333
				if (!getJavaPluginWorkingLocation().isPrefixOf(indexLocation)) { // the index belongs to non-jdt search participant
342
				if (indexLocation.isParticipantIndex() && indexLocation.exists()) { // the index belongs to non-jdt search participant
334
					if (indexLocation.toFile().exists()) { 
343
					try {
335
						try {
344
						IPath container = getParticipantsContainer(indexLocation);
336
							IPath container = getParticipantsContainer(indexLocation);
345
						if (container != null) {
337
							if (container != null) {
346
							index = new Index(indexLocation, container.toOSString(), true /*reuse index file*/);
338
								index = new Index(indexLocation.toOSString(), container.toOSString(), true /*reuse index file*/);
347
							this.indexes.put(indexLocation, index);
339
								this.indexes.put(indexLocation, index);
340
							}
341
						} catch (IOException e) {
342
							// ignore
343
						}
348
						}
344
					} 
349
					} catch (IOException e) {
350
						// ignore
351
					}
345
				}
352
				}
346
			}
353
			}
347
		}
354
		}
Lines 358-364 Link Here
358
	return locatedIndexes;
365
	return locatedIndexes;
359
}
366
}
360
public synchronized Index getIndexForUpdate(IPath containerPath, boolean reuseExistingFile, boolean createIfMissing) {
367
public synchronized Index getIndexForUpdate(IPath containerPath, boolean reuseExistingFile, boolean createIfMissing) {
361
	IPath indexLocation = computeIndexLocation(containerPath);
368
	IndexLocation indexLocation = computeIndexLocation(containerPath);
362
	if (getIndexStates().get(indexLocation) == REBUILDING_STATE)
369
	if (getIndexStates().get(indexLocation) == REBUILDING_STATE)
363
		return getIndex(containerPath, indexLocation, reuseExistingFile, createIfMissing);
370
		return getIndex(containerPath, indexLocation, reuseExistingFile, createIfMissing);
364
371
Lines 368-380 Link Here
368
	if (this.indexStates != null) return this.indexStates;
375
	if (this.indexStates != null) return this.indexStates;
369
376
370
	this.indexStates = new SimpleLookupTable();
377
	this.indexStates = new SimpleLookupTable();
371
	IPath indexesDirectoryPath = getJavaPluginWorkingLocation();
378
	File indexesDirectoryPath = getSavedIndexesDirectory();
372
	char[][] savedNames = readIndexState(indexesDirectoryPath.toOSString());
379
	char[][] savedNames = readIndexState(getJavaPluginWorkingLocation().toOSString());
373
	if (savedNames != null) {
380
	if (savedNames != null) {
374
		for (int i = 1, l = savedNames.length; i < l; i++) { // first name is saved signature, see readIndexState()
381
		for (int i = 1, l = savedNames.length; i < l; i++) { // first name is saved signature, see readIndexState()
375
			char[] savedName = savedNames[i];
382
			char[] savedName = savedNames[i];
376
			if (savedName.length > 0) {
383
			if (savedName.length > 0) {
377
				IPath indexLocation = indexesDirectoryPath.append(new String(savedName)); // shares indexesDirectoryPath's segments
384
				IndexLocation indexLocation = new FlatFileIndex(new File(indexesDirectoryPath, String.valueOf(savedName))); // shares indexesDirectoryPath's segments
378
				if (VERBOSE)
385
				if (VERBOSE)
379
					Util.verbose("Reading saved index file " + indexLocation); //$NON-NLS-1$
386
					Util.verbose("Reading saved index file " + indexLocation); //$NON-NLS-1$
380
				this.indexStates.put(indexLocation, SAVED_STATE);
387
				this.indexStates.put(indexLocation, SAVED_STATE);
Lines 389-395 Link Here
389
	}
396
	}
390
	return this.indexStates;
397
	return this.indexStates;
391
}
398
}
392
private IPath getParticipantsContainer(IPath indexLocation) {
399
private IPath getParticipantsContainer(IndexLocation indexLocation) {
393
	if (this.participantsContainers == null) {
400
	if (this.participantsContainers == null) {
394
		readParticipantsIndexNamesFile();
401
		readParticipantsIndexNamesFile();
395
	}
402
	}
Lines 474-480 Link Here
474
		for (int i = 0; i < entries.length; i++) {
481
		for (int i = 0; i < entries.length; i++) {
475
			IClasspathEntry entry= entries[i];
482
			IClasspathEntry entry= entries[i];
476
			if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY)
483
			if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY)
477
				indexLibrary(entry.getPath(), project);
484
				indexLibrary(entry.getPath(), project, ((ClasspathEntry)entry).getLibraryIndexLocation());
478
		}
485
		}
479
	} catch(JavaModelException e){ // cannot retrieve classpath info
486
	} catch(JavaModelException e){ // cannot retrieve classpath info
480
	}
487
	}
Lines 488-503 Link Here
488
 * Trigger addition of a library to an index
495
 * Trigger addition of a library to an index
489
 * Note: the actual operation is performed in background
496
 * Note: the actual operation is performed in background
490
 */
497
 */
491
public void indexLibrary(IPath path, IProject requestingProject) {
498
public void indexLibrary(IPath path, IProject requestingProject, URL indexURL) {
492
	// requestingProject is no longer used to cancel jobs but leave it here just in case
499
	// requestingProject is no longer used to cancel jobs but leave it here just in case
500
	IndexLocation indexFile = indexURL != null ? IndexLocation.createIndexLocation(indexURL): null;
493
	if (JavaCore.getPlugin() == null) return;
501
	if (JavaCore.getPlugin() == null) return;
494
495
	Object target = JavaModel.getTarget(path, true);
496
	IndexRequest request = null;
502
	IndexRequest request = null;
503
	Object target = JavaModel.getTarget(path, true);
497
	if (target instanceof IFile) {
504
	if (target instanceof IFile) {
498
		request = new AddJarFileToIndex((IFile) target, this);
505
		request = new AddJarFileToIndex((IFile) target, indexFile, this);
499
	} else if (target instanceof File) {
506
	} else if (target instanceof File) {
500
		request = new AddJarFileToIndex(path, this);
507
		request = new AddJarFileToIndex(path, indexFile, this);
501
	} else if (target instanceof IContainer) {
508
	} else if (target instanceof IContainer) {
502
		request = new IndexBinaryFolder((IContainer) target, this);
509
		request = new IndexBinaryFolder((IContainer) target, this);
503
	} else {
510
	} else {
Lines 508-513 Link Here
508
	if (!isJobWaiting(request))
515
	if (!isJobWaiting(request))
509
		request(request);
516
		request(request);
510
}
517
}
518
519
synchronized boolean addIndex(IPath containerPath, IndexLocation indexFile) {
520
	this.indexStates.put(indexFile, REUSE_STATE);
521
	this.indexLocations.put(containerPath, indexFile);
522
	Index index = getIndex(containerPath, indexFile, true, false);
523
	if (index == null) {
524
		indexFile.close();
525
		this.indexLocations.put(containerPath, null);
526
		return false;
527
	}
528
	return true;
529
}
530
511
/**
531
/**
512
 * Index the content of the given source folder.
532
 * Index the content of the given source folder.
513
 */
533
 */
Lines 522-528 Link Here
522
	request(new AddFolderToIndex(sourceFolder, project, inclusionPatterns, exclusionPatterns, this));
542
	request(new AddFolderToIndex(sourceFolder, project, inclusionPatterns, exclusionPatterns, this));
523
}
543
}
524
public synchronized void jobWasCancelled(IPath containerPath) {
544
public synchronized void jobWasCancelled(IPath containerPath) {
525
	IPath indexLocation = computeIndexLocation(containerPath);
545
	IndexLocation indexLocation = computeIndexLocation(containerPath);
526
	Index index = getIndex(indexLocation);
546
	Index index = getIndex(indexLocation);
527
	if (index != null) {
547
	if (index != null) {
528
		index.monitor = null;
548
		index.monitor = null;
Lines 568-574 Link Here
568
	}
588
	}
569
	return null;
589
	return null;
570
}
590
}
571
private void rebuildIndex(IPath indexLocation, IPath containerPath) {
591
private void rebuildIndex(IndexLocation indexLocation, IPath containerPath) {
572
	Object target = JavaModel.getTarget(containerPath, true);
592
	Object target = JavaModel.getTarget(containerPath, true);
573
	if (target == null) return;
593
	if (target == null) return;
574
594
Lines 584-592 Link Here
584
	} else if (target instanceof IFolder) {
604
	} else if (target instanceof IFolder) {
585
		request = new IndexBinaryFolder((IFolder) target, this);
605
		request = new IndexBinaryFolder((IFolder) target, this);
586
	} else if (target instanceof IFile) {
606
	} else if (target instanceof IFile) {
587
		request = new AddJarFileToIndex((IFile) target, this);
607
		request = new AddJarFileToIndex((IFile) target, null, this);
588
	} else if (target instanceof File) {
608
	} else if (target instanceof File) {
589
		request = new AddJarFileToIndex(containerPath, this);
609
		request = new AddJarFileToIndex(containerPath, null, this);
590
	}
610
	}
591
	if (request != null)
611
	if (request != null)
592
		request(request);
612
		request(request);
Lines 601-613 Link Here
601
	String containerPathString = containerPath.getDevice() == null ? containerPath.toString() : containerPath.toOSString();
621
	String containerPathString = containerPath.getDevice() == null ? containerPath.toString() : containerPath.toOSString();
602
	try {
622
	try {
603
		// Path is already canonical
623
		// Path is already canonical
604
		IPath indexLocation = computeIndexLocation(containerPath);
624
		IndexLocation indexLocation = computeIndexLocation(containerPath);
605
		Index index = getIndex(indexLocation);
625
		Index index = getIndex(indexLocation);
606
		ReadWriteMonitor monitor = index == null ? null : index.monitor;
626
		ReadWriteMonitor monitor = index == null ? null : index.monitor;
607
627
608
		if (VERBOSE)
628
		if (VERBOSE)
609
			Util.verbose("-> recreating index: "+indexLocation+" for path: "+containerPathString); //$NON-NLS-1$ //$NON-NLS-2$
629
			Util.verbose("-> recreating index: "+indexLocation+" for path: "+containerPathString); //$NON-NLS-1$ //$NON-NLS-2$
610
		index = new Index(indexLocation.toOSString(), containerPathString, false /*do not reuse index file*/);
630
		index = new Index(indexLocation, containerPathString, false /*do not reuse index file*/);
611
		this.indexes.put(indexLocation, index);
631
		this.indexes.put(indexLocation, index);
612
		index.monitor = monitor;
632
		index.monitor = monitor;
613
		return index;
633
		return index;
Lines 634-640 Link Here
634
public synchronized void removeIndex(IPath containerPath) {
654
public synchronized void removeIndex(IPath containerPath) {
635
	if (VERBOSE || DEBUG)
655
	if (VERBOSE || DEBUG)
636
		Util.verbose("removing index " + containerPath); //$NON-NLS-1$
656
		Util.verbose("removing index " + containerPath); //$NON-NLS-1$
637
	IPath indexLocation = computeIndexLocation(containerPath);
657
	IndexLocation indexLocation = computeIndexLocation(containerPath);
638
	Index index = getIndex(indexLocation);
658
	Index index = getIndex(indexLocation);
639
	File indexFile = null;
659
	File indexFile = null;
640
	if (index != null) {
660
	if (index != null) {
Lines 642-649 Link Here
642
		indexFile = index.getIndexFile();
662
		indexFile = index.getIndexFile();
643
	}
663
	}
644
	if (indexFile == null)
664
	if (indexFile == null)
645
		indexFile = new File(indexLocation.toOSString()); // index is not cached yet, but still want to delete the file
665
		indexFile = indexLocation.getIndexFile(); // index is not cached yet, but still want to delete the file
646
	if (indexFile.exists()) {
666
	if (this.indexStates.get(indexLocation) == REUSE_STATE) {
667
		indexLocation.close();
668
		this.indexLocations.put(containerPath, null);
669
	} else if (indexFile != null && indexFile.exists()) {
647
		if (DEBUG)
670
		if (DEBUG)
648
			Util.verbose("removing index file " + indexFile); //$NON-NLS-1$
671
			Util.verbose("removing index file " + indexFile); //$NON-NLS-1$
649
		indexFile.delete();
672
		indexFile.delete();
Lines 659-682 Link Here
659
		Util.verbose("removing index path " + path); //$NON-NLS-1$
682
		Util.verbose("removing index path " + path); //$NON-NLS-1$
660
	Object[] keyTable = this.indexes.keyTable;
683
	Object[] keyTable = this.indexes.keyTable;
661
	Object[] valueTable = this.indexes.valueTable;
684
	Object[] valueTable = this.indexes.valueTable;
662
	IPath[] locations = null;
685
	IndexLocation[] locations = null;
663
	int max = this.indexes.elementSize;
686
	int max = this.indexes.elementSize;
664
	int count = 0;
687
	int count = 0;
665
	for (int i = 0, l = keyTable.length; i < l; i++) {
688
	for (int i = 0, l = keyTable.length; i < l; i++) {
666
		IPath indexLocation = (IPath) keyTable[i];
689
		IndexLocation indexLocation = (IndexLocation) keyTable[i];
667
		if (indexLocation == null)
690
		if (indexLocation == null)
668
			continue;
691
			continue;
669
		if (path.isPrefixOf(indexLocation)) {
692
		if (path.isPrefixOf(new Path(indexLocation.getFilePath()))) {
670
			Index index = (Index) valueTable[i];
693
			Index index = (Index) valueTable[i];
671
			index.monitor = null;
694
			index.monitor = null;
672
			if (locations == null)
695
			if (locations == null)
673
				locations = new IPath[max];
696
				locations = new IndexLocation[max];
674
			locations[count++] = indexLocation;
697
			locations[count++] = indexLocation;
675
			File indexFile = index.getIndexFile();
698
			if (this.indexStates.get(indexLocation) == REUSE_STATE) {
676
			if (indexFile.exists()) {
699
				indexLocation.close();
700
			} else {
677
				if (DEBUG)
701
				if (DEBUG)
678
					Util.verbose("removing index file " + indexFile); //$NON-NLS-1$
702
					Util.verbose("removing index file " + indexLocation); //$NON-NLS-1$
679
				indexFile.delete();
703
				indexLocation.delete();
680
			}
704
			}
681
		} else {
705
		} else {
682
			max--;
706
			max--;
Lines 686-694 Link Here
686
		for (int i = 0; i < count; i++)
710
		for (int i = 0; i < count; i++)
687
			this.indexes.removeKey(locations[i]);
711
			this.indexes.removeKey(locations[i]);
688
		removeIndexesState(locations);
712
		removeIndexesState(locations);
689
		if (this.participantsContainers != null && this.participantsContainers.get(path.toOSString()) != null) {
713
		if (this.participantsContainers != null) {
690
			this.participantsContainers.removeKey(path.toOSString());	
714
			boolean update = false;
691
			writeParticipantsIndexNamesFile();
715
			for (int i = 0; i < count; i++) {
716
				if (this.participantsContainers.get(locations[i]) != null) {
717
					update = true;
718
					this.participantsContainers.removeKey(locations[i]);
719
				}
720
			}
721
			if (update) writeParticipantsIndexNamesFile();
692
		}
722
		}
693
	}
723
	}
694
}
724
}
Lines 746-752 Link Here
746
	String containerPathString = containerPath.getDevice() == null ? containerPath.toString() : containerPath.toOSString();
776
	String containerPathString = containerPath.getDevice() == null ? containerPath.toString() : containerPath.toOSString();
747
	try {
777
	try {
748
		// Path is already canonical
778
		// Path is already canonical
749
		IPath indexLocation = computeIndexLocation(containerPath);
779
		IndexLocation indexLocation = computeIndexLocation(containerPath);
750
		Index index = getIndex(indexLocation);
780
		Index index = getIndex(indexLocation);
751
		if (VERBOSE) {
781
		if (VERBOSE) {
752
			Util.verbose("-> reseting index: "+indexLocation+" for path: "+containerPathString); //$NON-NLS-1$ //$NON-NLS-2$
782
			Util.verbose("-> reseting index: "+indexLocation+" for path: "+containerPathString); //$NON-NLS-1$ //$NON-NLS-2$
Lines 770-776 Link Here
770
	// must have permission to write from the write monitor
800
	// must have permission to write from the write monitor
771
	if (index.hasChanged()) {
801
	if (index.hasChanged()) {
772
		if (VERBOSE)
802
		if (VERBOSE)
773
			Util.verbose("-> saving index " + index.getIndexFile()); //$NON-NLS-1$
803
			Util.verbose("-> saving index " + index.getIndexLocation()); //$NON-NLS-1$
774
		index.save();
804
		index.save();
775
	}
805
	}
776
	synchronized (this) {
806
	synchronized (this) {
Lines 782-788 Link Here
782
					if (((IndexRequest) job).containerPath.equals(containerPath)) return;
812
					if (((IndexRequest) job).containerPath.equals(containerPath)) return;
783
			}
813
			}
784
		}
814
		}
785
		IPath indexLocation = computeIndexLocation(containerPath);
815
		IndexLocation indexLocation = computeIndexLocation(containerPath);
786
		updateIndexState(indexLocation, SAVED_STATE);
816
		updateIndexState(indexLocation, SAVED_STATE);
787
	}
817
	}
788
}
818
}
Lines 837-856 Link Here
837
	}
867
	}
838
	this.needToSave = !allSaved;
868
	this.needToSave = !allSaved;
839
}
869
}
840
public void scheduleDocumentIndexing(final SearchDocument searchDocument, IPath container, final IPath indexLocation, final SearchParticipant searchParticipant) {
870
public void scheduleDocumentIndexing(final SearchDocument searchDocument, IPath container, final IndexLocation indexLocation, final SearchParticipant searchParticipant) {
841
	request(new IndexRequest(container, this) {
871
	request(new IndexRequest(container, this) {
842
		public boolean execute(IProgressMonitor progressMonitor) {
872
		public boolean execute(IProgressMonitor progressMonitor) {
843
			if (this.isCancelled || progressMonitor != null && progressMonitor.isCanceled()) return true;
873
			if (this.isCancelled || progressMonitor != null && progressMonitor.isCanceled()) return true;
844
874
845
			/* ensure no concurrent write access to index */
875
			/* ensure no concurrent write access to index */
846
			Index index = getIndex(this.containerPath, indexLocation, true, /*reuse index file*/ true /*create if none*/);
876
			Index index;
877
			index = getIndex(this.containerPath, indexLocation, true, /*reuse index file*/ true /*create if none*/);
847
			if (index == null) return true;
878
			if (index == null) return true;
848
			ReadWriteMonitor monitor = index.monitor;
879
			ReadWriteMonitor monitor = index.monitor;
849
			if (monitor == null) return true; // index got deleted since acquired
880
			if (monitor == null) return true; // index got deleted since acquired
850
881
851
			try {
882
			try {
852
				monitor.enterWrite(); // ask permission to write
883
				monitor.enterWrite(); // ask permission to write
853
				indexDocument(searchDocument, searchParticipant, index, indexLocation);
884
				indexDocument(searchDocument, searchParticipant, index, new Path(indexLocation.getFilePath()));
854
			} finally {
885
			} finally {
855
				monitor.exitWrite(); // free write lock
886
				monitor.exitWrite(); // free write lock
856
			}
887
			}
Lines 904-910 Link Here
904
				// First line is DiskIndex signature  (see writeParticipantsIndexNamesFile())
935
				// First line is DiskIndex signature  (see writeParticipantsIndexNamesFile())
905
				if (DiskIndex.SIGNATURE.equals(new String(names[0]))) {					
936
				if (DiskIndex.SIGNATURE.equals(new String(names[0]))) {					
906
					for (int i = 1, l = names.length-1 ; i < l ; i+=2) {
937
					for (int i = 1, l = names.length-1 ; i < l ; i+=2) {
907
						containers.put(new Path(new String(names[i])), new Path(new String(names[i+1])));
938
						IndexLocation indexLocation = new FlatFileIndex(new File(new String(names[i])));
939
						indexLocation.setParticipantIndex();
940
						containers.put(indexLocation, new Path(new String(names[i+1])));
908
					}
941
					}
909
				}				
942
				}				
910
			}
943
			}
Lines 916-922 Link Here
916
	this.participantsContainers = containers;
949
	this.participantsContainers = containers;
917
	return;
950
	return;
918
}
951
}
919
private synchronized void removeIndexesState(IPath[] locations) {
952
private synchronized void removeIndexesState(IndexLocation[] locations) {
920
	getIndexStates(); // ensure the states are initialized
953
	getIndexStates(); // ensure the states are initialized
921
	int length = locations.length;
954
	int length = locations.length;
922
	boolean changed = false;
955
	boolean changed = false;
Lines 933-940 Link Here
933
966
934
	writeSavedIndexNamesFile();
967
	writeSavedIndexNamesFile();
935
}
968
}
936
private synchronized void updateIndexState(IPath indexLocation, Integer indexState) {
969
private synchronized void updateIndexState(IndexLocation indexLocation, Integer indexState) {
937
	if (indexLocation.isEmpty())
970
	if (indexLocation == null)
938
		throw new IllegalArgumentException();
971
		throw new IllegalArgumentException();
939
972
940
	getIndexStates(); // ensure the states are initialized
973
	getIndexStates(); // ensure the states are initialized
Lines 962-973 Link Here
962
	}
995
	}
963
996
964
}
997
}
965
public void updateParticipant(IPath indexLocation, IPath containerPath) {
998
public void updateParticipant(IPath indexPath, IPath containerPath) {
966
	if (this.participantsContainers == null) {
999
	if (this.participantsContainers == null) {
967
		readParticipantsIndexNamesFile();
1000
		readParticipantsIndexNamesFile();
968
	} 
1001
	}
1002
	IndexLocation indexLocation = new FlatFileIndex(indexPath.toFile());
969
	if (this.participantsContainers.get(indexLocation) == null) {
1003
	if (this.participantsContainers.get(indexLocation) == null) {
970
		this.participantsContainers.put(indexLocation, containerPath);
1004
		this.participantsContainers.put(indexLocation, containerPath);
1005
		indexLocation.setParticipantIndex();
971
		this.participantUpdated  = true;
1006
		this.participantUpdated  = true;
972
	}
1007
	}
973
}
1008
}
Lines 1014-1022 Link Here
1014
		Object[] indexFiles = this.participantsContainers.keyTable;
1049
		Object[] indexFiles = this.participantsContainers.keyTable;
1015
		Object[] containers = this.participantsContainers.valueTable;
1050
		Object[] containers = this.participantsContainers.valueTable;
1016
		for (int i = 0, l = indexFiles.length; i < l; i++) {
1051
		for (int i = 0, l = indexFiles.length; i < l; i++) {
1017
			IPath indexFile = (IPath)indexFiles[i];
1052
			IndexLocation indexFile = (IndexLocation)indexFiles[i];
1018
			if (indexFile != null) {
1053
			if (indexFile != null) {
1019
				writer.write(indexFile.toOSString());
1054
				writer.write(indexFile.getIndexFile().getPath());
1020
				writer.write('\n');
1055
				writer.write('\n');
1021
				writer.write(((IPath)containers[i]).toOSString());
1056
				writer.write(((IPath)containers[i]).toOSString());
1022
				writer.write('\n');
1057
				writer.write('\n');
Lines 1046-1054 Link Here
1046
		Object[] keys = this.indexStates.keyTable;
1081
		Object[] keys = this.indexStates.keyTable;
1047
		Object[] states = this.indexStates.valueTable;
1082
		Object[] states = this.indexStates.valueTable;
1048
		for (int i = 0, l = states.length; i < l; i++) {
1083
		for (int i = 0, l = states.length; i < l; i++) {
1049
			IPath key = (IPath) keys[i];
1084
			IndexLocation key = (IndexLocation) keys[i];
1050
			if (key != null && !key.isEmpty() && states[i] == SAVED_STATE) {
1085
			if (key != null && states[i] == SAVED_STATE) {
1051
				writer.write(key.lastSegment());
1086
				writer.write(key.fileName());
1052
				writer.write('\n');
1087
				writer.write('\n');
1053
			}
1088
			}
1054
		}
1089
		}

Return to bug 356620