blob: 8fecc9980ee3ef5695645bc2214368b2af830c6e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2013, 2020 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.bundles;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Map;
import java.util.jar.Attributes;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.eclipse.osgi.launch.Equinox;
import org.eclipse.osgi.tests.OSGiTestsActivator;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
/*
* The framework must discard a persisted bundle when the
* osgi.checkConfiguration configuration property is specified and equal to
* true.
*
* On a related note, if the osgi.dev configuration property is specified but
* the osgi.checkConfiguration configuration property is not specified, the
* framework must specify the osgi.checkConfiguration configuration property
* with a value equal to true.
*/
public class DiscardBundleTests extends AbstractBundleTests {
private static final String BUNDLE_DIR = "discardable";
private static final String BUNDLE_JAR = BUNDLE_DIR + ".jar";
private static final String BUNDLE_MANIFEST = "META-INF/MANIFEST.MF";
private static final String OSGI_DEV = "osgi.dev";
private static final String OSGI_CHECKCONFIGURATION = "osgi.checkConfiguration";
private static final String REFERENCE_PROTOCOL = "reference:";
private File root;
@Override
protected void setUp() throws Exception {
super.setUp();
root = OSGiTestsActivator.getContext().getDataFile(getName());
createBundleDirectory();
createBundleJar();
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
}
public static Test suite() {
return new TestSuite(DiscardBundleTests.class);
}
public void testDiscardOsgiCheckConfigurationTrueOsgiDevSpecified() throws Exception {
Map<String, Object> configuration = createConfiguration();
configuration.put(OSGI_CHECKCONFIGURATION, Boolean.TRUE.toString());
configuration.put(OSGI_DEV, "");
doTest(configuration, true);
}
public void testDiscardOsgiCheckConfigurationTrueOsgiDevUnspecified() throws Exception {
Map<String, Object> configuration = createConfiguration();
configuration.put(OSGI_CHECKCONFIGURATION, Boolean.TRUE.toString());
doTest(configuration, true);
}
public void testDiscardOsgiCheckConfigurationUnspecifiedOsgiDevSpecified() throws Exception {
Map<String, Object> configuration = createConfiguration();
configuration.put(OSGI_DEV, "");
doTest(configuration, true);
}
public void testNoDiscardOsgiCheckConfigurationFalseOsgiDevSpecified() throws Exception {
Map<String, Object> configuration = createConfiguration();
configuration.put(OSGI_CHECKCONFIGURATION, Boolean.FALSE.toString());
configuration.put(OSGI_DEV, "");
doTest(configuration, false);
}
public void testNoDiscardOsgiCheckConfigurationFalseOsgiDevUnspecified() throws Exception {
Map<String, Object> configuration = createConfiguration();
configuration.put(OSGI_CHECKCONFIGURATION, Boolean.FALSE.toString());
doTest(configuration, false);
}
public void testNoDiscardOsgiCheckConfigurationUnspecifiedOsgiDevUnspecified() throws Exception {
doTest(createConfiguration(), false);
}
public void testDiscardDeletedBundleFile() throws Exception {
doTestDiscardDeletedBundleFile(getDirectoryLocation());
doTestDiscardDeletedBundleFile(getJarLocation());
}
private void doTestDiscardDeletedBundleFile(File bundleFile) throws Exception {
Map<String, Object> configuration = createConfiguration();
Equinox equinox = new Equinox(configuration);
initAndStart(equinox);
try {
String location = REFERENCE_PROTOCOL + bundleFile.toURI();
equinox.getBundleContext().installBundle(location);
equinox = restart(equinox, configuration);
assertNotDiscarded(location, equinox);
// Attempting to delete the file with equinox still running
// will sometimes result in failure presumably due to a locked
// file.
stop(equinox);
rm(bundleFile);
equinox = restart(equinox, configuration);
assertDiscarded(location, equinox);
} finally {
stopQuietly(equinox);
}
}
private void assertDiscarded(String location, Equinox equinox) {
assertNull("The bundle was not discarded", equinox.getBundleContext().getBundle(location));
}
private void assertNotDiscarded(String location, Equinox equinox) {
assertNotNull("The bundle was discarded", equinox.getBundleContext().getBundle(location));
}
private void createBundleDirectory() throws IOException {
File file = new File(root, BUNDLE_DIR + '/' + BUNDLE_MANIFEST);
assertTrue("Could not make directories", file.getParentFile().mkdirs());
Manifest manifest = createBundleManifest();
FileOutputStream fos = new FileOutputStream(file);
try {
manifest.write(fos);
} finally {
fos.close();
}
}
private void createBundleJar() throws IOException {
Manifest manifest = createBundleManifest();
JarOutputStream target = new JarOutputStream(new FileOutputStream(new File(root, BUNDLE_JAR)), manifest);
target.close();
}
private Manifest createBundleManifest() {
Manifest manifest = new Manifest();
manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
manifest.getMainAttributes().putValue(Constants.BUNDLE_SYMBOLICNAME, BUNDLE_DIR);
return manifest;
}
private void doTest(Map<String, ?> configuration, boolean discard) throws Exception {
doTest(configuration, discard, getDirectoryLocation());
doTest(configuration, discard, getJarLocation());
}
private void doTest(Map<String, ?> configuration, boolean discard, File bundleFile) throws Exception {
Equinox equinox = new Equinox(configuration);
initAndStart(equinox);
try {
String location = REFERENCE_PROTOCOL + bundleFile.toURI();
equinox.getBundleContext().installBundle(location);
try {
equinox = restart(equinox, configuration);
assertNotDiscarded(location, equinox);
// Attempting to touch the file with equinox still running
// will sometimes result in failure presumably due to a locked
// file.
stop(equinox);
touchFile(bundleFile);
equinox = restart(equinox, configuration);
if (discard)
assertDiscarded(location, equinox);
else
assertNotDiscarded(location, equinox);
} finally {
try {
equinox.getBundleContext().getBundle(location).uninstall();
} catch (Exception e) {
// Ignore
}
}
} finally {
stopQuietly(equinox);
}
}
private File getDirectoryLocation() {
return new File(root, BUNDLE_DIR);
}
private File getJarLocation() {
return new File(root, BUNDLE_JAR);
}
private Equinox restart(Equinox equinox, Map<String, ?> configuration) throws BundleException {
stop(equinox);
equinox = new Equinox(configuration);
initAndStart(equinox);
return equinox;
}
private void touchFile(File file) {
if (file.isDirectory())
file = new File(file, BUNDLE_MANIFEST);
assertTrue("Could not set last modified: " + file, file.setLastModified(file.lastModified() + 1000));
}
public static boolean rm(File file) {
if (file.exists()) {
if (file.isDirectory()) {
String list[] = file.list();
if (list != null) {
int len = list.length;
for (int i = 0; i < len; i++) {
rm(new File(file, list[i]));
}
}
}
return file.delete();
}
return (true);
}
}