blob: 734637b4d30a559f78f7bee923f0c7afedb9c892 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.struts2.osgi.host;
import com.opensymphony.xwork2.config.ConfigurationException;
import java.util.Map;
import junit.framework.TestCase;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.config.Configurator;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.springframework.mock.web.MockServletContext;
public class FelixOsgiHostTest extends TestCase {
private static final Logger LOG = LogManager.getLogger(FelixOsgiHostTest.class);
private FelixOsgiHost felixHost;
private MockServletContext servletContext;
@Override
protected void setUp() throws Exception {
super.setUp();
// Use non-public API to explicitly set Log4j2 logging levels for the test.
Configurator.setRootLevel(Level.INFO);
Configurator.setLevel("org.apache.felix.framework.Felix.", Level.INFO);
Configurator.setLevel("org.apache.struts2.osgi.host.BaseOsgiHost", Level.INFO);
Configurator.setLevel("org.apache.struts2.osgi.host.FelixOsgiHost", Level.INFO);
// Set up mock ServletContext for Felix OSGi testing.
servletContext = new MockServletContext();
servletContext.setInitParameter("struts.osgi.clearBundleCache", "true"); // Same as default (true).
servletContext.setInitParameter("struts.osgi.felixCacheLocking", "true"); // Same as default (true). If testing a start-after-init, value must be false (otherwise the second start fails).
servletContext.setInitParameter("struts.osgi.runLevel", "0"); // Different from default (3). Setting to run level above 0 causes error complaints in the Felix initialization for the unit test.
servletContext.setInitParameter("struts.osgi.logLevel", "3"); // INFO instead of default (1) for ERROR.
servletContext.setInitParameter("struts.osgi.searchForPropertiesFilesInRelativePath", "true"); // Different from default (false). Must be true for unit tests.
servletContext.setInitParameter("struts.osgi.felixPropertiesPath", "default.properties"); // Same as default.
servletContext.setInitParameter("struts.osgi.strutsOSGiPropertiesPath", "struts-osgi.properties"); // Same as default.
felixHost = new FelixOsgiHost();
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
try {
felixHost.destroy();
} catch (Exception ex) {
// Nothing to be done if destruction fails.
}
}
public void testGetVersionFromString() {
assertEquals("2.1.1", felixHost.getVersionFromString("2.1.1-SNAPSHOT"));
assertEquals("2.1.1", felixHost.getVersionFromString("2.1.1.SNAPSHOT"));
assertEquals("2.1.1", felixHost.getVersionFromString("something-2.1.1.SNAPSHOT"));
assertEquals("2.1.1", felixHost.getVersionFromString("something-2-1-1.SNAPSHOT"));
assertEquals("2.1.0", felixHost.getVersionFromString("something-2-1.SNAPSHOT"));
assertEquals("2.0.0", felixHost.getVersionFromString("something-2.SNAPSHOT"));
assertEquals("1.0.0", felixHost.getVersionFromString("something"));
}
public void testInitAndDestroy() {
try {
// Calling init will call start as part of the flow. Calling startFelix() afterwards
// will produce errors, unless destroy has been called first
felixHost.init(servletContext);
} catch (Exception ex) {
if (ex instanceof RuntimeException && ex.getMessage().contains("Unable to create cache directory.")) {
LOG.warn("Felix cache directory could not be created (possible environment issue). Skipping rest of the test. Exception message: [{}]", ex.getMessage());
return; // Prevent Struts build from failing due to inability to create Felix cache directory.
} else if (ex instanceof ConfigurationException && ex.getCause() instanceof BundleException && ex.getCause().getMessage().contains("Error creating bundle cache.")) {
LOG.warn("Felix cache directory could not be populated (possible environment issue). Skipping rest of the test. Exception message: [{}], Cause message: [{}]", ex.getMessage(), ex.getCause().getMessage());
return; // Prevent Struts build from failing due to inability to create bundles within the Felix cache directory.
}
fail("Unable to initialize Felix OSGi container. Exception: " + ex );
}
try {
felixHost.destroy();
} catch (Exception ex) {
fail("Unable to destroy Felix OSGi container after init. Exception: " + ex );
}
// Test to confirm a Felix restart is possible (with cache locking true), using the previously initialized values.
try {
felixHost.startFelix();
} catch (Exception ex) {
fail("Unable to start Felix OSGi container after destroy. Exception: " + ex );
}
try {
felixHost.destroy();
} catch (Exception ex) {
fail("Unable to destroy Felix OSGi container after start. Exception: " + ex );
}
}
public void testGetBundles() {
try {
Map<String, Bundle> bundles = felixHost.getBundles();
fail("Expected an IllegalStateException since Felix was never initialized or started");
} catch (IllegalStateException isex) {
// Expected state
} catch (Exception ex) {
fail("Unable to get Felix bundles. Exception: " + ex );
}
try {
felixHost.init(servletContext);
Map<String, Bundle> bundles = felixHost.getBundles();
assertNotNull("Bundles is null ?", bundles);
assertFalse("Bundles is empty ?", bundles.isEmpty());
LOG.info("OSGi Bundles: " + bundles.toString());
} catch (Exception ex) {
if (ex instanceof RuntimeException && ex.getMessage().contains("Unable to create cache directory.")) {
LOG.warn("Felix cache directory could not be created (possible environment issue). Skipping rest of the test. Exception message: [{}]", ex.getMessage());
return; // Prevent Struts build from failing due to inability to create Felix cache directory.
} else if (ex instanceof ConfigurationException && ex.getCause() instanceof BundleException && ex.getCause().getMessage().contains("Error creating bundle cache.")) {
LOG.warn("Felix cache directory could not be populated (possible environment issue). Skipping rest of the test. Exception message: [{}], Cause message: [{}]", ex.getMessage(), ex.getCause().getMessage());
return; // Prevent Struts build from failing due to inability to create bundles within the Felix cache directory.
}
fail("Unable to get Felix bundles. Exception: " + ex );
} finally {
try {
felixHost.destroy();
} catch (Exception ex) {
// Nothing to be done if destruction fails.
}
}
}
public void testGetActiveBundles() {
try {
Map<String, Bundle> bundles = felixHost.getActiveBundles();
fail("Expected an IllegalStateException since Felix was never initialized or started");
} catch (IllegalStateException isex) {
// Expected state
} catch (Exception ex) {
fail("Unable to get Felix active bundles. Exception: " + ex );
}
try {
felixHost.init(servletContext);
Map<String, Bundle> bundles = felixHost.getActiveBundles();
assertNotNull("Bundles is null ?", bundles);
assertFalse("Bundles is empty ?", bundles.isEmpty());
LOG.info("OSGi Active Bundles: " + bundles.toString());
} catch (Exception ex) {
if (ex instanceof RuntimeException && ex.getMessage().contains("Unable to create cache directory.")) {
LOG.warn("Felix cache directory could not be created (possible environment issue). Skipping rest of the test. Exception message: [{}]", ex.getMessage());
return; // Prevent Struts build from failing due to inability to create Felix cache directory.
} else if (ex instanceof ConfigurationException && ex.getCause() instanceof BundleException && ex.getCause().getMessage().contains("Error creating bundle cache.")) {
LOG.warn("Felix cache directory could not be populated (possible environment issue). Skipping rest of the test. Exception message: [{}], Cause message: [{}]", ex.getMessage(), ex.getCause().getMessage());
return; // Prevent Struts build from failing due to inability to create bundles within the Felix cache directory.
}
fail("Unable to get Felix active bundles. Exception: " + ex );
} finally {
try {
felixHost.destroy();
} catch (Exception ex) {
// Nothing to be done if destruction fails.
}
}
}
public void testGetBundleContext() {
try {
BundleContext bundleContext = felixHost.getBundleContext();
fail("Expected an IllegalStateException since Felix was never initialized or started");
} catch (IllegalStateException isex) {
// Expected state
} catch (Exception ex) {
fail("Unable to get Felix bundle context. Exception: " + ex );
}
try {
felixHost.init(servletContext);
BundleContext bundleContext = felixHost.getBundleContext();
assertNotNull("Bundle context is null ?", bundleContext);
} catch (Exception ex) {
if (ex instanceof RuntimeException && ex.getMessage().contains("Unable to create cache directory.")) {
LOG.warn("Felix cache directory could not be created (possible environment issue). Skipping rest of the test. Exception message: [{}]", ex.getMessage());
return; // Prevent Struts build from failing due to inability to create Felix cache directory.
} else if (ex instanceof ConfigurationException && ex.getCause() instanceof BundleException && ex.getCause().getMessage().contains("Error creating bundle cache.")) {
LOG.warn("Felix cache directory could not be populated (possible environment issue). Skipping rest of the test. Exception message: [{}], Cause message: [{}]", ex.getMessage(), ex.getCause().getMessage());
return; // Prevent Struts build from failing due to inability to create bundles within the Felix cache directory.
}
fail("Unable to get Felix bundle context. Exception: " + ex );
} finally {
try {
felixHost.destroy();
} catch (Exception ex) {
// Nothing to be done if destruction fails.
}
}
}
}