/******************************************************************************* * Copyright (c) 2000, 2015 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.debug.tests.core; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.jdt.core.IClasspathAttribute; import org.eclipse.jdt.core.IClasspathContainer; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.index.JavaIndexer; import org.eclipse.jdt.debug.testplugin.JavaTestPlugin; import org.eclipse.jdt.debug.tests.AbstractDebugTest; import org.eclipse.jdt.internal.launching.JREContainer; import org.eclipse.jdt.internal.launching.JREContainerInitializer; import org.eclipse.jdt.internal.launching.JRERuntimeClasspathEntryResolver; import org.eclipse.jdt.launching.IVMInstall; import org.eclipse.jdt.launching.JavaRuntime; import org.eclipse.jdt.launching.LibraryLocation; import org.eclipse.jdt.launching.VMStandin; /** * Tests JRE classpath container */ public class ClasspathContainerTests extends AbstractDebugTest { class FakeContainer implements IClasspathContainer { IClasspathEntry[] entries = new IClasspathEntry[0]; /** * @see org.eclipse.jdt.core.IClasspathContainer#getClasspathEntries() */ @Override public IClasspathEntry[] getClasspathEntries() { return entries; } /** * @see org.eclipse.jdt.core.IClasspathContainer#getDescription() */ @Override public String getDescription() { return "Fake"; } /** * @see org.eclipse.jdt.core.IClasspathContainer#getKind() */ @Override public int getKind() { return IClasspathContainer.K_DEFAULT_SYSTEM; } /** * @see org.eclipse.jdt.core.IClasspathContainer#getPath() */ @Override public IPath getPath() { return new Path(JavaRuntime.JRE_CONTAINER); } /** * @param cpe */ public void setEntries(IClasspathEntry[] cpe) { entries = cpe; } } /** * @param name */ public ClasspathContainerTests(String name) { super(name); } /** * Tests that the container will accept an update * @throws CoreException */ public void testCanUpdate() throws CoreException { // Create a new VM install that mirrors the current install IVMInstall def = JavaRuntime.getDefaultVMInstall(); String vmId = def.getId() + System.currentTimeMillis(); VMStandin standin = new VMStandin(def.getVMInstallType(), vmId); String vmName = "Alternate JRE"; IPath containerPath = new Path(JavaRuntime.JRE_CONTAINER); containerPath = containerPath.append(new Path(def.getVMInstallType().getId())); containerPath = containerPath.append(new Path(vmName)); standin.setName(vmName); standin.setInstallLocation(def.getInstallLocation()); standin.setJavadocLocation(def.getJavadocLocation()); standin.setLibraryLocations(JavaRuntime.getLibraryLocations(def)); standin.convertToRealVM(); // ensure the new VM exists IVMInstall newVM = def.getVMInstallType().findVMInstall(vmId); assertNotNull("Failed to create new VM", newVM); JREContainer container = new JREContainer(newVM, containerPath, get14Project()); JREContainerInitializer initializer = new JREContainerInitializer(); // store the current library settings LibraryLocation[] originalLibs = JavaRuntime.getLibraryLocations(newVM); assertTrue("Libraries should not be empty", originalLibs.length > 0); IClasspathEntry[] originalEntries = container.getClasspathEntries(); assertEquals("Libraries should be same size as classpath entries", originalLibs.length, originalEntries.length); // ensure we can update assertTrue("Initializer will not accept update", initializer.canUpdateClasspathContainer(containerPath, get14Project())); // update to an empty set of libraries FakeContainer fakeContainer = new FakeContainer(); initializer.requestClasspathContainerUpdate(containerPath, get14Project(), fakeContainer); // ensure the library locations are now empty on the new VM LibraryLocation[] newLibs = JavaRuntime.getLibraryLocations(newVM); assertEquals("Libraries should be empty", 0, newLibs.length); // re-set to original libraries fakeContainer.setEntries(originalEntries); initializer.requestClasspathContainerUpdate(containerPath, get14Project(), fakeContainer); // ensure libraries are restored newLibs = JavaRuntime.getLibraryLocations(newVM); assertEquals("Libraries should be restored", originalLibs.length, newLibs.length); for (int i = 0; i < newLibs.length; i++) { LibraryLocation location = newLibs[i]; LibraryLocation origi = originalLibs[i]; assertEquals("Library should be the equal", origi.getSystemLibraryPath().toFile(), location.getSystemLibraryPath().toFile()); } } /** * Tests library comparison case sensitivity. * * @throws CoreException */ public void testLibraryCaseSensitivity() { IVMInstall def = JavaRuntime.getDefaultVMInstall(); LibraryLocation[] libs = JavaRuntime.getLibraryLocations(def); boolean caseSensitive = !Platform.getOS().equals(Platform.WS_WIN32); LibraryLocation[] set1 = new LibraryLocation[libs.length]; LibraryLocation[] set2 = new LibraryLocation[libs.length]; for (int i = 0; i < libs.length; i++) { LibraryLocation lib = libs[i]; String s1 = lib.getSystemLibraryPath().toOSString(); IPath p1 = new Path(s1); String s2 = s1.toUpperCase(); IPath p2 = new Path(s2); set1[i] = new LibraryLocation(p1, null, null); set2[i] = new LibraryLocation(p2, null, null); } boolean equal = JRERuntimeClasspathEntryResolver.isSameArchives(set1, set2); if (caseSensitive) { assertFalse("Libraries should *not* be equal on case sensitive platform", equal); } else { assertTrue("Libraries *should* be equal on case sensitive platform", equal); } } /** * Tests that an index can be added to a {@link LibraryLocation} * * @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=399098 * @since 3.8.100 */ public void testJREContainerIndex() throws Exception { // get the current VM IVMInstall def = JavaRuntime.getDefaultVMInstall(); LibraryLocation[] libs = JavaRuntime.getLibraryLocations(def); // generate an index for the first library location only (to save time - do not need an index for all libraries) URL indexURL = this.getIndexForLibrary(libs[0]); // clone the current VM, but only add the one library that was indexed VMStandin newVMStandin = new VMStandin(def.getVMInstallType(), "index.jre"); newVMStandin.setName("JRE with pre-built index"); newVMStandin.setInstallLocation(def.getInstallLocation()); final LibraryLocation[] newLibs = new LibraryLocation[1]; newLibs[0] = new LibraryLocation(libs[0].getSystemLibraryPath(), libs[0].getSystemLibrarySourcePath(), libs[0].getPackageRootPath(), libs[0].getJavadocLocation(), indexURL); newVMStandin.setLibraryLocations(newLibs); IVMInstall newVM = newVMStandin.convertToRealVM(); // make sure the index URL is correct assertEquals(indexURL, newVM.getLibraryLocations()[0].getIndexLocation()); // create the JRE container IPath containerPath = new Path(JavaRuntime.JRE_CONTAINER); JREContainer container = new JREContainer(newVM, containerPath, get14Project()); IClasspathEntry[] originalEntries = container.getClasspathEntries(); // There should only be 1 classpath entry (the 1 library added) assertEquals(1, originalEntries.length); IClasspathAttribute[] cpAttributes = originalEntries[0].getExtraAttributes(); String indexloc = null; for (int i = 0; i < cpAttributes.length; i++) { if(IClasspathAttribute.INDEX_LOCATION_ATTRIBUTE_NAME.equals(cpAttributes[i].getName())) { indexloc = cpAttributes[i].getValue(); break; } } assertNotNull("The index_location classpath attribue was not found", indexloc); // and it should have a value of the original indexURL in its string form. assertEquals(indexURL.toString(), indexloc); } /** * Tests that an index can be added to a {@link LibraryLocation} and that successive calls to * {@link JavaRuntime#getLibraryLocations(IVMInstall)} does not erase the index infos * * @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=399098 * @since 3.8.100 */ public void testJREContainerIndex2() throws Exception { // get the current VM IVMInstall def = JavaRuntime.getDefaultVMInstall(); LibraryLocation[] libs = JavaRuntime.getLibraryLocations(def); // generate an index for the first library location only (to save time - do not need an index for all libraries) URL indexURL = this.getIndexForLibrary(libs[0]); // clone the current VM, but only add the one library that was indexed VMStandin newVMStandin = new VMStandin(def.getVMInstallType(), "index.jre"); newVMStandin.setName("JRE with pre-built index"); newVMStandin.setInstallLocation(def.getInstallLocation()); final LibraryLocation[] newLibs = new LibraryLocation[1]; newLibs[0] = new LibraryLocation(libs[0].getSystemLibraryPath(), libs[0].getSystemLibrarySourcePath(), libs[0].getPackageRootPath(), libs[0].getJavadocLocation(), indexURL); newVMStandin.setLibraryLocations(newLibs); IVMInstall newVM = newVMStandin.convertToRealVM(); libs = JavaRuntime.getLibraryLocations(newVM); assertNotNull("There should be an index file for: "+libs[0].getSystemLibraryPath(), libs[0].getIndexLocation()); } /** * Generates and returns a {@link URL} to the index file for a given {@link LibraryLocation} into the state location */ private URL getIndexForLibrary(final LibraryLocation library) throws IOException, MalformedURLException { // construct the path to the index file File libraryFile = library.getSystemLibraryPath().toFile(); String indexName = libraryFile.getName() + ".index"; IPath indexPath = JavaTestPlugin.getDefault().getStateLocation().append(indexName); // generate the index using JDT Core API JavaIndexer.generateIndexForJar(libraryFile.getAbsolutePath(), indexPath.toOSString()); // return the index URL URL indexURL = indexPath.toFile().toURI().toURL(); return indexURL; } }