This is an automated email from the ASF dual-hosted git repository. kwin pushed a commit to branch feature/ds in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-settings.git
commit cea76f779987ef0d7f4ab627f217566a9436f2c1 Author: Konrad Windszus <[email protected]> AuthorDate: Tue Jun 30 20:38:23 2020 +0200 SLING-9561 switch to DS 1.4 and component properties --- bnd.bnd | 5 - pom.xml | 53 ++- .../org/apache/sling/settings/impl/Activator.java | 50 --- .../apache/sling/settings/impl/RunModeCommand.java | 37 +-- .../sling/settings/impl/ServicesListener.java | 262 --------------- .../settings/impl/SettingsServiceConfigurator.java | 58 ---- .../settings/impl/SlingPropertiesPrinter.java | 51 +-- .../sling/settings/impl/SlingSettingsPrinter.java | 38 +-- .../settings/impl/SlingSettingsServiceImpl.java | 234 +++++++------ .../resources/OSGI-INF/l10n/metatype.properties | 29 -- ...ling.settings.impl.SlingSettingsServiceImpl.xml | 28 -- .../sling/settings/impl/RunModeImplTest.java | 365 +++++++-------------- .../impl/SlingSettingsServiceImplTest.java | 10 +- 13 files changed, 308 insertions(+), 912 deletions(-) diff --git a/bnd.bnd b/bnd.bnd index 8c25158..03ccd6c 100644 --- a/bnd.bnd +++ b/bnd.bnd @@ -1,14 +1,9 @@ -Bundle-Activator: org.apache.sling.settings.impl.Activator - Bundle-DocURL: http://sling.apache.org/documentation/bundles/sling-settings-orgapacheslingsettings.html DynamicImport-Package:\ org.osgi.service.cm,\ org.apache.felix.shell -Provide-Capability:\ - osgi.service;objectClass=org.apache.sling.settings.SlingSettingsService - Import-Package:\ org.osgi.service.cm;resolution:=optional,\ org.apache.felix.shell;resolution:=optional,\ diff --git a/pom.xml b/pom.xml index ccd5970..ee21df2 100644 --- a/pom.xml +++ b/pom.xml @@ -1,30 +1,31 @@ <?xml version="1.0" encoding="ISO-8859-1"?> <!-- Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file + or more contributor license agreements. See the NOTICE file distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file + 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 - + 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 + KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.apache.sling</groupId> <artifactId>sling-bundle-parent</artifactId> <version>39</version> - <relativePath /> + <relativePath/> </parent> <artifactId>org.apache.sling.settings</artifactId> @@ -39,8 +40,8 @@ <connection>scm:git:https://gitbox.apache.org/repos/asf/sling-org-apache-sling-settings.git</connection> <developerConnection>scm:git:https://gitbox.apache.org/repos/asf/sling-org-apache-sling-settings.git</developerConnection> <url>https://gitbox.apache.org/repos/asf?p=sling-org-apache-sling-settings.git</url> - <tag>HEAD</tag> - </scm> + <tag>HEAD</tag> + </scm> <properties> <site.jira.version.id>12315254</site.jira.version.id> @@ -76,6 +77,23 @@ <artifactId>org.osgi.annotation.versioning</artifactId> <scope>provided</scope> </dependency> + <!-- https://osgi.org/javadoc/osgi.cmpn/7.0.0/org/osgi/service/component/annotations/package-frame.html --> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.service.component.annotations</artifactId> + <scope>provided</scope> + </dependency> + <!-- https://osgi.org/javadoc/osgi.cmpn/7.0.0/org/osgi/service/metatype/annotations/package-frame.html --> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.service.metatype.annotations</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.service.component</artifactId> + <scope>provided</scope> + </dependency> <dependency> <groupId>org.osgi</groupId> <artifactId>osgi.core</artifactId> @@ -83,7 +101,6 @@ <dependency> <groupId>org.osgi</groupId> <artifactId>org.osgi.service.cm</artifactId> - <version>1.5.0</version> <scope>provided</scope> </dependency> <dependency> @@ -96,7 +113,7 @@ <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> </dependency> - <!-- Testing --> + <!-- Testing --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> @@ -117,5 +134,17 @@ <version>1.10.19</version> <scope>test</scope> </dependency> + <dependency> + <groupId>org.apache.felix</groupId> + <artifactId>org.apache.felix.converter</artifactId> + <version>1.0.14</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.util.function</artifactId> + <version>1.0.0</version> + <scope>test</scope> + </dependency> </dependencies> </project> diff --git a/src/main/java/org/apache/sling/settings/impl/Activator.java b/src/main/java/org/apache/sling/settings/impl/Activator.java deleted file mode 100644 index 91781f2..0000000 --- a/src/main/java/org/apache/sling/settings/impl/Activator.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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.sling.settings.impl; - -import org.osgi.framework.BundleActivator; -import org.osgi.framework.BundleContext; - -/** - * This is the bundle activator. - * It registers the SlingSettingsService. - * - */ -public class Activator implements BundleActivator { - - /** The service listener */ - private ServicesListener servicesListener; - - /** - * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext) - */ - public void start(final BundleContext bundleContext) throws Exception { - this.servicesListener = new ServicesListener(bundleContext); - } - - /** - * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext) - */ - public void stop(final BundleContext context) throws Exception { - if ( this.servicesListener != null ) { - this.servicesListener.deactivate(); - this.servicesListener = null; - } - } -} diff --git a/src/main/java/org/apache/sling/settings/impl/RunModeCommand.java b/src/main/java/org/apache/sling/settings/impl/RunModeCommand.java index 06b0dd3..96bcd63 100644 --- a/src/main/java/org/apache/sling/settings/impl/RunModeCommand.java +++ b/src/main/java/org/apache/sling/settings/impl/RunModeCommand.java @@ -19,44 +19,38 @@ package org.apache.sling.settings.impl; import java.io.PrintStream; -import java.util.Dictionary; -import java.util.Hashtable; import java.util.Set; import org.apache.felix.shell.Command; +import org.apache.sling.settings.SlingSettingsService; import org.osgi.framework.BundleContext; -import org.osgi.framework.Constants; -import org.osgi.framework.ServiceRegistration; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; +import org.osgi.service.component.propertytypes.ServiceDescription; +import org.osgi.service.component.propertytypes.ServiceVendor; /** * Run mode command for the shell. */ +@Component +@ServiceVendor("The Apache Software Foundation") +@ServiceDescription("Apache Sling Sling Run Mode Shell Command") public class RunModeCommand implements Command { private static final String CMD_NAME = "runmodes"; - private final ServiceRegistration pluginReg; - private final Set<String> modes; - public RunModeCommand(final BundleContext btx, final Set<String> modes) { - this.modes = modes; - - final Dictionary<String, String> props = new Hashtable<String, String>(); - props.put(Constants.SERVICE_DESCRIPTION, - "Apache Sling Sling Run Mode Shell Command"); - props.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation"); - - pluginReg = btx.registerService(Command.class.getName(), this, props); - } - - public void destroy() { - pluginReg.unregister(); + @Activate + public RunModeCommand(final BundleContext btx, @Reference SlingSettingsService slingSettings) { + this.modes = slingSettings.getRunModes(); } /** * @see org.apache.felix.shell.Command#getName() */ + @Override public String getName() { return CMD_NAME; } @@ -64,6 +58,7 @@ public class RunModeCommand implements Command { /** * @see org.apache.felix.shell.Command#getShortDescription() */ + @Override public String getShortDescription() { return "lists current run modes"; } @@ -71,6 +66,7 @@ public class RunModeCommand implements Command { /** * @see org.apache.felix.shell.Command#getUsage() */ + @Override public String getUsage() { return CMD_NAME; } @@ -78,9 +74,10 @@ public class RunModeCommand implements Command { /** * @see org.apache.felix.shell.Command#execute(java.lang.String, java.io.PrintStream, java.io.PrintStream) */ + @Override public void execute(String command, PrintStream out, PrintStream err) { out.print("Current Run Modes: "); - if (modes == null || modes.size() == 0) { + if (modes == null || modes.isEmpty()) { out.println("-"); } else { out.println(modes); diff --git a/src/main/java/org/apache/sling/settings/impl/ServicesListener.java b/src/main/java/org/apache/sling/settings/impl/ServicesListener.java deleted file mode 100644 index 8ac0e96..0000000 --- a/src/main/java/org/apache/sling/settings/impl/ServicesListener.java +++ /dev/null @@ -1,262 +0,0 @@ -/* - * 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.sling.settings.impl; - -import java.util.Dictionary; -import java.util.Hashtable; - -import org.apache.sling.settings.SlingSettingsService; -import org.osgi.framework.BundleContext; -import org.osgi.framework.Constants; -import org.osgi.framework.InvalidSyntaxException; -import org.osgi.framework.ServiceEvent; -import org.osgi.framework.ServiceListener; -import org.osgi.framework.ServiceReference; -import org.osgi.framework.ServiceRegistration; - -/** - * The <code>ServicesListener</code> listens for the required services - * and registers the settings service once all required services are - * available - */ -public class ServicesListener { - - /** The bundle context. */ - private final BundleContext bundleContext; - - /** The listener for configuration admin. */ - private ConfigAdminListener configAdminListener; - - /** The listener for the shell. */ - private ShellListener shellListener; - - - /** The registration of the settings service. */ - private ServiceRegistration settingsReg; - - /** - * Start listeners - */ - public ServicesListener(final BundleContext bundleContext) { - this.bundleContext = bundleContext; - final SlingSettingsServiceImpl settingsService = new SlingSettingsServiceImpl(bundleContext); - - final Dictionary<String, String> props = new Hashtable<String, String>(); - props.put(Constants.SERVICE_DESCRIPTION, - "Apache Sling Settings Service"); - props.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation"); - this.settingsReg = bundleContext.registerService(new String[] { - SlingSettingsService.class.getName()}, - settingsService, props); - SlingPropertiesPrinter.initPlugin(bundleContext); - SlingSettingsPrinter.initPlugin(bundleContext, settingsService); - - // add config admin support - this.configAdminListener = new ConfigAdminListener(settingsService); - this.configAdminListener.start(); - - // add shell support - this.shellListener = new ShellListener(settingsService); - this.shellListener.start(); - } - - /** - * Deactivate this listener. - */ - public void deactivate() { - if ( this.shellListener != null ) { - this.shellListener.deactivate(); - this.shellListener = null; - } - if ( this.configAdminListener != null ) { - this.configAdminListener.deactivate(); - this.configAdminListener = null; - } - if ( this.settingsReg != null ) { - this.settingsReg.unregister(); - this.settingsReg = null; - } - - SlingSettingsPrinter.destroyPlugin(); - SlingPropertiesPrinter.destroyPlugin(); - } - - /** - * Helper class listening for service events for a defined service. - */ - private abstract class AbstractListener implements ServiceListener { - - /** The name of the service. */ - private final String serviceName; - - /** The service reference. */ - private volatile ServiceReference reference; - - /** The service. */ - private volatile Object service; - - /** - * Constructor - */ - public AbstractListener(final String serviceName) { - this.serviceName = serviceName; - } - - /** - * Start the listener. - * First register a service listener and then check for the service. - */ - public void start() { - try { - bundleContext.addServiceListener(this, "(" - + Constants.OBJECTCLASS + "=" + serviceName + ")"); - } catch (final InvalidSyntaxException ise) { - // this should really never happen - throw new RuntimeException("Unexpected exception occurred.", ise); - } - this.retainService(); - } - - /** - * Unregister the listener. - */ - public void deactivate() { - bundleContext.removeServiceListener(this); - } - - /** - * Return the service (if available) - */ - public synchronized Object getService() { - return this.service; - } - - /** - * Try to get the service and notify the change. - */ - private synchronized void retainService() { - if ( this.reference == null ) { - this.reference = bundleContext.getServiceReference(this.serviceName); - if ( this.reference != null ) { - this.service = bundleContext.getService(this.reference); - if ( this.service == null ) { - this.reference = null; - } else { - serviceChanged(); - } - } - } - } - - /** - * Try to release the service and notify the change. - */ - private synchronized void releaseService() { - if ( this.reference != null ) { - this.service = null; - bundleContext.ungetService(this.reference); - this.reference = null; - serviceChanged(); - } - } - - /** - * @see org.osgi.framework.ServiceListener#serviceChanged(org.osgi.framework.ServiceEvent) - */ - public void serviceChanged(ServiceEvent event) { - if (event.getType() == ServiceEvent.REGISTERED) { - this.retainService(); - } else if ( event.getType() == ServiceEvent.UNREGISTERING ) { - this.releaseService(); - } - } - - protected abstract void serviceChanged(); - } - - /** - * Helper class listening for service events for config admin - */ - private final class ConfigAdminListener extends AbstractListener { - - private Object settingsServiceConfigurator; - - private final SlingSettingsServiceImpl settings; - - /** - * Constructor - */ - public ConfigAdminListener(final SlingSettingsServiceImpl settings) { - super("org.osgi.service.cm.ConfigurationAdmin"); - this.settings = settings; - } - - @Override - protected void serviceChanged() { - if ( this.getService() != null && this.settingsServiceConfigurator == null ) { - this.settingsServiceConfigurator = new SettingsServiceConfigurator(bundleContext, settings); - } - } - - @Override - public void deactivate() { - super.deactivate(); - if ( settingsServiceConfigurator != null ) { - ((SettingsServiceConfigurator)settingsServiceConfigurator).destroy(); - settingsServiceConfigurator = null; - } - } - - } - - /** - * Helper class listening for service events for config admin - */ - private final class ShellListener extends AbstractListener { - - private Object runModeCommand; - - private final SlingSettingsServiceImpl settings; - - /** - * Constructor - */ - public ShellListener(final SlingSettingsServiceImpl settings) { - super("org.apache.felix.shell.ShellService"); - this.settings = settings; - } - - @Override - protected void serviceChanged() { - if ( this.getService() != null && this.runModeCommand == null ) { - this.runModeCommand = new RunModeCommand(bundleContext, settings.getRunModes()); - } - } - - @Override - public void deactivate() { - super.deactivate(); - if ( runModeCommand != null ) { - ((RunModeCommand)runModeCommand).destroy(); - runModeCommand = null; - } - } - - } -} diff --git a/src/main/java/org/apache/sling/settings/impl/SettingsServiceConfigurator.java b/src/main/java/org/apache/sling/settings/impl/SettingsServiceConfigurator.java deleted file mode 100644 index 85d0b54..0000000 --- a/src/main/java/org/apache/sling/settings/impl/SettingsServiceConfigurator.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * 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.sling.settings.impl; - -import java.util.Dictionary; -import java.util.Hashtable; - -import org.osgi.framework.BundleContext; -import org.osgi.framework.Constants; -import org.osgi.framework.ServiceRegistration; -import org.osgi.service.cm.ConfigurationException; -import org.osgi.service.cm.ManagedService; - -public class SettingsServiceConfigurator implements ManagedService { - - private final SlingSettingsServiceImpl settings; - - private final ServiceRegistration managedServiceReg; - - public SettingsServiceConfigurator(final BundleContext btx, - final SlingSettingsServiceImpl s) { - this.settings = s; - // setup manager service for configuration handling - final Dictionary<String, String> msProps = new Hashtable<String, String>(); - msProps.put(Constants.SERVICE_PID, s.getClass().getName()); - msProps.put(Constants.SERVICE_DESCRIPTION, - "Apache Sling Managed Service for the Settings Service"); - msProps.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation"); - managedServiceReg = btx.registerService(ManagedService.class.getName(), this, msProps); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - public void updated(final Dictionary properties) throws ConfigurationException { - if ( properties != null ) { - this.settings.update(properties); - } - } - - public void destroy() { - managedServiceReg.unregister(); - } -} diff --git a/src/main/java/org/apache/sling/settings/impl/SlingPropertiesPrinter.java b/src/main/java/org/apache/sling/settings/impl/SlingPropertiesPrinter.java index 6ad1bab..3864e05 100644 --- a/src/main/java/org/apache/sling/settings/impl/SlingPropertiesPrinter.java +++ b/src/main/java/org/apache/sling/settings/impl/SlingPropertiesPrinter.java @@ -23,39 +23,29 @@ import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.net.URL; -import java.util.Dictionary; -import java.util.Hashtable; import java.util.Iterator; import java.util.Properties; import java.util.SortedSet; import java.util.TreeSet; import org.osgi.framework.BundleContext; -import org.osgi.framework.Constants; -import org.osgi.framework.ServiceRegistration; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; /** * This is a configuration printer for the web console which * prints out the Sling properties from Launchpad if available. - * */ +@Component(service = SlingPropertiesPrinter.class, property= {"felix.webconsole.label=slingprops","felix.webconsole.title=Sling Properties","felix.webconsole.configprinter.modes=always"}) public class SlingPropertiesPrinter { - private static final Logger LOGGER = LoggerFactory.getLogger(SlingPropertiesPrinter.class); - - private static ServiceRegistration propertiesPlugin; - - public static void initPlugin(final BundleContext bundleContext) { + @Activate + public SlingPropertiesPrinter(BundleContext bundleContext) throws IOException { // if the properties are available, we register the sling properties plugin final String propUrl = bundleContext.getProperty("sling.properties.url"); if ( propUrl != null ) { // try to read properties - Properties props = null; - try { - final URL url = new URL(propUrl); - final InputStream is = url.openStream(); + try (final InputStream is = new URL(propUrl).openStream()) { final Properties tmp = new Properties(); tmp.load(is); // update props @@ -68,29 +58,10 @@ public class SlingPropertiesPrinter { props = tmp; } catch (IOException ioe) { - LOGGER.warn("Unable to read sling properties from " + propUrl, ioe); - } - if ( props != null ) { - final SlingPropertiesPrinter propertiesPrinter = new SlingPropertiesPrinter(props); - final Dictionary<String, String> serviceProps = new Hashtable<String, String>(); - serviceProps.put(Constants.SERVICE_DESCRIPTION, - "Apache Sling Sling Properties Configuration Printer"); - serviceProps.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation"); - serviceProps.put("felix.webconsole.label", "slingprops"); - serviceProps.put("felix.webconsole.title", "Sling Properties"); - serviceProps.put("felix.webconsole.configprinter.modes", "always"); - - propertiesPlugin = bundleContext.registerService(SlingPropertiesPrinter.class.getName(), - propertiesPrinter, - serviceProps); + throw new IOException("Unable to read sling properties from " + propUrl, ioe); } - } - } - - public static void destroyPlugin() { - if ( propertiesPlugin != null) { - propertiesPlugin.unregister(); - propertiesPlugin = null; + } else { + throw new IllegalStateException("No bundle context property 'sling.properties.url' provided"); } } @@ -98,10 +69,6 @@ public class SlingPropertiesPrinter { private final Properties props; - public SlingPropertiesPrinter(final Properties props) { - this.props = props; - } - /** * Print out the servlet filter chains. * @see org.apache.felix.webconsole.ConfigurationPrinter#printConfiguration(java.io.PrintWriter) diff --git a/src/main/java/org/apache/sling/settings/impl/SlingSettingsPrinter.java b/src/main/java/org/apache/sling/settings/impl/SlingSettingsPrinter.java index 0c1ad50..4999ff0 100644 --- a/src/main/java/org/apache/sling/settings/impl/SlingSettingsPrinter.java +++ b/src/main/java/org/apache/sling/settings/impl/SlingSettingsPrinter.java @@ -19,52 +19,26 @@ package org.apache.sling.settings.impl; import java.io.PrintWriter; -import java.util.Dictionary; -import java.util.Hashtable; import org.apache.sling.settings.SlingSettingsService; -import org.osgi.framework.BundleContext; -import org.osgi.framework.Constants; -import org.osgi.framework.ServiceRegistration; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; /** * This is a configuration printer for the web console which * prints out the sling settings. * */ +@Component(service = SlingSettingsPrinter.class, property= {"felix.webconsole.label=slingsettings","felix.webconsole.title=Sling Settings","felix.webconsole.configprinter.modes=always"}) public class SlingSettingsPrinter { - private static ServiceRegistration pluginReg; - - public static void initPlugin(final BundleContext bundleContext, - final SlingSettingsService service) { - final SlingSettingsPrinter printer = new SlingSettingsPrinter(service); - - final Dictionary<String, String> props = new Hashtable<String, String>(); - props.put(Constants.SERVICE_DESCRIPTION, - "Apache Sling Sling Settings Configuration Printer"); - props.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation"); - props.put("felix.webconsole.label", "slingsettings"); - props.put("felix.webconsole.title", "Sling Settings"); - props.put("felix.webconsole.configprinter.modes", "always"); - - pluginReg = bundleContext.registerService(SlingSettingsPrinter.class.getName(), - printer, - props); - } - - public static void destroyPlugin() { - if ( pluginReg != null) { - pluginReg.unregister(); - pluginReg = null; - } - } - private static String HEADLINE = "Apache Sling Settings"; private final SlingSettingsService settings; - public SlingSettingsPrinter(final SlingSettingsService settings) { + @Activate + public SlingSettingsPrinter(@Reference final SlingSettingsService settings) { this.settings = settings; } diff --git a/src/main/java/org/apache/sling/settings/impl/SlingSettingsServiceImpl.java b/src/main/java/org/apache/sling/settings/impl/SlingSettingsServiceImpl.java index 16ae4b3..95e2bf7 100644 --- a/src/main/java/org/apache/sling/settings/impl/SlingSettingsServiceImpl.java +++ b/src/main/java/org/apache/sling/settings/impl/SlingSettingsServiceImpl.java @@ -30,30 +30,31 @@ import java.net.URL; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -import java.util.Dictionary; -import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.regex.Pattern; import org.apache.sling.settings.SlingSettingsService; import org.osgi.framework.BundleContext; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Modified; +import org.osgi.service.component.propertytypes.ServiceDescription; +import org.osgi.service.component.propertytypes.ServiceVendor; +import org.osgi.service.metatype.annotations.AttributeDefinition; +import org.osgi.service.metatype.annotations.Designate; +import org.osgi.service.metatype.annotations.ObjectClassDefinition; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -/** - * This is the basic implementation of the sling settings service. - */ +/** This is the basic implementation of the sling settings service. */ +@Component +@Designate(ocd = SlingSettingsServiceImpl.Configuration.class) +@ServiceVendor("The Apache Software Foundation") +@ServiceDescription("Apache Sling Settings Service") public class SlingSettingsServiceImpl - implements SlingSettingsService { - - /** Property containing the sling name. */ - private static final String SLING_NAME = "sling.name"; - - /** Property containing the sling description. */ - private static final String SLING_DESCRIPTION = "sling.description"; + implements SlingSettingsService { /** The logger */ private final Logger logger = LoggerFactory.getLogger(this.getClass()); @@ -67,40 +68,51 @@ public class SlingSettingsServiceImpl /** The sling home url */ private URL slingHomeUrl; - /** The set of run modes .*/ + /** The set of run modes . */ private Set<String> runModes; + private Configuration configuration; + /** The name of the data file holding the sling id. */ private static final String ID_FILE = "sling.id.file"; /** The name of the data file holding install run mode options */ private static final String OPTIONS_FILE = "sling.options.file"; - /** The properties for name, description. */ - private final Map<String, String> slingProps = new HashMap<String, String>(); + @ObjectClassDefinition(id = "org.apache.sling.settings.impl.SlingSettingsServiceImpl", name = "Apache Sling Settings Service", + description = "The settings service manages some basic settings of Sling like run modes or information about the current instance.") + static @interface Configuration { + @AttributeDefinition(name = "Instance Name", description = "A human readable name for the current instance.") + String sling_name(); - /** - * Create the service and search the Sling home urls and - * get/create a sling id. - * Setup run modes - * @param context The bundle context - */ - public SlingSettingsServiceImpl(final BundleContext context) { - this.setupSlingProps(context); + @AttributeDefinition(name = "Instance Description", description = "A human readable description for the current instance.") + String sling_description(); + } + + /** Create the service and search the Sling home urls and get/create a sling id. Setup run modes + * + * @param context The bundle context */ + @Activate + public SlingSettingsServiceImpl(final Configuration configuration, final BundleContext context) { + this.configuration = configuration; this.setupSlingHome(context); this.setupSlingId(context); - this.setupRunModes(context); - } - + /** - * Get sling home and sling home URL + * Constructor only to be used from tests + * @param runModes */ + public SlingSettingsServiceImpl(String runModes) { + this.runModes = parseRunModes(runModes); + } + + /** Get sling home and sling home URL */ private void setupSlingHome(final BundleContext context) { this.slingHome = context.getProperty(SLING_HOME); final String url = context.getProperty(SLING_HOME_URL); - if ( url != null ) { + if (url != null) { try { this.slingHomeUrl = new URL(url); } catch (MalformedURLException e) { @@ -109,13 +121,11 @@ public class SlingSettingsServiceImpl } } - /** - * Get / create sling id - */ + /** Get / create sling id */ private void setupSlingId(final BundleContext context) { // try to read the id from the id file first final File idFile = context.getDataFile(ID_FILE); - if ( idFile == null ) { + if (idFile == null) { // the osgi framework does not support storing something in the file system throw new RuntimeException("Unable to read from bundle data file."); } @@ -139,45 +149,31 @@ public class SlingSettingsServiceImpl } } - /** - * Get / create sling id - */ - private void setupSlingProps(final BundleContext context) { - synchronized ( this.slingProps ) { - if ( this.slingProps.get(SLING_NAME) == null && context.getProperty(SLING_NAME) != null ) { - this.slingProps.put(SLING_NAME, context.getProperty(SLING_NAME)); - } - if ( this.slingProps.get(SLING_DESCRIPTION) == null && context.getProperty(SLING_DESCRIPTION) != null ) { - this.slingProps.put(SLING_DESCRIPTION, context.getProperty(SLING_DESCRIPTION)); - } - } - } - static final class Options implements Serializable { private static final long serialVersionUID = 1L; String[] modes; - String selected; + String selected; } private List<Options> handleOptions(final Set<String> modesSet, final String propOptions) { final List<Options> optionsList = new ArrayList<Options>(); - if ( propOptions != null && propOptions.trim().length() > 0 ) { + if (propOptions != null && propOptions.trim().length() > 0) { final String[] options = propOptions.trim().split("\\|"); - for(final String opt : options) { + for (final String opt : options) { String selected = null; final String[] modes = opt.trim().split(","); - for(int i=0; i<modes.length; i++) { + for (int i = 0; i < modes.length; i++) { modes[i] = modes[i].trim(); - if ( selected != null ) { + if (selected != null) { modesSet.remove(modes[i]); } else { - if ( modesSet.contains(modes[i]) ) { + if (modesSet.contains(modes[i])) { selected = modes[i]; } } } - if ( selected == null ) { + if (selected == null) { selected = modes[0]; modesSet.add(modes[0]); } @@ -190,30 +186,36 @@ public class SlingSettingsServiceImpl return optionsList; } - /** - * Set up run modes. - */ + private Set<String> parseRunModes(String runModes) { + final Set<String> modesSet = new HashSet<>(); + final String[] modes = runModes.split(","); + for (int i = 0; i < modes.length; i++) { + modesSet.add(modes[i].trim()); + } + return modesSet; + } + + /** Set up run modes. */ private void setupRunModes(final BundleContext context) { - final Set<String> modesSet = new HashSet<String>(); + final Set<String> modesSet; // check configuration property first final String prop = context.getProperty(RUN_MODES_PROPERTY); if (prop != null && prop.trim().length() > 0) { - final String[] modes = prop.split(","); - for(int i=0; i < modes.length; i++) { - modesSet.add(modes[i].trim()); - } + modesSet = parseRunModes(prop); + } else { + modesSet = new HashSet<>(); } - // handle configured options + // handle configured options this.handleOptions(modesSet, context.getProperty(RUN_MODE_OPTIONS)); // handle configured install options // read persisted options if restart or update final List<Options> storedOptions = readOptions(context); - if ( storedOptions != null ) { - for(final Options o : storedOptions) { - for(final String m : o.modes) { + if (storedOptions != null) { + for (final Options o : storedOptions) { + for (final String m : o.modes) { modesSet.remove(m); } modesSet.add(o.selected); @@ -228,19 +230,18 @@ public class SlingSettingsServiceImpl // make the set unmodifiable and synced // we probably don't need a synced set as it is read only this.runModes = Collections.synchronizedSet(Collections.unmodifiableSet(modesSet)); - if ( this.runModes.size() > 0 ) { + if (this.runModes.size() > 0) { logger.info("Active run modes: {}", this.runModes); } else { logger.info("No run modes active"); } } - @SuppressWarnings("unchecked") private List<Options> readOptions(final BundleContext context) { List<Options> optionsList = null; final File file = context.getDataFile(OPTIONS_FILE); - if ( file.exists() ) { + if (file.exists()) { FileInputStream fis = null; ObjectInputStream ois = null; try { @@ -248,16 +249,22 @@ public class SlingSettingsServiceImpl ois = new ObjectInputStream(fis); optionsList = (List<Options>) ois.readObject(); - } catch ( final IOException ioe ) { + } catch (final IOException ioe) { throw new RuntimeException("Unable to read from options data file.", ioe); } catch (ClassNotFoundException cnfe) { throw new RuntimeException("Unable to read from options data file.", cnfe); } finally { - if ( ois != null ) { - try { ois.close(); } catch ( final IOException ignore) {} + if (ois != null) { + try { + ois.close(); + } catch (final IOException ignore) { + } } - if ( fis != null ) { - try { fis.close(); } catch ( final IOException ignore) {} + if (fis != null) { + try { + fis.close(); + } catch (final IOException ignore) { + } } } } @@ -272,53 +279,49 @@ public class SlingSettingsServiceImpl fos = new FileOutputStream(file); oos = new ObjectOutputStream(fos); oos.writeObject(optionsList); - } catch ( final IOException ioe ) { + } catch (final IOException ioe) { throw new RuntimeException("Unable to write to options data file.", ioe); } finally { - if ( oos != null ) { - try { oos.close(); } catch ( final IOException ignore) {} + if (oos != null) { + try { + oos.close(); + } catch (final IOException ignore) { + } } - if ( fos != null ) { - try { fos.close(); } catch ( final IOException ignore) {} + if (fos != null) { + try { + fos.close(); + } catch (final IOException ignore) { + } } } } - /** - * @see org.apache.sling.settings.SlingSettingsService#getAbsolutePathWithinSlingHome(String) - */ + /** @see org.apache.sling.settings.SlingSettingsService#getAbsolutePathWithinSlingHome(String) */ @Override public String getAbsolutePathWithinSlingHome(final String relativePath) { return new File(slingHome, relativePath).getAbsolutePath(); } - /** - * @see org.apache.sling.settings.SlingSettingsService#getSlingId() - */ + /** @see org.apache.sling.settings.SlingSettingsService#getSlingId() */ @Override public String getSlingId() { return this.slingId; } - /** - * @see org.apache.sling.settings.SlingSettingsService#getSlingHome() - */ + /** @see org.apache.sling.settings.SlingSettingsService#getSlingHome() */ @Override public URL getSlingHome() { return this.slingHomeUrl; } - /** - * @see org.apache.sling.settings.SlingSettingsService#getSlingHomePath() - */ + /** @see org.apache.sling.settings.SlingSettingsService#getSlingHomePath() */ @Override public String getSlingHomePath() { return this.slingHome; } - /** - * @see org.apache.sling.settings.SlingSettingsService#getRunModes() - */ + /** @see org.apache.sling.settings.SlingSettingsService#getRunModes() */ @Override public Set<String> getRunModes() { return this.runModes; @@ -365,42 +368,27 @@ public class SlingSettingsServiceImpl */ @Override public String getSlingName() { - synchronized ( this.slingProps ) { - String name = this.slingProps.get(SLING_NAME); - if ( name == null ) { - name = "Instance " + this.slingId; // default - } - return name; + String name = configuration.sling_name(); + if ( name == null ) { + name = "Instance " + this.slingId; // default } + return name; } - /** - * @see org.apache.sling.settings.SlingSettingsService#getSlingDescription() - */ + /** @see org.apache.sling.settings.SlingSettingsService#getSlingDescription() */ @Override public String getSlingDescription() { - synchronized ( this.slingProps ) { - String desc = this.slingProps.get(SLING_DESCRIPTION); - if ( desc == null ) { - desc = "Instance with id " + this.slingId + " and run modes " + this.getRunModes(); // default - } - return desc; + String desc = configuration.sling_description(); + if (desc == null) { + desc = "Instance with id " + this.slingId + " and run modes " + this.getRunModes(); // default } + return desc; } - /** - * Update the configuration of this service - */ - public void update(final Dictionary<String, Object> properties) { - if ( properties != null ) { - synchronized ( this.slingProps ) { - if ( properties.get(SLING_NAME) != null ) { - this.slingProps.put(SLING_NAME, properties.get(SLING_NAME).toString()); - } - if ( properties.get(SLING_DESCRIPTION) != null ) { - this.slingProps.put(SLING_DESCRIPTION, properties.get(SLING_DESCRIPTION).toString()); - } - } - } + /** Update the configuration of this service */ + @Modified + public void update(final Configuration configuration) { + // TODO is configuration thread safe i.e. new object per call? + this.configuration = configuration; } } diff --git a/src/main/resources/OSGI-INF/l10n/metatype.properties b/src/main/resources/OSGI-INF/l10n/metatype.properties deleted file mode 100644 index 8b9371f..0000000 --- a/src/main/resources/OSGI-INF/l10n/metatype.properties +++ /dev/null @@ -1,29 +0,0 @@ -# -# 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. -# - - -settings.name = Apache Sling Settings Service -settings.description = The settings service manages some basic settings of Sling \ - like run modes or information about the current instance. - -sling.name.name = Instance Name -sling.name.description = A human readable name for the current instance. - -sling.description.name = Instance Description -sling.description.description = A human readable description for the current instance. \ No newline at end of file diff --git a/src/main/resources/OSGI-INF/metatype/org.apache.sling.settings.impl.SlingSettingsServiceImpl.xml b/src/main/resources/OSGI-INF/metatype/org.apache.sling.settings.impl.SlingSettingsServiceImpl.xml deleted file mode 100644 index ede0b76..0000000 --- a/src/main/resources/OSGI-INF/metatype/org.apache.sling.settings.impl.SlingSettingsServiceImpl.xml +++ /dev/null @@ -1,28 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - 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. ---><metatype:MetaData xmlns:metatype="http://www.osgi.org/xmlns/metatype/v1.0.0" - localization="OSGI-INF/l10n/metatype"> - <OCD id="org.apache.sling.settings.impl.SlingSettingsServiceImpl" name="%settings.name" description="%settings.description"> - <AD id="sling.name" type="String" name="%sling.name.name" description="%sling.name.description"/> - <AD id="sling.description" type="String" name="%sling.description.name" description="%sling.description.description"/> - </OCD> - <Designate pid="org.apache.sling.settings.impl.SlingSettingsServiceImpl"> - <Object ocdref="org.apache.sling.settings.impl.SlingSettingsServiceImpl"/> - </Designate> -</metatype:MetaData> \ No newline at end of file diff --git a/src/test/java/org/apache/sling/settings/impl/RunModeImplTest.java b/src/test/java/org/apache/sling/settings/impl/RunModeImplTest.java index 0d0fbe0..28b521c 100644 --- a/src/test/java/org/apache/sling/settings/impl/RunModeImplTest.java +++ b/src/test/java/org/apache/sling/settings/impl/RunModeImplTest.java @@ -18,39 +18,88 @@ */ package org.apache.sling.settings.impl; -import static org.hamcrest.CoreMatchers.equalTo; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import java.io.File; import java.io.IOException; -import java.io.InputStream; -import java.util.Collection; -import java.util.Dictionary; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.apache.sling.settings.SlingSettingsService; -import org.osgi.framework.Bundle; +import org.junit.Assert; +import org.junit.Before; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.stubbing.Answer; import org.osgi.framework.BundleContext; -import org.osgi.framework.BundleException; -import org.osgi.framework.BundleListener; -import org.osgi.framework.Filter; -import org.osgi.framework.FrameworkListener; -import org.osgi.framework.InvalidSyntaxException; -import org.osgi.framework.ServiceFactory; -import org.osgi.framework.ServiceListener; -import org.osgi.framework.ServiceObjects; -import org.osgi.framework.ServiceReference; -import org.osgi.framework.ServiceRegistration; +import org.osgi.util.converter.Converter; +import org.osgi.util.converter.Converters; +@RunWith(MockitoJUnitRunner.class) public class RunModeImplTest { - private void assertParse(String str, String [] expected) { - final SlingSettingsService rm = new SlingSettingsServiceImpl(new BundleContextMock(str, null, null)); + private SlingSettingsServiceImpl.Configuration configuration; + + @Mock + BundleContext mockBundleContext; + + private Map<String, File> files = new HashMap<String, File>(); + + private String runModes; + private String options; + private String installOptions; + + @Before + public void before() { + Converter c = Converters.standardConverter(); + // use standard configuration + configuration = c.convert(new HashMap<String, Object>()).to(SlingSettingsServiceImpl.Configuration.class); + runModes = null; + options = null; + installOptions = null; + Mockito.when(mockBundleContext.getDataFile(Mockito.anyString())).then(new Answer<File>() { + + @Override + public File answer(InvocationOnMock invocation) throws Throwable { + String filename = invocation.getArgumentAt(0, String.class); + File f = files.get(filename); + if ( f == null ) { + try { + f = File.createTempFile(filename, "id"); + f.delete(); + files.put(filename, f); + } catch (IOException ioe) { + throw new RuntimeException(ioe); + } + } + return f; + } + }); + + Mockito.when(mockBundleContext.getProperty(Mockito.anyString())).then(new Answer<String>() { + @Override + public String answer(InvocationOnMock invocation) throws Throwable { + String key = invocation.getArgumentAt(0, String.class); + if ( key.equals(SlingSettingsService.RUN_MODES_PROPERTY) ) { + return runModes; + } else if ( key.equals(SlingSettingsService.RUN_MODE_OPTIONS) ) { + return options; + } else if ( key.equals(SlingSettingsService.RUN_MODE_INSTALL_OPTIONS) ) { + return installOptions; + } + return null; + } + }); + } + + private void assertParse(String str, String[] expected) { + final SlingSettingsService rm = createSlingSettingsService(str, null, null); final Set<String> modes = rm.getRunModes(); Set<String> expectedSet = new HashSet<String>(expected.length); @@ -58,19 +107,20 @@ public class RunModeImplTest { expectedSet.add(expectedEntry); } - assertThat("Parsed runModes match for '" + str + "'", modes, equalTo(expectedSet)); + Assert.assertEquals("Parsed runModes match for '" + str + "'", expectedSet, modes); } - @org.junit.Test public void testParseRunModes() { + @org.junit.Test + public void testParseRunModes() { assertParse(null, new String[0]); assertParse("", new String[0]); assertParse(" foo \t", new String[] { "foo" }); assertParse(" foo \t, bar\n", new String[] { "foo", "bar" }); } - private void assertActive(SlingSettingsService s, boolean active, String ...modes) { - for(String mode : modes) { - if(active) { + private void assertActive(SlingSettingsService s, boolean active, String... modes) { + for (String mode : modes) { + if (active) { assertTrue(mode + " should be active", s.getRunModes().contains(mode)); } else { assertFalse(mode + " should NOT be active", s.getRunModes().contains(mode)); @@ -78,286 +128,101 @@ public class RunModeImplTest { } } - @org.junit.Test public void testMatchesNotEmpty() { - final SlingSettingsService rm = new SlingSettingsServiceImpl(new BundleContextMock("foo,bar", null, null)); + @org.junit.Test + public void testMatchesNotEmpty() { + final SlingSettingsService rm = createSlingSettingsService("foo,bar", null, null); assertActive(rm, true, "foo", "bar"); assertActive(rm, false, "wiz", "bah", ""); } - @org.junit.Test public void testOptions() { - final SlingSettingsService rm = new SlingSettingsServiceImpl(new BundleContextMock("foo,bar", "a,b,c|d,e,f", null)); + @org.junit.Test + public void testOptions() { + final SlingSettingsService rm = createSlingSettingsService("foo,bar", "a,b,c|d,e,f", null); assertActive(rm, true, "foo", "bar", "a", "d"); assertActive(rm, false, "b", "c", "e", "f"); } - @org.junit.Test public void testEmptyRunModesWithOptions() { - final SlingSettingsService rm = new SlingSettingsServiceImpl(new BundleContextMock("", "a,b,c|d,e,f", null)); + @org.junit.Test + public void testEmptyRunModesWithOptions() { + final SlingSettingsService rm = createSlingSettingsService("", "a,b,c|d,e,f", null); assertActive(rm, true, "a", "d"); assertActive(rm, false, "b", "c", "e", "f"); } - @org.junit.Test public void testOptionsSelected() { - final SlingSettingsService rm = new SlingSettingsServiceImpl(new BundleContextMock("foo,bar,c,e", "a,b,c|d,e,f", null)); + @org.junit.Test + public void testOptionsSelected() { + final SlingSettingsService rm = createSlingSettingsService("foo,bar,c,e", "a,b,c|d,e,f", null); assertActive(rm, true, "foo", "bar", "c", "e"); assertActive(rm, false, "a", "b", "d", "f"); } - @org.junit.Test public void testOptionsMultipleSelected() { - final SlingSettingsService rm = new SlingSettingsServiceImpl(new BundleContextMock("foo,bar,c,e,f,a", "a,b,c|d,e,f", null)); + @org.junit.Test + public void testOptionsMultipleSelected() { + final SlingSettingsService rm = createSlingSettingsService("foo,bar,c,e,f,a", "a,b,c|d,e,f", null); assertActive(rm, true, "foo", "bar", "a", "e"); assertActive(rm, false, "b", "c", "d", "f"); } - @org.junit.Test public void testOptionsMultipleSelected2() { - final SlingSettingsService rm = new SlingSettingsServiceImpl(new BundleContextMock("foo,bar,c,f,a,d", "a,b,c|d,e,f", null)); + @org.junit.Test + public void testOptionsMultipleSelected2() { + final SlingSettingsService rm = createSlingSettingsService("foo,bar,c,f,a,d", "a,b,c|d,e,f", null); assertActive(rm, true, "foo", "bar", "a", "d"); assertActive(rm, false, "b", "c", "e", "f"); } - @org.junit.Test public void testInstallOptions() { - final SlingSettingsService rm = new SlingSettingsServiceImpl(new BundleContextMock("foo,bar", null, "a,b,c|d,e,f")); + @org.junit.Test + public void testInstallOptions() { + final SlingSettingsService rm = createSlingSettingsService("foo,bar", null, "a,b,c|d,e,f"); assertActive(rm, true, "foo", "bar", "a", "d"); assertActive(rm, false, "b", "c", "e", "f"); } - @org.junit.Test public void testInstallOptionsSelected() { - final SlingSettingsService rm = new SlingSettingsServiceImpl(new BundleContextMock("foo,bar,c,e", null , "a,b,c|d,e,f")); + @org.junit.Test + public void testInstallOptionsSelected() { + final SlingSettingsService rm = createSlingSettingsService("foo,bar,c,e", null, "a,b,c|d,e,f"); assertActive(rm, true, "foo", "bar", "c", "e"); assertActive(rm, false, "a", "b", "d", "f"); } - @org.junit.Test public void testInstallOptionsMultipleSelected() { - final SlingSettingsService rm = new SlingSettingsServiceImpl(new BundleContextMock("foo,bar,c,e,f,a", null, "a,b,c|d,e,f")); + @org.junit.Test + public void testInstallOptionsMultipleSelected() { + final SlingSettingsService rm = createSlingSettingsService("foo,bar,c,e,f,a", null, "a,b,c|d,e,f"); assertActive(rm, true, "foo", "bar", "a", "e"); assertActive(rm, false, "b", "c", "d", "f"); } - @org.junit.Test public void testInstallOptionsMultipleSelected2() { - final SlingSettingsService rm = new SlingSettingsServiceImpl(new BundleContextMock("foo,bar,c,d,f,a", null, "a,b,c|d,e,f")); + @org.junit.Test + public void testInstallOptionsMultipleSelected2() { + final SlingSettingsService rm = createSlingSettingsService("foo,bar,c,d,f,a", null, "a,b,c|d,e,f"); assertActive(rm, true, "foo", "bar", "a", "d"); assertActive(rm, false, "b", "c", "e", "f"); } - @org.junit.Test public void testInstallOptionsRestart() { - final BundleContextMock bc = new BundleContextMock("foo,bar,c,e,f,a", null, "a,b,c|d,e,f"); - + @org.junit.Test + public void testInstallOptionsRestart() { { // create first context to simulate install - final SlingSettingsService rm = new SlingSettingsServiceImpl(bc); - assertActive(rm, true, "foo", "bar", "a", "e"); - assertActive(rm, false, "b", "c", "d", "f"); - } - - { - final SlingSettingsService rm = new SlingSettingsServiceImpl(bc); + final SlingSettingsService rm = createSlingSettingsService("foo,bar,c,e,f,a", null, "a,b,c|d,e,f"); assertActive(rm, true, "foo", "bar", "a", "e"); assertActive(rm, false, "b", "c", "d", "f"); } // simulate restart with different run modes: new ones that are // mentioned in the .options properties are ignored - bc.update("foo,doo,a,b,c,d,e,f,waa"); { - final SlingSettingsService rm = new SlingSettingsServiceImpl(bc); + SlingSettingsService rm = createSlingSettingsService("foo,bar,c,e,f,a", null, "a,b,c|d,e,f"); + assertActive(rm, true, "foo", "bar", "a", "e"); + assertActive(rm, false, "b", "c", "d", "f"); + rm = createSlingSettingsService("foo,doo,a,b,c,d,e,f,waa", null, "a,b,c|d,e,f"); assertActive(rm, true, "foo", "doo", "a", "e", "waa"); assertActive(rm, false, "bar", "b", "c", "d", "f"); } } - private static final class BundleContextMock implements BundleContext { - - private String runModes; - private final String options; - private final String installOptions; - - private final Map<String, File> files = new HashMap<String, File>(); - - public BundleContextMock(String runModes, String options, String installOptions) { - this.runModes = runModes; - this.options = options; - this.installOptions = installOptions; - } - - public void update(final String rm) { - this.runModes = rm; - } - - @Override - public void addBundleListener(BundleListener listener) { - // TODO Auto-generated method stub - - } - - @Override - public void addFrameworkListener(FrameworkListener listener) { - // TODO Auto-generated method stub - - } - - @Override - public void addServiceListener(ServiceListener listener, String filter) - throws InvalidSyntaxException { - // TODO Auto-generated method stub - - } - - @Override - public void addServiceListener(ServiceListener listener) { - // TODO Auto-generated method stub - - } - - @Override - public Filter createFilter(String filter) throws InvalidSyntaxException { - // TODO Auto-generated method stub - return null; - } - - @Override - public ServiceReference[] getAllServiceReferences(String clazz, - String filter) throws InvalidSyntaxException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Bundle getBundle() { - // TODO Auto-generated method stub - return null; - } - - @Override - public Bundle getBundle(long id) { - // TODO Auto-generated method stub - return null; - } - - @Override - public Bundle[] getBundles() { - return new Bundle[0]; - } - - @Override - public File getDataFile(String filename) { - File f = files.get(filename); - if ( f == null ) { - try { - f = File.createTempFile(filename, "id"); - f.delete(); - files.put(filename, f); - } catch (IOException ioe) { - throw new RuntimeException(ioe); - } - } - return f; - } - - @Override - public String getProperty(String key) { - if ( key.equals(SlingSettingsService.RUN_MODES_PROPERTY) ) { - return runModes; - } else if ( key.equals(SlingSettingsService.RUN_MODE_OPTIONS) ) { - return options; - } else if ( key.equals(SlingSettingsService.RUN_MODE_INSTALL_OPTIONS) ) { - return installOptions; - } - return null; - } - - @Override - public Object getService(ServiceReference reference) { - return null; - } - - @Override - public ServiceReference getServiceReference(String clazz) { - return null; - } - - @Override - public ServiceReference[] getServiceReferences(String clazz, - String filter) throws InvalidSyntaxException { - return null; - } - - @Override - public Bundle installBundle(String location, InputStream input) - throws BundleException { - return null; - } - - @Override - public Bundle installBundle(String location) throws BundleException { - return null; - } - - @Override - @SuppressWarnings("unchecked") - public ServiceRegistration registerService(String clazz, - Object service, Dictionary properties) { - return null; - } - - @Override - @SuppressWarnings("unchecked") - public ServiceRegistration registerService(String[] clazzes, - Object service, Dictionary properties) { - return null; - } - - @Override - public void removeBundleListener(BundleListener listener) { - } - - @Override - public void removeFrameworkListener(FrameworkListener listener) { - } - - @Override - public void removeServiceListener(ServiceListener listener) { - } - - @Override - public boolean ungetService(ServiceReference reference) { - return false; - } - - @Override - public <S> ServiceRegistration<S> registerService(Class<S> clazz, S service, Dictionary<String, ?> properties) { - // TODO Auto-generated method stub - return null; - } - - @Override - public <S> ServiceRegistration<S> registerService(Class<S> clazz, ServiceFactory<S> factory, - Dictionary<String, ?> properties) { - // TODO Auto-generated method stub - return null; - } - - @Override - public <S> ServiceReference<S> getServiceReference(Class<S> clazz) { - // TODO Auto-generated method stub - return null; - } - - @Override - public <S> Collection<ServiceReference<S>> getServiceReferences(Class<S> clazz, String filter) - throws InvalidSyntaxException { - // TODO Auto-generated method stub - return null; - } - - @Override - public <S> ServiceObjects<S> getServiceObjects(ServiceReference<S> reference) { - // TODO Auto-generated method stub - return null; - } - - @Override - public Bundle getBundle(String location) { - // TODO Auto-generated method stub - return null; - } + private SlingSettingsService createSlingSettingsService(String runModes, String options, String installOptions) { + this.runModes = runModes; + this.options = options; + this.installOptions = installOptions; + return new SlingSettingsServiceImpl(configuration, mockBundleContext); } } \ No newline at end of file diff --git a/src/test/java/org/apache/sling/settings/impl/SlingSettingsServiceImplTest.java b/src/test/java/org/apache/sling/settings/impl/SlingSettingsServiceImplTest.java index 15c935f..e47bc46 100644 --- a/src/test/java/org/apache/sling/settings/impl/SlingSettingsServiceImplTest.java +++ b/src/test/java/org/apache/sling/settings/impl/SlingSettingsServiceImplTest.java @@ -29,6 +29,7 @@ import java.io.IOException; import java.io.ObjectOutputStream; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -40,6 +41,8 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.osgi.framework.BundleContext; +import org.osgi.util.converter.Converter; +import org.osgi.util.converter.Converters; public class SlingSettingsServiceImplTest { @@ -50,11 +53,16 @@ public class SlingSettingsServiceImplTest { private File slingIdFile = null; private File optionsFile = null; + + private SlingSettingsServiceImpl.Configuration configuration; @Before public void before() throws IOException { slingIdFile = File.createTempFile(SLING_ID_FILE_NAME, ""); optionsFile = File.createTempFile(OPTIONS_FILE_NAME, ""); + Converter c = Converters.standardConverter(); + // use standard configuration + configuration = c.convert(new HashMap<String, Object>()).to(SlingSettingsServiceImpl.Configuration.class); } @After @@ -132,7 +140,7 @@ public class SlingSettingsServiceImplTest { } catch (final IOException ioe) { throw new RuntimeException("Unable to write to options data file.", ioe); } - return new SlingSettingsServiceImpl(context); + return new SlingSettingsServiceImpl(configuration, context); } }
