diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/Util.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/Util.java
index 8b41712..8c25994 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/Util.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/Util.java
@@ -1348,6 +1348,27 @@
}
}
}
+public static void zipFiles(File[] files, String zipPath) throws IOException {
+ File zipFile = new File(zipPath);
+ if (zipFile.exists()) {
+ if (!delete(zipFile))
+ throw new IOException("Could not delete " + zipPath);
+ // ensure the new zip file has a different timestamp than the previous one
+ int timeToWait = 1000; // some platform (like Linux) have a 1s granularity)
+ waitAtLeast(timeToWait);
+ } else {
+ zipFile.getParentFile().mkdirs();
+ }
+ ZipOutputStream zip = new ZipOutputStream(new FileOutputStream(zipFile));
+ for (int i = 0, length = files.length; i < length; i++) {
+ File file = files[i];
+ ZipEntry entry = new ZipEntry(file.getName());
+ zip.putNextEntry(entry);
+ zip.write(org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(file));
+ zip.closeEntry();
+ }
+ zip.close();
+}
/**
* Returns the compilation errors / warnings for the given CompilationResult.
*
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaIndexTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaIndexTests.java
new file mode 100644
index 0000000..ca1d7af
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaIndexTests.java
@@ -0,0 +1,775 @@
+/*******************************************************************************
+ * Copyright (c) 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.tests.model;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+
+import junit.framework.Test;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jdt.core.IClasspathAttribute;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.index.*;
+import org.eclipse.jdt.core.search.SearchEngine;
+import org.eclipse.jdt.core.tests.util.Util;
+import org.eclipse.jdt.internal.core.JavaModelManager;
+
+public class JavaIndexTests extends AbstractJavaSearchTests {
+
+ static {
+ // TESTS_NAMES = new String[] {"testMultipleProjects"};
+ }
+ public JavaIndexTests(String name) {
+ super(name);
+ }
+
+ public static Test suite() {
+ return buildModelTestSuite(JavaIndexTests.class);
+ }
+ // Test that the index file is really generated.
+ public void testGenerateIndex() throws IOException {
+ String indexFilePath = getExternalResourcePath("Test.index");
+ String jarFilePath = getExternalResourcePath("Test.jar");
+ try {
+ createJar(new String[] {
+ "pkg/Test.java",
+ "package pkg;\n" +
+ "public class Test {\n" +
+ " protected Test(int i) {}\n" +
+ "}"}, jarFilePath);
+
+ JavaIndexer.generateIndexForJar(jarFilePath, indexFilePath);
+ assertTrue(new File(indexFilePath).exists());
+ } finally {
+ new File(indexFilePath).delete();
+ new File(jarFilePath).delete();
+ }
+ }
+
+ // Test that the index file and the jar in held after the index is created
+ public void testDeleteIndexedFile() {
+ String indexFilePath = getExternalResourcePath("Test.index");
+ String jarFilePath = getExternalResourcePath("Test.jar");
+ try {
+ createJar(new String[] {
+ "pkg/Test.java",
+ "package pkg;\n" +
+ "public class Test {\n" +
+ " protected Test(int i) {}\n" +
+ "}"}, jarFilePath);
+ JavaIndexer.generateIndexForJar(jarFilePath, indexFilePath);
+ assertTrue("Could not delete the index file", new File(indexFilePath).delete());
+ assertTrue("Could not delete the jar file", new File(jarFilePath).delete());
+ } catch (IOException e) {
+ assertFalse("Test failed", true);
+ }
+ }
+
+ // Test that search works fine with the index file
+ public void testUseIndex() throws CoreException, IOException {
+ String indexFilePath = getExternalResourcePath("Test.index");
+ String jarFilePath = getExternalResourcePath("Test.jar");
+ try {
+ createJar(new String[] {
+ "pkg/Test.java",
+ "package pkg;\n" +
+ "public class Test {\n" +
+ " protected Test(int i) {}\n" +
+ "}"}, jarFilePath);
+ JavaIndexer.generateIndexForJar(jarFilePath, indexFilePath);
+ long modified = new File(indexFilePath).lastModified();
+
+ IJavaProject p = createJavaProject("P");
+ Path libPath = new Path(jarFilePath);
+ IClasspathAttribute attribute = JavaCore.newClasspathAttribute(IClasspathAttribute.INDEX_LOCATION_ATTRIBUTE_NAME, "file:///"+indexFilePath);
+ IClasspathEntry entry = JavaCore.newLibraryEntry(libPath, null, null, null, new IClasspathAttribute[]{attribute}, false);
+ setClasspath(p, new IClasspathEntry[] {entry});
+
+ waitUntilIndexesReady();
+
+ // Test that specified index file is really used
+ java.io.File indexFile = JavaModelManager.getIndexManager().getIndex(libPath, false, false).getIndexFile();
+ assertEquals("Specified index file is not being used", indexFilePath,indexFile.toString());
+
+ // Test that search works properly
+ search("Test", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
+ assertSearchResults(getExternalPath() + "Test.jar pkg.Test");
+
+ // Ensure that the index file is not modified
+ assertEquals(modified, new File(indexFilePath).lastModified());
+ } finally {
+ deleteProject("P");
+ new File(indexFilePath).delete();
+ new File(jarFilePath).delete();
+ }
+ }
+
+ // Test that the same index file is used even after restarting
+ public void testUseIndexAfterRestart() throws IOException, CoreException {
+ String indexFilePath = getExternalResourcePath("Test.index");
+ String jarFilePath = getExternalResourcePath("Test.jar");
+ try {
+ createJar(new String[] {
+ "pkg/Test.java",
+ "package pkg;\n" +
+ "public class Test {\n" +
+ " protected Test(int i) {}\n" +
+ "}"}, jarFilePath);
+ JavaIndexer.generateIndexForJar(jarFilePath, indexFilePath);
+ long modified = new File(indexFilePath).lastModified();
+ IJavaProject p = createJavaProject("P");
+ Path libPath = new Path(jarFilePath);
+ IClasspathAttribute attribute = JavaCore.newClasspathAttribute(IClasspathAttribute.INDEX_LOCATION_ATTRIBUTE_NAME, "file:///"+indexFilePath);
+ IClasspathEntry entry = JavaCore.newLibraryEntry(libPath, null, null, null, new IClasspathAttribute[]{attribute}, false);
+ setClasspath(p, new IClasspathEntry[] {entry});
+ waitUntilIndexesReady();
+
+ search("Test", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
+ assertSearchResults(getExternalPath() + "Test.jar pkg.Test");
+
+ simulateExitRestart();
+ getJavaModel().refreshExternalArchives(null, null);
+ waitUntilIndexesReady();
+
+ this.resultCollector = new JavaSearchResultCollector();
+ search("Test", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
+ assertSearchResults(getExternalPath() + "Test.jar pkg.Test");
+
+ java.io.File indexFile = JavaModelManager.getIndexManager().getIndex(libPath, false, false).getIndexFile();
+ assertEquals(indexFilePath,indexFile.toString());
+ // Ensure that the file is not modified
+ assertEquals(modified, new File(indexFilePath).lastModified());
+ } finally {
+ deleteProject("P");
+ new File(indexFilePath).delete();
+ new File(jarFilePath).delete();
+ }
+ }
+
+ // Test that the same index file is used even after restarting
+ public void testUseIndexInternalJarAfterRestart() throws IOException, CoreException {
+ String indexFilePath = getExternalResourcePath("Test.index");
+ String jarFilePath = "/P/Test.jar";
+ try {
+ IJavaProject p = createJavaProject("P");
+ createJar(new String[] {
+ "pkg/Test.java",
+ "package pkg;\n" +
+ "public class Test {\n" +
+ " protected Test(int i) {}\n" +
+ "}"}, jarFilePath);
+ JavaIndexer.generateIndexForJar(jarFilePath, indexFilePath);
+ long modified = new File(indexFilePath).lastModified();
+ IPath libPath = new Path(jarFilePath);
+ IClasspathAttribute attribute = JavaCore.newClasspathAttribute(IClasspathAttribute.INDEX_LOCATION_ATTRIBUTE_NAME, "file:///"+indexFilePath);
+ IClasspathEntry entry = JavaCore.newLibraryEntry(libPath, null, null, null, new IClasspathAttribute[]{attribute}, false);
+ setClasspath(p, new IClasspathEntry[] {entry});
+ waitUntilIndexesReady();
+
+ search("Test", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
+ assertSearchResults("\\P\\Test.jar pkg.Test");
+
+ simulateExitRestart();
+ getJavaModel().refreshExternalArchives(null, null);
+ waitUntilIndexesReady();
+
+ this.resultCollector = new JavaSearchResultCollector();
+ search("Test", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
+ assertSearchResults("\\P\\Test.jar pkg.Test");
+
+ java.io.File indexFile = JavaModelManager.getIndexManager().getIndex(libPath, false, false).getIndexFile();
+ assertEquals(indexFilePath,indexFile.toString());
+ // Ensure that the file is not modified
+ assertEquals(modified, new File(indexFilePath).lastModified());
+ } finally {
+ deleteProject("P");
+ new File(indexFilePath).delete();
+ }
+ }
+
+ // Test that a jar file that gets modified after the index is created doesn't return new changes.
+ // This behavior might have to be modified but..
+ public void testModifyJarAfterIndex() throws CoreException, IOException {
+ String indexFilePath = getExternalResourcePath("Test.index");
+ String jarFilePath = getExternalResourcePath("Test.jar");
+ try {
+ createJar(new String[] {
+ "pkg/Test.java",
+ "package pkg;\n" +
+ "public class Test {\n" +
+ " protected Test(int i) {}\n" +
+ "}"}, jarFilePath);
+ JavaIndexer.generateIndexForJar(jarFilePath, indexFilePath);
+ createJar(new String[] {
+ "pkg/Test.java",
+ "package pkg;\n" +
+ "public class Test {\n" +
+ " protected Test(int i) {}\n" +
+ "}",
+ "pkg/NewTest.java",
+ "package pkg;\n" +
+ "public class NewTest {\n" +
+ " protected NewTest(int i) {}\n" +
+ "}"}, jarFilePath);
+ IJavaProject p = createJavaProject("P");
+ Path libPath = new Path(jarFilePath);
+ IClasspathAttribute attribute = JavaCore.newClasspathAttribute(IClasspathAttribute.INDEX_LOCATION_ATTRIBUTE_NAME, "file:///"+indexFilePath);
+ IClasspathEntry entry = JavaCore.newLibraryEntry(libPath, null, null, null, new IClasspathAttribute[]{attribute}, false);
+ setClasspath(p, new IClasspathEntry[] {entry});
+ waitUntilIndexesReady();
+ search("NewTest", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
+ assertSearchResults("");
+ } finally {
+ deleteProject("P");
+ new File(indexFilePath).delete();
+ new File(jarFilePath).delete();
+ }
+ }
+
+ // test a non-existent index
+ public void testNonExistentIndex() throws CoreException, IOException {
+ String indexFilePath = getExternalResourcePath("Test.index");
+ String jarFilePath = getExternalResourcePath("Test.jar");
+ try {
+ createJar(new String[] {
+ "pkg/Test.java",
+ "package pkg;\n" +
+ "public class Test {\n" +
+ " protected Test(int i) {}\n" +
+ "}"}, jarFilePath);
+ IJavaProject p = createJavaProject("P");
+ Path libPath = new Path(jarFilePath);
+ new File(indexFilePath).delete();
+ IClasspathAttribute attribute = JavaCore.newClasspathAttribute(IClasspathAttribute.INDEX_LOCATION_ATTRIBUTE_NAME, "file:///"+indexFilePath);
+ IClasspathEntry entry = JavaCore.newLibraryEntry(libPath, null, null, null, new IClasspathAttribute[]{attribute}, false);
+ setClasspath(p, new IClasspathEntry[] {entry});
+ waitUntilIndexesReady();
+ search("Test", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
+ assertSearchResults(getExternalPath() + "Test.jar pkg.Test");
+
+ } finally {
+ deleteProject("P");
+ new File(indexFilePath).delete();
+ new File(jarFilePath).delete();
+ }
+ }
+
+ // test a non-existent index
+ public void testNonExistentIndexRestart() throws CoreException, IOException {
+ String indexFilePath = getExternalResourcePath("Test.index");
+ String jarFilePath = getExternalResourcePath("Test.jar");
+ try {
+ createJar(new String[] {
+ "pkg/Test.java",
+ "package pkg;\n" +
+ "public class Test {\n" +
+ " protected Test(int i) {}\n" +
+ "}"}, jarFilePath);
+
+ new File(indexFilePath).delete();
+
+ IJavaProject p = createJavaProject("P");
+ Path libPath = new Path(jarFilePath);
+ IClasspathAttribute attribute = JavaCore.newClasspathAttribute(IClasspathAttribute.INDEX_LOCATION_ATTRIBUTE_NAME, "file:///"+indexFilePath);
+ IClasspathEntry entry = JavaCore.newLibraryEntry(libPath, null, null, null, new IClasspathAttribute[]{attribute}, false);
+ setClasspath(p, new IClasspathEntry[] {entry});
+ waitUntilIndexesReady();
+
+ search("Test", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
+ assertSearchResults(getExternalPath() + "Test.jar pkg.Test");
+
+ java.io.File indexFile = JavaModelManager.getIndexManager().getIndex(libPath, false, false).getIndexFile();
+ long modified = indexFile.lastModified();
+ assertEquals(modified, indexFile.lastModified());
+
+ simulateExitRestart();
+ getJavaModel().refreshExternalArchives(null,null);
+ waitUntilIndexesReady();
+
+ this.resultCollector = new JavaSearchResultCollector();
+ search("Test", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
+ assertSearchResults(getExternalPath() + "Test.jar pkg.Test");
+
+ indexFile = JavaModelManager.getIndexManager().getIndex(libPath, false, false).getIndexFile();
+ assertEquals("Index File should not have got modified",modified, indexFile.lastModified());
+ } finally {
+ deleteProject("P");
+ new File(indexFilePath).delete();
+ new File(jarFilePath).delete();
+ }
+ }
+
+ // test that if the index is not existent after restart, it should build up a new index
+ public void testNonExistentIndexAfterRestart() throws CoreException, IOException {
+ String indexFilePath = getExternalResourcePath("Test.index");
+ String jarFilePath = getExternalResourcePath("Test.jar");
+ try {
+ createJar(new String[] {
+ "pkg/Test.java",
+ "package pkg;\n" +
+ "public class Test {\n" +
+ "protected Test(int i) {}\n" + "}"
+ },jarFilePath);
+ JavaIndexer.generateIndexForJar(jarFilePath, indexFilePath);
+
+ IJavaProject p = createJavaProject("P");
+ Path libPath = new Path(jarFilePath);
+ IClasspathAttribute attribute = JavaCore.newClasspathAttribute(IClasspathAttribute.INDEX_LOCATION_ATTRIBUTE_NAME, "file:///"+indexFilePath);
+ IClasspathEntry entry = JavaCore.newLibraryEntry(libPath, null, null, null, new IClasspathAttribute[]{attribute}, false);
+ setClasspath(p, new IClasspathEntry[] {entry});
+ waitUntilIndexesReady();
+
+ search("Test", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
+ assertSearchResults(getExternalPath() + "Test.jar pkg.Test");
+
+ simulateExitRestart();
+ File indexFile = new File(indexFilePath);
+ indexFile.delete();
+ assertTrue(!indexFile.exists());
+ getJavaModel().refreshExternalArchives(null,null);
+ waitUntilIndexesReady();
+
+ this.resultCollector = new JavaSearchResultCollector();
+ search("Test", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
+ assertSearchResults(getExternalPath() + "Test.jar pkg.Test");
+
+ } finally {
+ deleteProject("P");
+ new File(indexFilePath).delete();
+ new File(jarFilePath).delete();
+ }
+ }
+
+ // test a non-existent index which becomes existent after restart
+ public void testExistentIndexAfterRestart() throws CoreException, IOException {
+ String indexFilePath = getExternalResourcePath("Test.index");
+ String jarFilePath = getExternalResourcePath("Test.jar");
+ try {
+ createJar(new String[] {
+ "pkg/Test.java",
+ "package pkg;\n" +
+ "public class Test {\n" +
+ " protected Test(int i) {}\n" +
+ "}"}, jarFilePath);
+
+ File indexFile = new File(indexFilePath);
+ indexFile.delete();
+ assertTrue(!indexFile.exists());
+
+ IJavaProject p = createJavaProject("P");
+ Path libPath = new Path(jarFilePath);
+ IClasspathAttribute attribute = JavaCore.newClasspathAttribute(IClasspathAttribute.INDEX_LOCATION_ATTRIBUTE_NAME, "file:///"+indexFilePath);
+ IClasspathEntry entry = JavaCore.newLibraryEntry(libPath, null, null, null, new IClasspathAttribute[]{attribute}, false);
+ setClasspath(p, new IClasspathEntry[] {entry});
+ waitUntilIndexesReady();
+
+ search("Test", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
+ assertSearchResults(getExternalPath() + "Test.jar pkg.Test");
+
+ JavaIndexer.generateIndexForJar(jarFilePath, indexFilePath);
+ simulateExitRestart();
+ getJavaModel().refreshExternalArchives(null,null);
+ waitUntilIndexesReady();
+
+ this.resultCollector = new JavaSearchResultCollector();
+ search("Test", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
+ assertSearchResults(getExternalPath() + "Test.jar pkg.Test");
+
+ indexFile = JavaModelManager.getIndexManager().getIndex(libPath, false, false).getIndexFile();
+ assertEquals(indexFilePath,indexFile.toString());
+ } finally {
+ deleteProject("P");
+ new File(indexFilePath).delete();
+ new File(jarFilePath).delete();
+ }
+ }
+
+ // Test that the index file is not deletes when the project is deleted
+ public void testDeleteProject() throws CoreException, IOException {
+ String indexFilePath = getExternalResourcePath("Test.index");
+ String jarFilePath = getExternalResourcePath("Test.jar");
+ try {
+ createJar(new String[] {
+ "pkg/Test.java",
+ "package pkg;\n" +
+ "public class Test {\n" +
+ " protected Test(int i) {}\n" +
+ "}"}, jarFilePath);
+ JavaIndexer.generateIndexForJar(jarFilePath, indexFilePath);
+ IJavaProject p = createJavaProject("P");
+ createExternalFolder("externalLib");
+ Path libPath = new Path(jarFilePath);
+ IClasspathAttribute attribute = JavaCore.newClasspathAttribute(IClasspathAttribute.INDEX_LOCATION_ATTRIBUTE_NAME, "file:///"+indexFilePath);
+ IClasspathEntry entry = JavaCore.newLibraryEntry(libPath, null, null, null, new IClasspathAttribute[]{attribute}, false);
+ setClasspath(p, new IClasspathEntry[] {entry});
+ waitUntilIndexesReady();
+ deleteProject("P");
+ File f = new File(indexFilePath);
+ assertTrue(f.exists());
+ } finally {
+ new File(indexFilePath).delete();
+ new File(jarFilePath).delete();
+ }
+ }
+
+ // Test that it works if the index file is in the jar file
+ public void testIndexInJar() throws IOException, CoreException {
+ String indexFilePath = getExternalResourcePath("Test.index");
+ String jarFilePath = getExternalResourcePath("Test.jar");
+ String indexZipPath = getExternalResourcePath("TestIndex.zip");
+ try {
+ createJar(new String[] {
+ "pkg/Test.java",
+ "package pkg;\n" +
+ "public class Test {\n" +
+ " protected Test(int i) {}\n" +
+ "}"}, jarFilePath);
+
+ JavaIndexer.generateIndexForJar(jarFilePath, indexFilePath);
+ Util.zipFiles(new File[]{new File(indexFilePath)}, indexZipPath);
+
+ IJavaProject p = createJavaProject("P");
+ Path libPath = new Path(jarFilePath);
+ String url = "jar:file:/"+indexZipPath+"!/Test.index";
+ IClasspathAttribute attribute = JavaCore.newClasspathAttribute(IClasspathAttribute.INDEX_LOCATION_ATTRIBUTE_NAME, url);
+ IClasspathEntry entry = JavaCore.newLibraryEntry(libPath, null, null, null, new IClasspathAttribute[]{attribute}, false);
+ setClasspath(p, new IClasspathEntry[] {entry});
+ waitUntilIndexesReady();
+
+ assertEquals(url,JavaModelManager.getIndexManager().getIndex(libPath, false, false).getIndexLocation().getUrl().toString());
+
+ search("Test", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
+ assertSearchResults(getExternalPath() + "Test.jar pkg.Test");
+
+ simulateExitRestart();
+ getJavaModel().refreshExternalArchives(null,null);
+ waitUntilIndexesReady();
+
+ this.resultCollector = new JavaSearchResultCollector();
+ assertEquals(url,JavaModelManager.getIndexManager().getIndex(libPath, false, false).getIndexLocation().getUrl().toString());
+ search("Test", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
+ assertSearchResults(getExternalPath() + "Test.jar pkg.Test");
+ } finally {
+ deleteProject("P");
+ new File(indexZipPath).delete();
+ new File(jarFilePath).delete();
+ }
+ }
+
+ // Test index file in platform
+ public void testPlatformIndexFile() throws CoreException, IOException {
+ String indexFilePath = null;
+ String jarFilePath = getExternalResourcePath("Test.jar");
+ String indexUrl = "platform:/resource/P/Test.index";
+ try {
+ createJar(new String[] {
+ "pkg/Test.java",
+ "package pkg;\n" +
+ "public class Test {\n" +
+ " protected Test(int i) {}\n" +
+ "}"}, jarFilePath);
+
+ IJavaProject p = createJavaProject("P");
+ indexFilePath = p.getProject().getLocation().append("Test.index").toFile().getAbsolutePath();
+ JavaIndexer.generateIndexForJar(jarFilePath, indexFilePath);
+ long modified = new File(indexFilePath).lastModified();
+
+ Path libPath = new Path(jarFilePath);
+ IClasspathAttribute attribute = JavaCore.newClasspathAttribute(IClasspathAttribute.INDEX_LOCATION_ATTRIBUTE_NAME, indexUrl);
+ IClasspathEntry entry = JavaCore.newLibraryEntry(libPath, null, null, null, new IClasspathAttribute[]{attribute}, false);
+ setClasspath(p, new IClasspathEntry[] {entry});
+ waitUntilIndexesReady();
+
+ search("Test", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
+ assertSearchResults(getExternalPath() + "Test.jar pkg.Test");
+
+ URL url = JavaModelManager.getIndexManager().getIndex(libPath, false, false).getIndexLocation().getUrl();
+ assertEquals(indexUrl, url.toString());
+
+ simulateExitRestart();
+ getJavaModel().refreshExternalArchives(null,null);
+ waitUntilIndexesReady();
+
+ this.resultCollector = new JavaSearchResultCollector();
+ search("Test", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
+ assertSearchResults(getExternalPath() + "Test.jar pkg.Test");
+
+ url = JavaModelManager.getIndexManager().getIndex(libPath, false, false).getIndexLocation().getUrl();
+ assertEquals(indexUrl, url.toString());
+
+ assertEquals(modified, new File(indexFilePath).lastModified());
+ } finally {
+ deleteProject("P");
+ if (indexFilePath != null) new File(indexFilePath).delete();
+ new File(jarFilePath).delete();
+ }
+ }
+
+ // Test index file in platform
+ public void testPlatformJarIndexFile() throws CoreException, IOException {
+ String indexFilePath = null;
+ String jarFilePath = getExternalResourcePath("Test.jar");
+ String indexUrl = "platform:/resource/ForIndex/Test.index.zip!/Test.index";
+ try {
+ createJar(new String[] {
+ "pkg/Test.java",
+ "package pkg;\n" +
+ "public class Test {\n" +
+ " protected Test(int i) {}\n" +
+ "}"}, jarFilePath);
+
+ IProject indexProj = createProject("ForIndex");
+ indexFilePath = indexProj.getProject().getLocation().append("Test.index").toFile().getAbsolutePath();
+ JavaIndexer.generateIndexForJar(jarFilePath, indexFilePath);
+ Util.zipFiles(new File[]{new File(indexFilePath)}, indexFilePath+".zip");
+
+ IJavaProject p = createJavaProject("P");
+ Path libPath = new Path(jarFilePath);
+ IClasspathAttribute attribute = JavaCore.newClasspathAttribute(IClasspathAttribute.INDEX_LOCATION_ATTRIBUTE_NAME, indexUrl);
+ IClasspathEntry entry = JavaCore.newLibraryEntry(libPath, null, null, null, new IClasspathAttribute[]{attribute}, false);
+ setClasspath(p, new IClasspathEntry[] {entry});
+ waitUntilIndexesReady();
+
+ search("Test", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
+ assertSearchResults(getExternalPath() + "Test.jar pkg.Test");
+
+ URL url = JavaModelManager.getIndexManager().getIndex(libPath, false, false).getIndexLocation().getUrl();
+ assertEquals(indexUrl, url.toString());
+
+ simulateExitRestart();
+ getJavaModel().refreshExternalArchives(null,null);
+ waitUntilIndexesReady();
+
+ this.resultCollector = new JavaSearchResultCollector();
+ search("Test", TYPE, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
+ assertSearchResults(getExternalPath() + "Test.jar pkg.Test");
+
+ url = JavaModelManager.getIndexManager().getIndex(libPath, false, false).getIndexLocation().getUrl();
+ assertEquals(indexUrl, url.toString());
+ } finally {
+ deleteProject("P");
+ if (indexFilePath != null) {
+ new File(indexFilePath).delete();
+ new File(indexFilePath+".zip").delete();
+ }
+ new File(jarFilePath).delete();
+ deleteProject("ForIndex");
+ }
+ }
+
+ public void testEditClasspath() throws CoreException, IOException {
+ String indexFilePath = getExternalResourcePath("Test.index");
+ String jarFilePath = getExternalResourcePath("Test.jar");
+ try {
+ createJar(new String[] {
+ "pkg/Test.java",
+ "package pkg;\n" +
+ "public class Test {\n" +
+ " protected Test(int i) {}\n" +
+ "}"}, jarFilePath);
+ JavaIndexer.generateIndexForJar(jarFilePath, indexFilePath);
+ File f = new File(indexFilePath);
+ long modified = f.lastModified();
+ IJavaProject p = this.createJavaProject("P", new String[] {}, "bin");
+
+ String content = new String(
+ "\n"
+ + "
+ * An Ant task to generate the index file for the given jar path. + *
+ *
+ * <eclipse.buildJarIndex jarPath="Test.jar" indexPath="Test.index"/>
+ *
+ * For more information on Ant check out the website at http://jakarta.apache.org/ant/ . + *
+ * + * This is not intended to be subclassed by users. + * + * @since 3.8 + */ +public class BuildJarIndex extends Task { + + private String jarPath; + private String indexPath; + + public void execute() throws BuildException { + if (this.jarPath == null) { + throw new BuildException(AntAdapterMessages.getString("buildJarIndex.jarFile.cannot.be.null")); //$NON-NLS-1$ + } + if (this.indexPath == null) { + throw new BuildException(AntAdapterMessages.getString("buildJarIndex.indexFile.cannot.be.null")); //$NON-NLS-1$ + } + + try { + JavaIndexer.generateIndexForJar(this.jarPath, this.indexPath); + } catch (IOException e) { + throw new BuildException(AntAdapterMessages.getString("buildJarIndex.ioexception.occured", e.getLocalizedMessage())); //$NON-NLS-1$ + } + setProject(getProject()); + } + + public void setJarPath(String path) { + this.jarPath = path; + } + + public void setIndexPath(String path) { + this.indexPath = path; + } +} diff --git a/org.eclipse.jdt.core/antadapter/org/eclipse/jdt/internal/antadapter/messages.properties b/org.eclipse.jdt.core/antadapter/org/eclipse/jdt/internal/antadapter/messages.properties index df61656..9cb9be2 100644 --- a/org.eclipse.jdt.core/antadapter/org/eclipse/jdt/internal/antadapter/messages.properties +++ b/org.eclipse.jdt.core/antadapter/org/eclipse/jdt/internal/antadapter/messages.properties @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2000, 2006 IBM Corporation and others. +# Copyright (c) 2000, 2011 IBM Corporation and others. # All rights reserved. This program and the accompanying materials # are made available under the terms of the Eclipse Public License v1.0 # which accompanies this distribution, and is available at @@ -19,3 +19,7 @@ checkDebugAttributes.property.argument.cannot.be.null=The property argument cannot be null checkDebugAttributes.ioexception.occured=IOException occurred while reading checkDebugAttributes.file.argument.must.be.a.classfile.or.a.jarfile=The file argument must be a .class or a .jar file + +buildJarIndex.jarFile.cannot.be.null=The jar file argument cannot be null +buildJarIndex.indexFile.cannot.be.null=The index file argument cannot be null +buildJarIndex.ioexception.occured=IOException - {0} diff --git a/org.eclipse.jdt.core/build.properties b/org.eclipse.jdt.core/build.properties index ff520f9..8e3f678 100644 --- a/org.eclipse.jdt.core/build.properties +++ b/org.eclipse.jdt.core/build.properties @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2000, 2010 IBM Corporation and others. +# Copyright (c) 2000, 2011 IBM Corporation and others. # All rights reserved. This program and the accompanying materials # are made available under the terms of the Eclipse Public License v1.0 # which accompanies this distribution, and is available at @@ -24,7 +24,8 @@ org.eclipse.jdt.core.jdom.*,\ org.eclipse.jdt.core.dom.*,\ org.eclipse.jdt.core.dom.rewrite.*,\ - org.eclipse.jdt.core.search.* + org.eclipse.jdt.core.search.*,\ + org.eclipse.jdt.core.index.* source.. = batch/,\ codeassist/,\ compiler/,\ diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathAttribute.java index d90ab15..51effaf 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathAttribute.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathAttribute.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2010 IBM Corporation and others. + * Copyright (c) 2005, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -58,6 +58,16 @@ * @since 3.1 */ String JAVADOC_LOCATION_ATTRIBUTE_NAME = "javadoc_location"; //$NON-NLS-1$ + + /** + * Constant for the name of the index location attribute. + * + *The value for this attribute has to be the string representation of a URL. + * It should point to an existing index file in a folder or a jar. The URL also supports the platform protocol.
+ * + * @since 3.8 + */ + String INDEX_LOCATION_ATTRIBUTE_NAME = "index_location"; //$NON-NLS-1$ /** * Constant for the name of the optional attribute. The possible values diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaElementDelta.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaElementDelta.java index bc17b09..b52c5ef 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaElementDelta.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaElementDelta.java @@ -57,6 +57,12 @@ *null
if this package fragment root's binary archive
+ * has no corresponding index file, or if this package fragment root
+ * is not a binary archive
+ * @exception JavaModelException if this operation fails
+ *
+ * @since 3.8
+ */
+ URL getIndexPath() throws JavaModelException;
+ /**
* Returns this package fragment root's kind encoded as an integer.
* A package fragment root can contain source files (i.e. files with one
* of the {@link JavaCore#getJavaLikeExtensions() Java-like extensions},
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathChange.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathChange.java
index b96cd44..5d5e3bd 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathChange.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathChange.java
@@ -10,6 +10,7 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core;
+import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@@ -335,6 +336,7 @@
boolean found = false;
for (int j = 0; j < accumulatedRoots.size(); j++) {
IPackageFragmentRoot root = (IPackageFragmentRoot) accumulatedRoots.elementAt(j);
+ // TODO SATYAM: Shouldn't the check be opposite?
if (!root.getPath().equals(oldRoot.getPath())) {
found = true;
break;
@@ -511,7 +513,7 @@
for (int i = 0; i < newLength; i++) {
int index = classpathContains(this.oldResolvedClasspath, newResolvedClasspath[i]);
- if (index == -1) {
+ if (index == -1 || newResolvedClasspath[i].getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
// remote projects are not indexed in this project
if (newResolvedClasspath[i].getEntryKind() == IClasspathEntry.CPE_PROJECT){
continue;
@@ -524,14 +526,23 @@
boolean pathHasChanged = true;
IPath newPath = newResolvedClasspath[i].getPath();
for (int j = 0; j < oldLength; j++) {
+ //TODO SATYAM: Isn't index == j?
IClasspathEntry oldEntry = this.oldResolvedClasspath[j];
if (oldEntry.getPath().equals(newPath)) {
- pathHasChanged = false;
+ URL oldurl = ((ClasspathEntry)oldEntry).getLibraryIndexLocation();
+ URL newurl = ((ClasspathEntry)newResolvedClasspath[i]).getLibraryIndexLocation();
+ if (oldurl == null && newurl == null) {
+ pathHasChanged = false;
+ } else if (oldurl != null && newurl != null) {
+ pathHasChanged = !(newurl.equals(oldurl));
+ } else if (oldurl != null) {
+ indexManager.removeIndex(newPath);
+ }
break;
}
}
if (pathHasChanged) {
- indexManager.indexLibrary(newPath, this.project.getProject());
+ indexManager.indexLibrary(newPath, this.project.getProject(),((ClasspathEntry)newResolvedClasspath[i]).getLibraryIndexLocation());
}
break;
case IClasspathEntry.CPE_SOURCE:
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java
index 5656323..5faf197 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java
@@ -17,6 +17,8 @@
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@@ -1524,6 +1526,33 @@
return JavaCore.getResolvedClasspathEntry(this);
}
+
+ /**
+ * This function computes the URL of the index location for this classpath entry. It returns null if the URL is
+ * invalid.
+ */
+ public URL getLibraryIndexLocation() {
+ switch(getEntryKind()) {
+ case IClasspathEntry.CPE_LIBRARY :
+ case IClasspathEntry.CPE_VARIABLE :
+ break;
+ default :
+ return null;
+ }
+
+ for (int i= 0; i < this.extraAttributes.length; i++) {
+ IClasspathAttribute attrib= this.extraAttributes[i];
+ if (IClasspathAttribute.INDEX_LOCATION_ATTRIBUTE_NAME.equals(attrib.getName())) {
+ String value = attrib.getValue();
+ try {
+ return new URL(value);
+ } catch (MalformedURLException e) {
+ return null;
+ }
+ }
+ }
+ return null;
+ }
/**
* Validate a given classpath and output location for a project, using the following rules:
@@ -2191,5 +2220,5 @@
}
}
return JavaModelStatus.VERIFIED_OK;
- }
+ }
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java
index 126fcc9..4ef6e0b 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java
@@ -13,6 +13,7 @@
package org.eclipse.jdt.internal.core;
import java.io.File;
+import java.net.URL;
import java.util.*;
import org.eclipse.core.resources.IContainer;
@@ -997,8 +998,12 @@
// first remove the index so that it is forced to be re-indexed
this.manager.indexManager.removeIndex(entryPath);
// then index the jar
- this.manager.indexManager.indexLibrary(entryPath, project.getProject());
+ this.manager.indexManager.indexLibrary(entryPath, project.getProject(), ((ClasspathEntry)entries[j]).getLibraryIndexLocation());
} else {
+ URL indexLocation = ((ClasspathEntry)entries[j]).getLibraryIndexLocation();
+ if (indexLocation != null) { // force reindexing, this could be faster rather than maintaining the list
+ this.manager.indexManager.indexLibrary(entryPath, project.getProject(), ((ClasspathEntry)entries[j]).getLibraryIndexLocation());
+ }
externalArchivesStatus.put(entryPath, EXTERNAL_JAR_UNCHANGED);
}
} else {
@@ -1009,7 +1014,7 @@
this.state.getExternalLibTimeStamps().put(entryPath, new Long(newTimeStamp));
// index the new jar
this.manager.indexManager.removeIndex(entryPath);
- this.manager.indexManager.indexLibrary(entryPath, project.getProject());
+ this.manager.indexManager.indexLibrary(entryPath, project.getProject(), ((ClasspathEntry)entries[j]).getLibraryIndexLocation());
}
}
} else { // internal JAR
@@ -2629,13 +2634,13 @@
switch (delta.getKind()) {
case IResourceDelta.ADDED:
// index the new jar
- indexManager.indexLibrary(jarPath, root.getJavaProject().getProject());
+ indexManager.indexLibrary(jarPath, root.getJavaProject().getProject(), root.getIndexPath() );
break;
case IResourceDelta.CHANGED:
// first remove the index so that it is forced to be re-indexed
indexManager.removeIndex(jarPath);
// then index the jar
- indexManager.indexLibrary(jarPath, root.getJavaProject().getProject());
+ indexManager.indexLibrary(jarPath, root.getJavaProject().getProject(), root.getIndexPath());
break;
case IResourceDelta.REMOVED:
// the jar was physically removed: remove the index
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementDelta.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementDelta.java
index ee0d715..e55c951 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementDelta.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementDelta.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -569,6 +569,29 @@
detachedDelta.changed(F_SOURCEDETACHED);
insertDeltaTree(element, detachedDelta);
}
+
+/**
+ * Creates the nested deltas resulting from a change operation.
+ * Convenience method for creating change deltas.
+ * The constructor should be used to create the root delta
+ * and then a change operation should call this method.
+ */
+public void indexAttached(IJavaElement element) {
+ JavaElementDelta attachedDelta = new JavaElementDelta(element);
+ attachedDelta.changed(F_INDEXATTACHED);
+ insertDeltaTree(element, attachedDelta);
+}
+/**
+ * Creates the nested deltas resulting from a change operation.
+ * Convenience method for creating change deltas.
+ * The constructor should be used to create the root delta
+ * and then a change operation should call this method.
+ */
+public void indexDetached(IJavaElement element) {
+ JavaElementDelta detachedDelta = new JavaElementDelta(element);
+ detachedDelta.changed(F_INDEXDETACHED);
+ insertDeltaTree(element, detachedDelta);
+}
/**
* Returns a string representation of this delta's
* structure suitable for debug purposes.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java
index 9fb59c6..a640d6a 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,6 +10,7 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core;
+import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Map;
@@ -807,4 +808,16 @@
}
}
+public URL getIndexPath() {
+ try {
+ if (getKind() != K_BINARY) return null;
+
+ IClasspathEntry entry = ((JavaProject) getParent()).getClasspathEntryFor(getPath());
+ if (entry != null) return ((ClasspathEntry)entry).getLibraryIndexLocation();
+ } catch (JavaModelException e) {
+ // ignore exception
+ }
+ return null;
+}
+
}
diff --git a/org.eclipse.jdt.core/plugin.xml b/org.eclipse.jdt.core/plugin.xml
index 3784256..5d69788 100644
--- a/org.eclipse.jdt.core/plugin.xml
+++ b/org.eclipse.jdt.core/plugin.xml
@@ -1,7 +1,7 @@
@@ -196,6 +201,17 @@
+
+
++ * On MacOS, when invoked using the Eclipse executable, the "user.dir" property is set to the folder in which the + * eclipse.ini file is located. This makes it harder to use relative paths to point to the files to be formatted or the + * configuration file to use to set the code formatter's options. + *
+ * + * + * @since 3.8 + * @noinstantiate This class is not intended to be instantiated by clients. + * @noextend This class is not intended to be subclassed by clients. + */ +public class JavaIndexerApplication implements IApplication { + + private final static class Messages extends NLS { + private static final String MESSAGES_NAME = "org.eclipse.jdt.core.index.messages";//$NON-NLS-1$ + + public static String CommandLineProcessing; + public static String CommandLineUsage; + public static String CommandLineOnlyOutputError; + public static String CommandLineOnlyOneJarError; + public static String CommandLineJarNotSpecified; + public static String CommandLineIndexFileNotSpecified; + public static String CaughtException; + public static String CommandLineJarFileNotExist; + + static { + NLS.initializeMessages(MESSAGES_NAME, Messages.class); + } + + public static String bind(String message) { + return bind(message, null); + } + + public static String bind(String message, Object binding) { + return bind(message, new Object[] { binding }); + } + + public static String bind(String message, Object binding1, Object binding2) { + return bind(message, new Object[] { binding1, binding2 }); + } + + public static String bind(String message, Object[] bindings) { + return MessageFormat.format(message, bindings); + } + } + + private String jarToIndex; + private String indexFile; + private boolean verbose = false; + private static final String PDE_LAUNCH = "-pdelaunch"; //$NON-NLS-1$ + private static final String ARG_HELP = "-help"; //$NON-NLS-1$ + private static final String ARG_VERBOSE = "-verbose"; //$NON-NLS-1$ + private static final String ARG_OUTPUT = "-output"; //$NON-NLS-1$ + + private void displayHelp() { + System.out.println(Messages.bind(Messages.CommandLineUsage)); + } + + private void displayError(String message) { + System.err.println(message); + System.out.println(); + displayHelp(); + } + + private boolean processCommandLine(String[] argsArray) { + ArrayList args = new ArrayList(); + for (int i = 0, max = argsArray.length; i < max; i++) { + args.add(argsArray[i]); + } + int index = 0; + final int argCount = argsArray.length; + + loop: while (index < argCount) { + String currentArg = argsArray[index++]; + if (PDE_LAUNCH.equals(currentArg)) { + continue loop; + } else if (ARG_HELP.equals(currentArg)) { + displayHelp(); + return false; + } else if (ARG_VERBOSE.equals(currentArg)) { + this.verbose = true; + continue loop; + } else if (ARG_OUTPUT.equals(currentArg)) { + if (this.indexFile != null || index == argCount) { + displayError(Messages.bind(Messages.CommandLineOnlyOutputError)); + return false; + } + this.indexFile = argsArray[index++]; + } else { + if (this.jarToIndex != null) { + displayError(Messages.bind(Messages.CommandLineOnlyOneJarError)); + return false; + } + this.jarToIndex = currentArg; + } + } + return true; + } + + public Object start(IApplicationContext context) throws Exception { + boolean execute = processCommandLine((String[]) context.getArguments().get(IApplicationContext.APPLICATION_ARGS)); + if (execute) { + if (this.jarToIndex != null && this.indexFile != null) { + File f = new File(this.jarToIndex); + if (!f.exists()) { + System.out.println(Messages.bind(Messages.CommandLineJarFileNotExist, this.jarToIndex)); + } + if (this.verbose) { + System.out.println(Messages.bind(Messages.CommandLineProcessing, this.jarToIndex, this.indexFile)); + } + try { + JavaIndexer.generateIndexForJar(this.jarToIndex, this.indexFile); + } catch (IOException e) { + System.out.println(Messages.bind(Messages.CaughtException, "IOException", e.getLocalizedMessage())); //$NON-NLS-1$ + } + } else if (this.jarToIndex == null) { + System.out.println(Messages.bind(Messages.CommandLineJarNotSpecified)); + } else if (this.indexFile == null) { + System.out.println(Messages.bind(Messages.CommandLineIndexFileNotSpecified)); + } + } + return IApplication.EXIT_OK; + } + + public void stop() { + // do nothing + } + +} diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/index/messages.properties b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/index/messages.properties new file mode 100644 index 0000000..704b29f --- /dev/null +++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/index/messages.properties @@ -0,0 +1,28 @@ +############################################################################### +# Copyright (c) 2000, 2006 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +############################################################################### +CommandLineUsage=Usage: eclipse -application org.eclipse.jdt.core.JavaCodeGenerateIndex [ OPTIONS ] -outputnull
if not found
*/
-public synchronized Index getIndex(IPath indexLocation) {
+public synchronized Index getIndex(IndexLocation indexLocation) {
return (Index) this.indexes.get(indexLocation); // is null if unknown, call if the containerPath must be computed
}
/**
@@ -219,7 +221,7 @@
* Warning: Does not check whether index is consistent (not being used)
*/
public synchronized Index getIndex(IPath containerPath, boolean reuseExistingFile, boolean createIfMissing) {
- IPath indexLocation = computeIndexLocation(containerPath);
+ IndexLocation indexLocation = computeIndexLocation(containerPath);
return getIndex(containerPath, indexLocation, reuseExistingFile, createIfMissing);
}
/**
@@ -230,7 +232,7 @@
*
* Warning: Does not check whether index is consistent (not being used)
*/
-public synchronized Index getIndex(IPath containerPath, IPath indexLocation, boolean reuseExistingFile, boolean createIfMissing) {
+public synchronized Index getIndex(IPath containerPath, IndexLocation indexLocation, boolean reuseExistingFile, boolean createIfMissing) {
// Path is already canonical per construction
Index index = getIndex(indexLocation);
if (index == null) {
@@ -245,19 +247,17 @@
// index isn't cached, consider reusing an existing index file
String containerPathString = containerPath.getDevice() == null ? containerPath.toString() : containerPath.toOSString();
- String indexLocationString = indexLocation.toOSString();
if (reuseExistingFile) {
- File indexFile = new File(indexLocationString);
- if (indexFile.exists()) { // check before creating index so as to avoid creating a new empty index if file is missing
+ if (indexLocation.exists()) { // check before creating index so as to avoid creating a new empty index if file is missing
try {
- index = new Index(indexLocationString, containerPathString, true /*reuse index file*/);
+ index = new Index(indexLocation, containerPathString, true /*reuse index file*/);
this.indexes.put(indexLocation, index);
return index;
} catch (IOException e) {
// failed to read the existing file or its no longer compatible
- if (currentIndexState != REBUILDING_STATE) { // rebuild index if existing file is corrupt, unless the index is already being rebuilt
+ if (currentIndexState != REBUILDING_STATE || currentIndexState != REUSE_STATE) { // rebuild index if existing file is corrupt, unless the index is already being rebuilt
if (VERBOSE)
- Util.verbose("-> cannot reuse existing index: "+indexLocationString+" path: "+containerPathString); //$NON-NLS-1$ //$NON-NLS-2$
+ Util.verbose("-> cannot reuse existing index: "+indexLocation+" path: "+containerPathString); //$NON-NLS-1$ //$NON-NLS-2$
rebuildIndex(indexLocation, containerPath);
return null;
}
@@ -268,18 +268,27 @@
rebuildIndex(indexLocation, containerPath);
return null;
}
+ if (currentIndexState == REUSE_STATE) {
+ // supposed to be in reuse state but error in the index file, so reindex.
+ if (VERBOSE)
+ Util.verbose("-> cannot reuse given index: "+indexLocation+" path: "+containerPathString); //$NON-NLS-1$ //$NON-NLS-2$
+ this.indexLocations.put(containerPath, null);
+ indexLocation = computeIndexLocation(containerPath);
+ rebuildIndex(indexLocation, containerPath);
+ return null;
+ }
}
// index wasn't found on disk, consider creating an empty new one
if (createIfMissing) {
try {
if (VERBOSE)
- Util.verbose("-> create empty index: "+indexLocationString+" path: "+containerPathString); //$NON-NLS-1$ //$NON-NLS-2$
- index = new Index(indexLocationString, containerPathString, false /*do not reuse index file*/);
+ Util.verbose("-> create empty index: "+indexLocation+" path: "+containerPathString); //$NON-NLS-1$ //$NON-NLS-2$
+ index = new Index(indexLocation, containerPathString, false /*do not reuse index file*/);
this.indexes.put(indexLocation, index);
return index;
} catch (IOException e) {
if (VERBOSE)
- Util.verbose("-> unable to create empty index: "+indexLocationString+" path: "+containerPathString); //$NON-NLS-1$ //$NON-NLS-2$
+ Util.verbose("-> unable to create empty index: "+indexLocation+" path: "+containerPathString); //$NON-NLS-1$ //$NON-NLS-2$
// The file could not be created. Possible reason: the project has been deleted.
return null;
}
@@ -295,7 +304,7 @@
* @param locations The list of of the index files path
* @return The corresponding indexes list.
*/
-public Index[] getIndexes(IPath[] locations, IProgressMonitor progressMonitor) {
+public Index[] getIndexes(IndexLocation[] locations, IProgressMonitor progressMonitor) {
// acquire the in-memory indexes on the fly
int length = locations.length;
Index[] locatedIndexes = new Index[length];
@@ -308,7 +317,7 @@
throw new OperationCanceledException();
}
// may trigger some index recreation work
- IPath indexLocation = locations[i];
+ IndexLocation indexLocation = locations[i];
Index index = getIndex(indexLocation);
if (index == null) {
// only need containerPath if the index must be built
@@ -330,18 +339,16 @@
index = null;
}
} else {
- if (!getJavaPluginWorkingLocation().isPrefixOf(indexLocation)) { // the index belongs to non-jdt search participant
- if (indexLocation.toFile().exists()) {
- try {
- IPath container = getParticipantsContainer(indexLocation);
- if (container != null) {
- index = new Index(indexLocation.toOSString(), container.toOSString(), true /*reuse index file*/);
- this.indexes.put(indexLocation, index);
- }
- } catch (IOException e) {
- // ignore
+ if (indexLocation.isParticipantIndex() && indexLocation.exists()) { // the index belongs to non-jdt search participant
+ try {
+ IPath container = getParticipantsContainer(indexLocation);
+ if (container != null) {
+ index = new Index(indexLocation, container.toOSString(), true /*reuse index file*/);
+ this.indexes.put(indexLocation, index);
}
- }
+ } catch (IOException e) {
+ // ignore
+ }
}
}
}
@@ -358,7 +365,7 @@
return locatedIndexes;
}
public synchronized Index getIndexForUpdate(IPath containerPath, boolean reuseExistingFile, boolean createIfMissing) {
- IPath indexLocation = computeIndexLocation(containerPath);
+ IndexLocation indexLocation = computeIndexLocation(containerPath);
if (getIndexStates().get(indexLocation) == REBUILDING_STATE)
return getIndex(containerPath, indexLocation, reuseExistingFile, createIfMissing);
@@ -368,13 +375,13 @@
if (this.indexStates != null) return this.indexStates;
this.indexStates = new SimpleLookupTable();
- IPath indexesDirectoryPath = getJavaPluginWorkingLocation();
- char[][] savedNames = readIndexState(indexesDirectoryPath.toOSString());
+ File indexesDirectoryPath = getSavedIndexesDirectory();
+ char[][] savedNames = readIndexState(getJavaPluginWorkingLocation().toOSString());
if (savedNames != null) {
for (int i = 1, l = savedNames.length; i < l; i++) { // first name is saved signature, see readIndexState()
char[] savedName = savedNames[i];
if (savedName.length > 0) {
- IPath indexLocation = indexesDirectoryPath.append(new String(savedName)); // shares indexesDirectoryPath's segments
+ IndexLocation indexLocation = new FlatFileIndex(new File(indexesDirectoryPath, String.valueOf(savedName))); // shares indexesDirectoryPath's segments
if (VERBOSE)
Util.verbose("Reading saved index file " + indexLocation); //$NON-NLS-1$
this.indexStates.put(indexLocation, SAVED_STATE);
@@ -389,7 +396,7 @@
}
return this.indexStates;
}
-private IPath getParticipantsContainer(IPath indexLocation) {
+private IPath getParticipantsContainer(IndexLocation indexLocation) {
if (this.participantsContainers == null) {
readParticipantsIndexNamesFile();
}
@@ -474,7 +481,7 @@
for (int i = 0; i < entries.length; i++) {
IClasspathEntry entry= entries[i];
if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY)
- indexLibrary(entry.getPath(), project);
+ indexLibrary(entry.getPath(), project, ((ClasspathEntry)entry).getLibraryIndexLocation());
}
} catch(JavaModelException e){ // cannot retrieve classpath info
}
@@ -488,16 +495,16 @@
* Trigger addition of a library to an index
* Note: the actual operation is performed in background
*/
-public void indexLibrary(IPath path, IProject requestingProject) {
+public void indexLibrary(IPath path, IProject requestingProject, URL indexURL) {
// requestingProject is no longer used to cancel jobs but leave it here just in case
+ IndexLocation indexFile = indexURL != null ? IndexLocation.createIndexLocation(indexURL): null;
if (JavaCore.getPlugin() == null) return;
-
- Object target = JavaModel.getTarget(path, true);
IndexRequest request = null;
+ Object target = JavaModel.getTarget(path, true);
if (target instanceof IFile) {
- request = new AddJarFileToIndex((IFile) target, this);
+ request = new AddJarFileToIndex((IFile) target, indexFile, this);
} else if (target instanceof File) {
- request = new AddJarFileToIndex(path, this);
+ request = new AddJarFileToIndex(path, indexFile, this);
} else if (target instanceof IContainer) {
request = new IndexBinaryFolder((IContainer) target, this);
} else {
@@ -508,6 +515,19 @@
if (!isJobWaiting(request))
request(request);
}
+
+synchronized boolean addIndex(IPath containerPath, IndexLocation indexFile) {
+ this.indexStates.put(indexFile, REUSE_STATE);
+ this.indexLocations.put(containerPath, indexFile);
+ Index index = getIndex(containerPath, indexFile, true, false);
+ if (index == null) {
+ indexFile.close();
+ this.indexLocations.put(containerPath, null);
+ return false;
+ }
+ return true;
+}
+
/**
* Index the content of the given source folder.
*/
@@ -522,7 +542,7 @@
request(new AddFolderToIndex(sourceFolder, project, inclusionPatterns, exclusionPatterns, this));
}
public synchronized void jobWasCancelled(IPath containerPath) {
- IPath indexLocation = computeIndexLocation(containerPath);
+ IndexLocation indexLocation = computeIndexLocation(containerPath);
Index index = getIndex(indexLocation);
if (index != null) {
index.monitor = null;
@@ -568,7 +588,7 @@
}
return null;
}
-private void rebuildIndex(IPath indexLocation, IPath containerPath) {
+private void rebuildIndex(IndexLocation indexLocation, IPath containerPath) {
Object target = JavaModel.getTarget(containerPath, true);
if (target == null) return;
@@ -584,9 +604,9 @@
} else if (target instanceof IFolder) {
request = new IndexBinaryFolder((IFolder) target, this);
} else if (target instanceof IFile) {
- request = new AddJarFileToIndex((IFile) target, this);
+ request = new AddJarFileToIndex((IFile) target, null, this);
} else if (target instanceof File) {
- request = new AddJarFileToIndex(containerPath, this);
+ request = new AddJarFileToIndex(containerPath, null, this);
}
if (request != null)
request(request);
@@ -601,13 +621,13 @@
String containerPathString = containerPath.getDevice() == null ? containerPath.toString() : containerPath.toOSString();
try {
// Path is already canonical
- IPath indexLocation = computeIndexLocation(containerPath);
+ IndexLocation indexLocation = computeIndexLocation(containerPath);
Index index = getIndex(indexLocation);
ReadWriteMonitor monitor = index == null ? null : index.monitor;
if (VERBOSE)
Util.verbose("-> recreating index: "+indexLocation+" for path: "+containerPathString); //$NON-NLS-1$ //$NON-NLS-2$
- index = new Index(indexLocation.toOSString(), containerPathString, false /*do not reuse index file*/);
+ index = new Index(indexLocation, containerPathString, false /*do not reuse index file*/);
this.indexes.put(indexLocation, index);
index.monitor = monitor;
return index;
@@ -634,7 +654,7 @@
public synchronized void removeIndex(IPath containerPath) {
if (VERBOSE || DEBUG)
Util.verbose("removing index " + containerPath); //$NON-NLS-1$
- IPath indexLocation = computeIndexLocation(containerPath);
+ IndexLocation indexLocation = computeIndexLocation(containerPath);
Index index = getIndex(indexLocation);
File indexFile = null;
if (index != null) {
@@ -642,8 +662,11 @@
indexFile = index.getIndexFile();
}
if (indexFile == null)
- indexFile = new File(indexLocation.toOSString()); // index is not cached yet, but still want to delete the file
- if (indexFile.exists()) {
+ indexFile = indexLocation.getIndexFile(); // index is not cached yet, but still want to delete the file
+ if (this.indexStates.get(indexLocation) == REUSE_STATE) {
+ indexLocation.close();
+ this.indexLocations.put(containerPath, null);
+ } else if (indexFile != null && indexFile.exists()) {
if (DEBUG)
Util.verbose("removing index file " + indexFile); //$NON-NLS-1$
indexFile.delete();
@@ -659,24 +682,25 @@
Util.verbose("removing index path " + path); //$NON-NLS-1$
Object[] keyTable = this.indexes.keyTable;
Object[] valueTable = this.indexes.valueTable;
- IPath[] locations = null;
+ IndexLocation[] locations = null;
int max = this.indexes.elementSize;
int count = 0;
for (int i = 0, l = keyTable.length; i < l; i++) {
- IPath indexLocation = (IPath) keyTable[i];
+ IndexLocation indexLocation = (IndexLocation) keyTable[i];
if (indexLocation == null)
continue;
- if (path.isPrefixOf(indexLocation)) {
+ if (path.isPrefixOf(new Path(indexLocation.getFilePath()))) {
Index index = (Index) valueTable[i];
index.monitor = null;
if (locations == null)
- locations = new IPath[max];
+ locations = new IndexLocation[max];
locations[count++] = indexLocation;
- File indexFile = index.getIndexFile();
- if (indexFile.exists()) {
+ if (this.indexStates.get(indexLocation) == REUSE_STATE) {
+ indexLocation.close();
+ } else {
if (DEBUG)
- Util.verbose("removing index file " + indexFile); //$NON-NLS-1$
- indexFile.delete();
+ Util.verbose("removing index file " + indexLocation); //$NON-NLS-1$
+ indexLocation.delete();
}
} else {
max--;
@@ -686,9 +710,15 @@
for (int i = 0; i < count; i++)
this.indexes.removeKey(locations[i]);
removeIndexesState(locations);
- if (this.participantsContainers != null && this.participantsContainers.get(path.toOSString()) != null) {
- this.participantsContainers.removeKey(path.toOSString());
- writeParticipantsIndexNamesFile();
+ if (this.participantsContainers != null) {
+ boolean update = false;
+ for (int i = 0; i < count; i++) {
+ if (this.participantsContainers.get(locations[i]) != null) {
+ update = true;
+ this.participantsContainers.removeKey(locations[i]);
+ }
+ }
+ if (update) writeParticipantsIndexNamesFile();
}
}
}
@@ -746,7 +776,7 @@
String containerPathString = containerPath.getDevice() == null ? containerPath.toString() : containerPath.toOSString();
try {
// Path is already canonical
- IPath indexLocation = computeIndexLocation(containerPath);
+ IndexLocation indexLocation = computeIndexLocation(containerPath);
Index index = getIndex(indexLocation);
if (VERBOSE) {
Util.verbose("-> reseting index: "+indexLocation+" for path: "+containerPathString); //$NON-NLS-1$ //$NON-NLS-2$
@@ -770,7 +800,7 @@
// must have permission to write from the write monitor
if (index.hasChanged()) {
if (VERBOSE)
- Util.verbose("-> saving index " + index.getIndexFile()); //$NON-NLS-1$
+ Util.verbose("-> saving index " + index.getIndexLocation()); //$NON-NLS-1$
index.save();
}
synchronized (this) {
@@ -782,7 +812,7 @@
if (((IndexRequest) job).containerPath.equals(containerPath)) return;
}
}
- IPath indexLocation = computeIndexLocation(containerPath);
+ IndexLocation indexLocation = computeIndexLocation(containerPath);
updateIndexState(indexLocation, SAVED_STATE);
}
}
@@ -837,20 +867,21 @@
}
this.needToSave = !allSaved;
}
-public void scheduleDocumentIndexing(final SearchDocument searchDocument, IPath container, final IPath indexLocation, final SearchParticipant searchParticipant) {
+public void scheduleDocumentIndexing(final SearchDocument searchDocument, IPath container, final IndexLocation indexLocation, final SearchParticipant searchParticipant) {
request(new IndexRequest(container, this) {
public boolean execute(IProgressMonitor progressMonitor) {
if (this.isCancelled || progressMonitor != null && progressMonitor.isCanceled()) return true;
/* ensure no concurrent write access to index */
- Index index = getIndex(this.containerPath, indexLocation, true, /*reuse index file*/ true /*create if none*/);
+ Index index;
+ index = getIndex(this.containerPath, indexLocation, true, /*reuse index file*/ true /*create if none*/);
if (index == null) return true;
ReadWriteMonitor monitor = index.monitor;
if (monitor == null) return true; // index got deleted since acquired
try {
monitor.enterWrite(); // ask permission to write
- indexDocument(searchDocument, searchParticipant, index, indexLocation);
+ indexDocument(searchDocument, searchParticipant, index, new Path(indexLocation.getFilePath()));
} finally {
monitor.exitWrite(); // free write lock
}
@@ -904,7 +935,9 @@
// First line is DiskIndex signature (see writeParticipantsIndexNamesFile())
if (DiskIndex.SIGNATURE.equals(new String(names[0]))) {
for (int i = 1, l = names.length-1 ; i < l ; i+=2) {
- containers.put(new Path(new String(names[i])), new Path(new String(names[i+1])));
+ IndexLocation indexLocation = new FlatFileIndex(new File(new String(names[i])));
+ indexLocation.setParticipantIndex();
+ containers.put(indexLocation, new Path(new String(names[i+1])));
}
}
}
@@ -916,7 +949,7 @@
this.participantsContainers = containers;
return;
}
-private synchronized void removeIndexesState(IPath[] locations) {
+private synchronized void removeIndexesState(IndexLocation[] locations) {
getIndexStates(); // ensure the states are initialized
int length = locations.length;
boolean changed = false;
@@ -933,8 +966,8 @@
writeSavedIndexNamesFile();
}
-private synchronized void updateIndexState(IPath indexLocation, Integer indexState) {
- if (indexLocation.isEmpty())
+private synchronized void updateIndexState(IndexLocation indexLocation, Integer indexState) {
+ if (indexLocation == null)
throw new IllegalArgumentException();
getIndexStates(); // ensure the states are initialized
@@ -962,12 +995,14 @@
}
}
-public void updateParticipant(IPath indexLocation, IPath containerPath) {
+public void updateParticipant(IPath indexPath, IPath containerPath) {
if (this.participantsContainers == null) {
readParticipantsIndexNamesFile();
- }
+ }
+ IndexLocation indexLocation = new FlatFileIndex(indexPath.toFile());
if (this.participantsContainers.get(indexLocation) == null) {
this.participantsContainers.put(indexLocation, containerPath);
+ indexLocation.setParticipantIndex();
this.participantUpdated = true;
}
}
@@ -1014,9 +1049,9 @@
Object[] indexFiles = this.participantsContainers.keyTable;
Object[] containers = this.participantsContainers.valueTable;
for (int i = 0, l = indexFiles.length; i < l; i++) {
- IPath indexFile = (IPath)indexFiles[i];
+ IndexLocation indexFile = (IndexLocation)indexFiles[i];
if (indexFile != null) {
- writer.write(indexFile.toOSString());
+ writer.write(indexFile.getIndexFile().getPath());
writer.write('\n');
writer.write(((IPath)containers[i]).toOSString());
writer.write('\n');
@@ -1046,9 +1081,9 @@
Object[] keys = this.indexStates.keyTable;
Object[] states = this.indexStates.valueTable;
for (int i = 0, l = states.length; i < l; i++) {
- IPath key = (IPath) keys[i];
- if (key != null && !key.isEmpty() && states[i] == SAVED_STATE) {
- writer.write(key.lastSegment());
+ IndexLocation key = (IndexLocation) keys[i];
+ if (key != null && states[i] == SAVED_STATE) {
+ writer.write(key.fileName());
writer.write('\n');
}
}