/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.portal.configuration.extender.internal.test;
import com.liferay.arquillian.deploymentscenario.annotations.BndFile;
import com.liferay.portal.configuration.extender.ConfigurationDescription;
import com.liferay.portal.configuration.extender.ConfigurationDescriptionFactory;
import com.liferay.portal.configuration.extender.FactoryConfigurationDescription;
import com.liferay.portal.configuration.extender.NamedConfigurationContent;
import com.liferay.portal.configuration.extender.SingleConfigurationDescription;
import com.liferay.portal.configuration.extender.internal.ConfiguratorExtension;
import com.liferay.portal.kernel.util.PropertiesUtil;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.Supplier;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Dictionary;
import java.util.Hashtable;
import org.apache.felix.utils.log.Logger;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.arquillian.test.api.ArquillianResource;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.osgi.framework.BundleContext;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
/**
* @author Carlos Sierra Andrés
*/
@BndFile("test-bnd.bnd")
@RunWith(Arquillian.class)
public class ConfiguratorExtensionTest {
@Before
public void setUp() throws InvalidSyntaxException, IOException {
_serviceReference = _bundleContext.getServiceReference(
ConfigurationAdmin.class);
_configurationAdmin = _bundleContext.getService(_serviceReference);
Configuration[] configurations = _configurationAdmin.listConfigurations(
null);
if (configurations != null) {
for (Configuration configuration : configurations) {
configuration.delete();
}
}
configurations = _configurationAdmin.listConfigurations(null);
Assert.assertNull(configurations);
}
@After
public void tearDown() throws Exception {
for (ConfiguratorExtension configurationExtension :
_configurationExtensions) {
configurationExtension.destroy();
}
_bundleContext.ungetService(_serviceReference);
}
@Test
public void testExceptionInSupplierDoesNotStopExtension() throws Exception {
ConfiguratorExtension configuratorExtension = new ConfiguratorExtension(
_configurationAdmin, new Logger(_bundleContext), "aBundle",
Arrays.<NamedConfigurationContent>asList(
new StringSingleNamedConfigurationContent(
"test.pid", "key=value")),
Arrays.asList(
new ConfigurationDescriptionFactory() {
@Override
public ConfigurationDescription create(
NamedConfigurationContent namedConfigurationContent) {
return new SingleConfigurationDescription(
"exception",
new Supplier<Dictionary<String, Object>>() {
@Override
public Dictionary<String, Object> get() {
throw new RuntimeException(
"This should be handled");
}
});
}
},
new StringConfigurationDescriptionFactory()));
configuratorExtension.start();
_configurationExtensions.add(configuratorExtension);
Configuration[] configurations = _configurationAdmin.listConfigurations(
null);
Assert.assertEquals(
Arrays.toString(configurations), 1, configurations.length);
}
@Test
public void testFactoryConfiguration() throws Exception {
_startExtension(
"aBundle",
new StringFactoryNamedConfigurationContent(
"test.factory.pid", "default", "key=value"));
Configuration[] configurations = _configurationAdmin.listConfigurations(
null);
Assert.assertEquals(
Arrays.toString(configurations), 1, configurations.length);
}
@Test
public void testFactoryConfigurationCreatesAnother() throws Exception {
Configuration configuration =
_configurationAdmin.createFactoryConfiguration(
"test.factory.pid", StringPool.QUESTION);
configuration.update(
new Hashtable<String, Object>() {
{
put("key", "value");
}
});
_startExtension(
"aBundle",
new StringFactoryNamedConfigurationContent(
"test.factory.pid", "default", "key=value2"));
Configuration[] configurations = _configurationAdmin.listConfigurations(
null);
Assert.assertEquals(
Arrays.toString(configurations), 2, configurations.length);
Assert.assertNotNull(
_configurationAdmin.listConfigurations("(key=value)"));
Assert.assertNotNull(
_configurationAdmin.listConfigurations("(key=value2)"));
}
@Test
public void testFactoryConfigurationWithClashingFactoryPid()
throws Exception {
_startExtension(
"aBundle",
new StringFactoryNamedConfigurationContent(
"test.factory.pid", "default", "key=value"),
new StringFactoryNamedConfigurationContent(
"test.factory.pid", "default2", "key=value"));
Configuration[] configurations = _configurationAdmin.listConfigurations(
null);
Assert.assertEquals(
Arrays.toString(configurations), 2, configurations.length);
}
@Test
public void testFactoryConfigurationWithClashingMultipleContents()
throws Exception {
_startExtension(
"aBundle",
new StringFactoryNamedConfigurationContent(
"test.factory.pid", "default", "key=value"),
new StringFactoryNamedConfigurationContent(
"test.factory.pid", "default", "key=value2"));
Configuration[] configurations = _configurationAdmin.listConfigurations(
null);
Assert.assertEquals(
Arrays.toString(configurations), 1, configurations.length);
Dictionary<String, Object> properties =
configurations[0].getProperties();
Assert.assertEquals("value", properties.get("key"));
}
@Test
public void testFactoryConfigurationWithClashingMultipleContentsAndDifferentNamespaces()
throws Exception {
_startExtension(
"aBundle",
new StringFactoryNamedConfigurationContent(
"test.factory.pid", "default", "key=value"));
_startExtension(
"otherBundle",
new StringFactoryNamedConfigurationContent(
"test.factory.pid", "default", "key=value"));
Configuration[] configurations = _configurationAdmin.listConfigurations(
null);
Assert.assertEquals(
Arrays.toString(configurations), 2, configurations.length);
}
@Test
public void testSingleConfiguration() throws Exception {
_startExtension(
"aBundle",
new StringSingleNamedConfigurationContent("test.pid", "key=value"));
Configuration[] configurations = _configurationAdmin.listConfigurations(
null);
Assert.assertEquals(
Arrays.toString(configurations), 1, configurations.length);
}
@Test
public void testSingleConfigurationRespectsExistingConfiguration()
throws Exception {
Configuration configuration = _configurationAdmin.getConfiguration(
"test.pid", StringPool.QUESTION);
configuration.update(
new Hashtable<String, Object>() {
{
put("key", "value");
}
});
_startExtension(
"aBundle",
new StringSingleNamedConfigurationContent(
"test.pid", "key=value2"));
Configuration[] configurations = _configurationAdmin.listConfigurations(
null);
Assert.assertEquals(
Arrays.toString(configurations), 1, configurations.length);
Dictionary<String, Object> properties =
configurations[0].getProperties();
Assert.assertEquals("value", properties.get("key"));
}
@Test
public void testSingleConfigurationWithClashingMultipleContents()
throws Exception {
_startExtension(
"aBundle",
new StringSingleNamedConfigurationContent("test.pid", "key=value"),
new StringSingleNamedConfigurationContent(
"test.pid", "key=value2"));
Configuration[] configurations = _configurationAdmin.listConfigurations(
null);
Assert.assertEquals(
Arrays.toString(configurations), 1, configurations.length);
Dictionary<String, Object> properties =
configurations[0].getProperties();
Assert.assertEquals("value", properties.get("key"));
}
@Test
public void testSingleConfigurationWithClashingMultipleContentsAndDifferentNamespaces()
throws Exception {
_startExtension(
"aBundle",
new StringSingleNamedConfigurationContent("test.pid", "key=value"));
_startExtension(
"otherBundle",
new StringSingleNamedConfigurationContent(
"test.pid", "key=value2"));
Configuration[] configurations = _configurationAdmin.listConfigurations(
null);
Assert.assertEquals(
Arrays.toString(configurations), 1, configurations.length);
Dictionary<String, Object> properties =
configurations[0].getProperties();
Assert.assertEquals("value", properties.get("key"));
}
@Test
public void testSingleConfigurationWithMultipleContents() throws Exception {
_startExtension(
"aBundle",
new StringSingleNamedConfigurationContent("test.pid", "key=value"),
new StringSingleNamedConfigurationContent(
"test.pid2", "key=value"));
Configuration[] configurations = _configurationAdmin.listConfigurations(
null);
Assert.assertEquals(
Arrays.toString(configurations), 2, configurations.length);
}
private void _startExtension(
String namespace,
NamedConfigurationContent... namedConfigurationContents)
throws Exception {
ConfiguratorExtension configuratorExtension = new ConfiguratorExtension(
_configurationAdmin, new Logger(_bundleContext), namespace,
Arrays.asList(namedConfigurationContents),
Arrays.<ConfigurationDescriptionFactory>asList(
new StringConfigurationDescriptionFactory()));
configuratorExtension.start();
_configurationExtensions.add(configuratorExtension);
}
@ArquillianResource
private BundleContext _bundleContext;
private ConfigurationAdmin _configurationAdmin;
private final Collection<ConfiguratorExtension> _configurationExtensions =
new ArrayList<>();
private ServiceReference<ConfigurationAdmin> _serviceReference;
private static class StringConfigurationDescriptionFactory
implements ConfigurationDescriptionFactory {
@Override
public ConfigurationDescription create(
NamedConfigurationContent namedConfigurationContent) {
if (namedConfigurationContent instanceof
StringSingleNamedConfigurationContent) {
final StringSingleNamedConfigurationContent ssncc =
(StringSingleNamedConfigurationContent)
namedConfigurationContent;
return new SingleConfigurationDescription(
ssncc._pid,
new Supplier<Dictionary<String, Object>>() {
@Override
public Dictionary<String, Object> get() {
try {
Dictionary<?, ?> properties =
PropertiesUtil.load(
ssncc.getInputStream(), "UTF-8");
return (Dictionary<String, Object>)properties;
}
catch (IOException ioe) {
throw new RuntimeException(ioe);
}
}
});
}
else {
final StringFactoryNamedConfigurationContent sfncc =
(StringFactoryNamedConfigurationContent)
namedConfigurationContent;
return new FactoryConfigurationDescription(
sfncc._factoryPid, sfncc._pid,
new Supplier<Dictionary<String, Object>>() {
@Override
public Dictionary<String, Object> get() {
try {
Dictionary<?, ?> properties =
PropertiesUtil.load(
sfncc.getInputStream(), "UTF-8");
return (Dictionary<String, Object>)properties;
}
catch (IOException ioe) {
throw new RuntimeException(ioe);
}
}
});
}
}
}
private static class StringFactoryNamedConfigurationContent
implements NamedConfigurationContent {
public StringFactoryNamedConfigurationContent(
String factoryPid, String pid, String content) {
_factoryPid = factoryPid;
_pid = pid;
_content = content;
}
@Override
public InputStream getInputStream() {
return new ByteArrayInputStream(
_content.getBytes(Charset.forName("UTF-8")));
}
@Override
public String getName() {
return _pid;
}
private final String _content;
private final String _factoryPid;
private final String _pid;
}
private static class StringSingleNamedConfigurationContent
implements NamedConfigurationContent {
public StringSingleNamedConfigurationContent(
String pid, String content) {
_pid = pid;
_content = content;
}
@Override
public InputStream getInputStream() {
return new ByteArrayInputStream(
_content.getBytes(Charset.forName("UTF-8")));
}
@Override
public String getName() {
return _pid;
}
private final String _content;
private final String _pid;
}
}