blob: 45b5fea23bf896567e3cea49be7e6a6801675280 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2021 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.osgi.tests.services.datalocation;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.tests.harness.CoreTest;
import org.eclipse.equinox.log.SynchronousLogListener;
import org.eclipse.osgi.internal.framework.EquinoxConfiguration;
import org.eclipse.osgi.internal.location.EquinoxLocations;
import org.eclipse.osgi.launch.Equinox;
import org.eclipse.osgi.service.datalocation.Location;
import org.eclipse.osgi.tests.OSGiTestsActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.service.log.LogEntry;
import org.osgi.service.log.LogReaderService;
import org.osgi.util.tracker.ServiceTracker;
public class BasicLocationTests extends CoreTest {
String prefix = "";
boolean windows = Platform.getOS().equals(Platform.OS_WIN32);
ServiceTracker<Location, Location> configLocationTracker = null;
ServiceTracker<Location, Location> instanceLocationTracker = null;
public BasicLocationTests(String name) {
super(name);
}
public static Test suite() {
return new TestSuite(BasicLocationTests.class);
}
protected void setUp() throws Exception {
super.setUp();
prefix = windows ? "c:" : "";
configLocationTracker = new ServiceTracker<>(OSGiTestsActivator.getContext(), OSGiTestsActivator.getContext().createFilter(Location.CONFIGURATION_FILTER), null);
instanceLocationTracker = new ServiceTracker<>(OSGiTestsActivator.getContext(), OSGiTestsActivator.getContext().createFilter(Location.INSTANCE_FILTER), null);
configLocationTracker.open();
instanceLocationTracker.open();
}
protected void tearDown() throws Exception {
configLocationTracker.close();
instanceLocationTracker.close();
super.tearDown();
}
private void checkSlashes(Map<String, Location> locations) {
checkLocation(locations.get(Location.USER_FILTER), true, true, null);
checkLocation(locations.get(Location.INSTANCE_FILTER), true, true, null);
checkLocation(locations.get(Location.CONFIGURATION_FILTER), true, true, null);
checkLocation(locations.get(Location.INSTALL_FILTER), true, true, null);
}
private void checkLocation(Location location, boolean leading, boolean trailing, String scheme) {
if (location == null)
return;
URL url = location.getURL();
if (scheme != null)
assertEquals(scheme, url.getProtocol());
if (!url.getProtocol().equals("file"))
return;
assertTrue(url.toExternalForm() + " should " + (trailing ? "" : "not") + " have a trailing slash", url.getFile().endsWith("/") == trailing);
if (windows)
assertTrue(url.toExternalForm() + " should " + (leading ? "" : "not") + " have a leading slash", url.getFile().startsWith("/") == leading);
}
public void testCreateLocation01() {
Location configLocation = configLocationTracker.getService();
File testLocationFile = OSGiTestsActivator.getContext().getDataFile("testLocations/testCreateLocation01");
Location testLocation = configLocation.createLocation(null, null, false);
try {
testLocation.set(testLocationFile.toURL(), false);
} catch (Throwable t) {
fail("Failed to set location", t);
}
try {
assertTrue("Could not lock location", testLocation.lock());
} catch (IOException e) {
fail("Failed to lock location", e);
}
testLocation.release();
}
public void testCreateLocation02() {
Location configLocation = configLocationTracker.getService();
File testLocationFile = OSGiTestsActivator.getContext().getDataFile("testLocations/testCreateLocation02");
Location testLocation = configLocation.createLocation(null, null, true);
try {
testLocation.set(testLocationFile.toURL(), false);
} catch (Throwable t) {
fail("Failed to set location", t);
}
try {
assertTrue("Could not lock location", testLocation.lock());
testLocation.release();
fail("Should not be able to lock read-only location");
} catch (IOException e) {
// expected
}
}
public void testCreateLocation03() {
Location configLocation = configLocationTracker.getService();
File testLocationFile = OSGiTestsActivator.getContext().getDataFile("testLocations/testCreateLocation03");
Location testLocation = configLocation.createLocation(null, null, false);
try {
testLocation.set(testLocationFile.toURL(), true);
} catch (Throwable t) {
fail("Failed to set location", t);
}
try {
assertTrue("Could not lock location", testLocation.isLocked());
} catch (IOException e) {
fail("Failed to lock location", e);
}
testLocation.release();
}
public void testCreateLocation04() {
Location configLocation = configLocationTracker.getService();
File testLocationFile = OSGiTestsActivator.getContext().getDataFile("testLocations/testCreateLocation04");
Location testLocation = configLocation.createLocation(null, null, true);
try {
testLocation.set(testLocationFile.toURL(), true);
testLocation.release();
fail("Should not be able to lock read-only location");
} catch (Throwable t) {
// expected
}
}
public void testCreateLocation05() {
Location configLocation = configLocationTracker.getService();
File testLocationFile = OSGiTestsActivator.getContext().getDataFile("testLocations/testCreateLocation01");
Location testLocation = configLocation.createLocation(null, null, false);
try {
testLocation.set(testLocationFile.toURL(), false);
} catch (Throwable t) {
fail("Failed to set location", t);
}
try {
assertTrue("Could not lock location", testLocation.lock());
assertFalse("Could lock a secend time", testLocation.lock());
assertFalse("Could lock a third time", testLocation.lock());
} catch (IOException e) {
fail("Failed to lock location", e);
} finally {
testLocation.release();
}
try {
assertTrue("Could not lock location", testLocation.lock());
} catch (IOException e) {
fail("Failed to lock location", e);
} finally {
testLocation.release();
}
}
private static final String INSTANCE_DATA_AREA_PREFIX = ".metadata/.plugins/"; //$NON-NLS-1$
public void testLocationDataArea01() {
Location instance = instanceLocationTracker.getService();
doAllTestLocationDataArea(instance, INSTANCE_DATA_AREA_PREFIX);
Location configuration = configLocationTracker.getService();
doAllTestLocationDataArea(configuration, "");
}
private void doAllTestLocationDataArea(Location location, String dataAreaPrefix) {
doTestLocateDataArea(location, dataAreaPrefix, getName());
doTestLocateDataArea(location, dataAreaPrefix, "");
doTestLocateDataArea(location, dataAreaPrefix, "test/multiple/paths");
doTestLocateDataArea(location, dataAreaPrefix, "test/multiple/../paths");
doTestLocateDataArea(location, dataAreaPrefix, "test\\multiple\\paths");
doTestLocateDataArea(location, dataAreaPrefix, "/test/begin/slash");
File testLocationFile = OSGiTestsActivator.getContext().getDataFile("testLocations/" + getName());
Location createdLocation = location.createLocation(null, null, false);
try {
createdLocation.set(testLocationFile.toURL(), false);
} catch (Exception e) {
fail("Failed to set location", e);
}
doTestLocateDataArea(createdLocation, dataAreaPrefix, getName());
doTestLocateDataArea(createdLocation, dataAreaPrefix, "");
doTestLocateDataArea(createdLocation, dataAreaPrefix, "test/multiple/paths");
doTestLocateDataArea(createdLocation, dataAreaPrefix, "test/multiple/../paths");
doTestLocateDataArea(location, dataAreaPrefix, "test\\multiple\\paths");
doTestLocateDataArea(location, dataAreaPrefix, "/test/begin/slash");
createdLocation = location.createLocation(null, null, false);
try {
createdLocation.getDataArea("shouldFail");
fail("expected failure when location is not set");
} catch (IOException e) {
// expected;
}
}
private void doTestLocateDataArea(Location location, String dataAreaPrefix, String namespace) {
assertTrue("Location is not set", location.isSet());
URL dataArea = null;
try {
dataArea = location.getDataArea(namespace);
} catch (IOException e) {
fail("Failed to get data area.", e);
}
assertNotNull("Data area is null.", dataArea);
namespace = namespace.replace('\\', '/');
if (namespace.startsWith("/")) {
namespace = namespace.substring(1);
}
assertTrue("Data area is not the expected value: " + dataArea.toExternalForm(), dataArea.toExternalForm().endsWith(dataAreaPrefix + namespace));
}
public void testSetLocationWithEmptyLockFile() {
Location configLocation = configLocationTracker.getService();
File testLocationFile = OSGiTestsActivator.getContext().getDataFile("testLocations/testSetLocationWithEmptyLockFile"); //$NON-NLS-1$
Location testLocation = configLocation.createLocation(null, null, false);
try {
testLocation.set(testLocationFile.toURL(), true, ""); //$NON-NLS-1$
// Make sure it has created the default lock file
File lockFile = new File(testLocationFile, ".metadata/.lock"); //$NON-NLS-1$
assertTrue("Lock file does not exist!", lockFile.exists()); //$NON-NLS-1$
} catch (Throwable t) {
fail("Failed to set location", t); //$NON-NLS-1$
}
try {
assertTrue("Could not lock location", testLocation.isLocked()); //$NON-NLS-1$
} catch (IOException e) {
fail("Failed to lock location", e); //$NON-NLS-1$
}
testLocation.release();
}
public void testSetLocationWithRelLockFile() {
Location configLocation = configLocationTracker.getService();
File testLocationFile = OSGiTestsActivator.getContext().getDataFile("testLocations/testSetLocationWithRelLockFile"); //$NON-NLS-1$
Location testLocation = configLocation.createLocation(null, null, false);
try {
testLocation.set(testLocationFile.toURL(), true, ".mocklock"); //$NON-NLS-1$
File lockFile = new File(testLocationFile, ".mocklock"); //$NON-NLS-1$
assertTrue("Lock file does not exist!", lockFile.exists()); //$NON-NLS-1$
} catch (Throwable t) {
fail("Failed to set location", t); //$NON-NLS-1$
}
try {
assertTrue("Could not lock location", testLocation.isLocked()); //$NON-NLS-1$
} catch (IOException e) {
fail("Failed to lock location", e); //$NON-NLS-1$
}
testLocation.release();
}
public void testSetLocationWithAbsLockFile() {
Location configLocation = configLocationTracker.getService();
File testLocationFile = OSGiTestsActivator.getContext().getDataFile("testLocations/testSetLocationWithAbsLockFile"); //$NON-NLS-1$
File testLocationLockFile = OSGiTestsActivator.getContext().getDataFile("testLocations/mock.lock"); //$NON-NLS-1$
assertTrue(testLocationLockFile.isAbsolute());
Location testLocation = configLocation.createLocation(null, null, false);
try {
testLocation.set(testLocationFile.toURL(), true, testLocationLockFile.getAbsolutePath());
assertTrue("The lock file should be present!", testLocationLockFile.exists()); //$NON-NLS-1$
} catch (Throwable t) {
fail("Failed to set location", t); //$NON-NLS-1$
}
try {
assertTrue("Could not lock location", testLocation.isLocked()); //$NON-NLS-1$
} catch (IOException e) {
fail("Failed to lock location", e); //$NON-NLS-1$
}
testLocation.release();
assertTrue("The lock file could not be removed!", testLocationLockFile.delete()); //$NON-NLS-1$
}
public void testSlashes() throws BundleException, InvalidSyntaxException {
Map<String, String> fwkConfig = new HashMap<>();
fwkConfig.put(EquinoxLocations.PROP_CONFIG_AREA + EquinoxLocations.READ_ONLY_AREA_SUFFIX, "true");
fwkConfig.put(EquinoxLocations.PROP_USER_AREA, prefix + "/a");
fwkConfig.put(EquinoxLocations.PROP_INSTANCE_AREA, prefix + "/c/d");
fwkConfig.put(EquinoxLocations.PROP_CONFIG_AREA, prefix + "/e/f");
fwkConfig.put(EquinoxLocations.PROP_INSTALL_AREA, "file:" + prefix + "/g");
Equinox equinox = new Equinox(fwkConfig);
equinox.init();
try {
checkSlashes(getLocations(equinox));
} finally {
equinox.stop();
}
}
private static Map<String, Location> getLocations(Equinox equinox) throws InvalidSyntaxException {
Map<String, Location> locations = new HashMap<>();
BundleContext context = equinox.getBundleContext();
addLocation(context, Location.CONFIGURATION_FILTER, locations);
addLocation(context, Location.INSTALL_FILTER, locations);
addLocation(context, Location.INSTANCE_FILTER, locations);
addLocation(context, Location.USER_FILTER, locations);
return locations;
}
private static void addLocation(BundleContext context, String filter, Map<String, Location> locations) throws InvalidSyntaxException {
Collection<ServiceReference<Location>> locationRefs = context.getServiceReferences(Location.class, filter);
if (!locationRefs.isEmpty()) {
locations.put(filter, context.getService(locationRefs.iterator().next()));
}
}
public void testSchemes() throws Exception {
Map<String, String> fwkConfig = new HashMap<>();
fwkConfig.put(EquinoxLocations.PROP_CONFIG_AREA + EquinoxLocations.READ_ONLY_AREA_SUFFIX, "true");
fwkConfig.put(EquinoxLocations.PROP_USER_AREA, "http://example.com/a");
fwkConfig.put(EquinoxLocations.PROP_INSTANCE_AREA, "ftp://example.com/c/d");
fwkConfig.put(EquinoxLocations.PROP_CONFIG_AREA, "platform:/base/e/f");
fwkConfig.put(EquinoxLocations.PROP_INSTALL_AREA, "file:" + prefix + "/g");
Equinox equinox = new Equinox(fwkConfig);
equinox.init();
try {
Map<String, Location> locations = getLocations(equinox);
checkSlashes(locations);
checkLocation(locations.get(Location.USER_FILTER), true, true, "http");
checkLocation(locations.get(Location.INSTANCE_FILTER), true, true, "ftp");
checkLocation(locations.get(Location.CONFIGURATION_FILTER), true, true, "platform");
checkLocation(locations.get(Location.INSTALL_FILTER), true, true, "file");
} finally {
equinox.stop();
}
}
public void testNone() throws Exception {
Map<String, String> fwkConfig = new HashMap<>();
fwkConfig.put(EquinoxLocations.PROP_CONFIG_AREA + EquinoxLocations.READ_ONLY_AREA_SUFFIX, "true");
fwkConfig.put(EquinoxLocations.PROP_USER_AREA, "@none");
fwkConfig.put(EquinoxLocations.PROP_INSTANCE_AREA, "@none");
// TODO framework does not handle no config area well
// fwkConfig.put(EquinoxLocations.PROP_CONFIG_AREA, "@none");
fwkConfig.put(EquinoxLocations.PROP_INSTALL_AREA, "file:" + prefix + "/g");
Equinox equinox = new Equinox(fwkConfig);
equinox.init();
try {
Map<String, Location> locations = getLocations(equinox);
assertNull("User location should be null", locations.get(Location.USER_FILTER));
assertNull("Instance location should be null", locations.get(Location.INSTANCE_FILTER));
// TODO assertNull("Configuration location should be null", locations.get(Location.CONFIGURATION_FILTER));
} finally {
equinox.stop();
}
}
public void testNoDefault() throws Exception {
Map<String, String> fwkConfig = new HashMap<>();
fwkConfig.put(EquinoxLocations.PROP_CONFIG_AREA + EquinoxLocations.READ_ONLY_AREA_SUFFIX, "true");
fwkConfig.put(EquinoxLocations.PROP_INSTALL_AREA, "file:" + prefix + "/g");
fwkConfig.put(EquinoxLocations.PROP_INSTANCE_AREA, "@noDefault");
fwkConfig.put(EquinoxLocations.PROP_USER_AREA, "@noDefault");
Equinox equinox = new Equinox(fwkConfig);
equinox.init();
try {
Map<String, Location> locations = getLocations(equinox);
Location userLocation = locations.get(Location.USER_FILTER);
Location instanceLocation = locations.get(Location.INSTANCE_FILTER);
assertNull("User locatoin is not null.", userLocation.getURL());
assertNull("Instance location is not null.", instanceLocation.getURL());
} finally {
equinox.stop();
}
}
public void testUserDir() throws Exception {
Map<String, String> fwkConfig = new HashMap<>();
fwkConfig.put(EquinoxLocations.PROP_USER_AREA, "@user.dir");
fwkConfig.put(EquinoxLocations.PROP_CONFIG_AREA + EquinoxLocations.READ_ONLY_AREA_SUFFIX, "true");
fwkConfig.put(EquinoxLocations.PROP_INSTANCE_AREA, "@user.dir");
fwkConfig.put(EquinoxLocations.PROP_CONFIG_AREA, "@user.dir");
fwkConfig.put(EquinoxLocations.PROP_INSTALL_AREA, "file:" + prefix + "/g");
Equinox equinox = new Equinox(fwkConfig);
equinox.init();
try {
Map<String, Location> locations = getLocations(equinox);
checkLocation(locations.get(Location.USER_FILTER), true, true, "file");
checkLocation(locations.get(Location.INSTANCE_FILTER), true, true, "file");
checkLocation(locations.get(Location.CONFIGURATION_FILTER), true, true, "file");
checkLocation(locations.get(Location.INSTALL_FILTER), true, true, "file");
} finally {
equinox.stop();
}
}
public void testUserHome() throws Exception {
Map<String, String> fwkConfig = new HashMap<>();
fwkConfig.put(EquinoxLocations.PROP_CONFIG_AREA + EquinoxLocations.READ_ONLY_AREA_SUFFIX, "true");
fwkConfig.put(EquinoxLocations.PROP_USER_AREA, "@user.home");
fwkConfig.put(EquinoxLocations.PROP_INSTANCE_AREA, "@user.home");
fwkConfig.put(EquinoxLocations.PROP_CONFIG_AREA, "@user.home");
fwkConfig.put(EquinoxLocations.PROP_INSTALL_AREA, "file:" + prefix + "/g");
Equinox equinox = new Equinox(fwkConfig);
equinox.init();
try {
Map<String, Location> locations = getLocations(equinox);
checkLocation(locations.get(Location.USER_FILTER), true, true, "file");
checkLocation(locations.get(Location.INSTANCE_FILTER), true, true, "file");
checkLocation(locations.get(Location.CONFIGURATION_FILTER), true, true, "file");
checkLocation(locations.get(Location.INSTALL_FILTER), true, true, "file");
} finally {
equinox.stop();
}
}
public void testUNC() throws Exception {
if (!windows)
return;
Map<String, String> fwkConfig = new HashMap<>();
fwkConfig.put(EquinoxLocations.PROP_CONFIG_AREA + EquinoxLocations.READ_ONLY_AREA_SUFFIX, "true");
fwkConfig.put(EquinoxLocations.PROP_USER_AREA, "//server/share/a");
fwkConfig.put(EquinoxLocations.PROP_INSTANCE_AREA, "//server/share/b");
fwkConfig.put(EquinoxLocations.PROP_CONFIG_AREA, "//server/share/c");
fwkConfig.put(EquinoxLocations.PROP_INSTALL_AREA, "file://server/share/g");
Equinox equinox = new Equinox(fwkConfig);
equinox.init();
try {
Map<String, Location> locations = getLocations(equinox);
checkLocation(locations.get(Location.USER_FILTER), true, true, "file");
checkLocation(locations.get(Location.INSTANCE_FILTER), true, true, "file");
checkLocation(locations.get(Location.CONFIGURATION_FILTER), true, true, "file");
checkLocation(locations.get(Location.INSTALL_FILTER), true, true, "file");
} finally {
equinox.stop();
}
}
public void testDebugLogOnGetURL() throws Exception {
Properties debugOptions = new Properties();
debugOptions.put("org.eclipse.osgi/debug/location", "true");
File debugOptionsFile = OSGiTestsActivator.getContext().getDataFile(getName() + ".options");
debugOptions.store(new FileOutputStream(debugOptionsFile), getName());
Map<String, String> fwkConfig = new HashMap<>();
fwkConfig.put(EquinoxLocations.PROP_CONFIG_AREA + EquinoxLocations.READ_ONLY_AREA_SUFFIX, "true");
fwkConfig.put(EquinoxLocations.PROP_INSTALL_AREA, "file:" + prefix + "/g");
fwkConfig.put(EquinoxConfiguration.PROP_DEBUG, debugOptionsFile.getAbsolutePath());
fwkConfig.put("eclipse.consoleLog", "true");
Equinox equinox = new Equinox(fwkConfig);
equinox.init();
try {
final List<LogEntry> logEntries = new ArrayList<>();
LogReaderService logReaderService = getLogReaderService(equinox);
SynchronousLogListener logListener = entry -> logEntries.add(entry);
logReaderService.addLogListener(logListener);
Map<String, Location> locations = getLocations(equinox);
Location userLocation = locations.get(Location.USER_FILTER);
Location instanceLocation = locations.get(Location.INSTANCE_FILTER);
assertNotNull("User locatoin is not null.", userLocation.getURL());
assertNotNull("Instance location is not null.", instanceLocation.getURL());
assertEquals("Wrong number of log entries", 2, logEntries.size());
} finally {
equinox.stop();
}
}
private LogReaderService getLogReaderService(Equinox equinox) {
return equinox.getBundleContext().getService(equinox.getBundleContext().getServiceReference(LogReaderService.class));
}
}