Author: cziegeler
Date: Mon Nov 26 10:14:09 2012
New Revision: 1413541
URL: http://svn.apache.org/viewvc?rev=1413541&view=rev
Log:
SLING-2674 : SlingSettingsServiceImpl should detect and handle upgrades
Added:
sling/trunk/bundles/extensions/settings/src/main/java/org/apache/sling/settings/impl/ServicesListener.java
(with props)
Modified:
sling/trunk/bundles/extensions/settings/src/main/java/org/apache/sling/settings/impl/Activator.java
sling/trunk/bundles/extensions/settings/src/main/java/org/apache/sling/settings/impl/SlingSettingsServiceImpl.java
sling/trunk/bundles/extensions/settings/src/test/java/org/apache/sling/settings/impl/RunModeImplTest.java
Modified:
sling/trunk/bundles/extensions/settings/src/main/java/org/apache/sling/settings/impl/Activator.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/settings/src/main/java/org/apache/sling/settings/impl/Activator.java?rev=1413541&r1=1413540&r2=1413541&view=diff
==============================================================================
---
sling/trunk/bundles/extensions/settings/src/main/java/org/apache/sling/settings/impl/Activator.java
(original)
+++
sling/trunk/bundles/extensions/settings/src/main/java/org/apache/sling/settings/impl/Activator.java
Mon Nov 26 10:14:09 2012
@@ -18,14 +18,8 @@
*/
package org.apache.sling.settings.impl;
-import java.util.Dictionary;
-import java.util.Hashtable;
-
-import org.apache.sling.settings.SlingSettingsService;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.framework.ServiceRegistration;
/**
* This is the bundle activator.
@@ -34,48 +28,23 @@ import org.osgi.framework.ServiceRegistr
*/
public class Activator implements BundleActivator {
- /** The service registration */
- private ServiceRegistration serviceRegistration;
+ /** The service listener */
+ private ServicesListener servicesListener;
/**
* @see
org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
*/
public void start(final BundleContext bundleContext) throws Exception {
- final SlingSettingsService settingsService = new
SlingSettingsServiceImpl(bundleContext);
-
- final Dictionary<String, String> props = new Hashtable<String,
String>();
- props.put(Constants.SERVICE_PID, settingsService.getClass().getName());
- props.put(Constants.SERVICE_DESCRIPTION,
- "Apache Sling Settings Service");
- props.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation");
- serviceRegistration = bundleContext.registerService(new String[] {
-
SlingSettingsService.class.getName()},
- settingsService, props);
- SlingPropertiesPrinter.initPlugin(bundleContext);
- SlingSettingsPrinter.initPlugin(bundleContext, settingsService);
- try {
- RunModeCommand.initPlugin(bundleContext,
settingsService.getRunModes());
- } catch (Throwable ignore) {
- // we just ignore this
- }
-
+ this.servicesListener = new ServicesListener(bundleContext);
}
/**
* @see
org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
*/
public void stop(final BundleContext context) throws Exception {
- try {
- RunModeCommand.destroyPlugin();
- } catch (Throwable ignore) {
- // we just ignore this
- }
- SlingSettingsPrinter.destroyPlugin();
- SlingPropertiesPrinter.destroyPlugin();
-
- if ( serviceRegistration != null ) {
- serviceRegistration.unregister();
- serviceRegistration = null;
+ if ( this.servicesListener != null ) {
+ this.servicesListener.deactivate();
+ this.servicesListener = null;
}
}
}
Added:
sling/trunk/bundles/extensions/settings/src/main/java/org/apache/sling/settings/impl/ServicesListener.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/settings/src/main/java/org/apache/sling/settings/impl/ServicesListener.java?rev=1413541&view=auto
==============================================================================
---
sling/trunk/bundles/extensions/settings/src/main/java/org/apache/sling/settings/impl/ServicesListener.java
(added)
+++
sling/trunk/bundles/extensions/settings/src/main/java/org/apache/sling/settings/impl/ServicesListener.java
Mon Nov 26 10:14:09 2012
@@ -0,0 +1,199 @@
+/*
+ * 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.launchpad.api.StartupHandler;
+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 the startup handler. */
+ private final Listener startupListener;
+
+ /** The registration of the settings service. */
+ private ServiceRegistration settingsReg;
+
+ /**
+ * Start listeners
+ */
+ public ServicesListener(final BundleContext bundleContext) {
+ this.bundleContext = bundleContext;
+ this.startupListener = new Listener(StartupHandler.class.getName());
+ this.startupListener.start();
+ }
+
+ /**
+ * Notify of service changes from the listeners.
+ * If all services are available, register listener and pass resources
+ * to the OSGi installer.
+ */
+ public synchronized void notifyChange() {
+ // check if all services are available
+ final StartupHandler handler =
(StartupHandler)this.startupListener.getService();
+ if ( handler != null && this.settingsReg == null ) {
+ this.activate(handler);
+ }
+ }
+
+ private void activate(final StartupHandler handler) {
+ final SlingSettingsService settingsService = new
SlingSettingsServiceImpl(bundleContext, handler);
+
+ final Dictionary<String, String> props = new Hashtable<String,
String>();
+ props.put(Constants.SERVICE_PID, settingsService.getClass().getName());
+ 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);
+ try {
+ RunModeCommand.initPlugin(bundleContext,
settingsService.getRunModes());
+ } catch (Throwable ignore) {
+ // we just ignore this
+ }
+ }
+ /**
+ * Deactivate this listener.
+ */
+ public void deactivate() {
+ this.startupListener.deactivate();
+ if ( this.settingsReg != null ) {
+ this.settingsReg.unregister();
+ this.settingsReg = null;
+ }
+ try {
+ RunModeCommand.destroyPlugin();
+ } catch (Throwable ignore) {
+ // we just ignore this
+ }
+ SlingSettingsPrinter.destroyPlugin();
+ SlingPropertiesPrinter.destroyPlugin();
+ }
+
+ /**
+ * Helper class listening for service events for a defined service.
+ */
+ protected final class Listener 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 Listener(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 occured.",
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 {
+ notifyChange();
+ }
+ }
+ }
+ }
+
+ /**
+ * 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;
+ notifyChange();
+ }
+ }
+
+ /**
+ * @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();
+ }
+ }
+ }
+}
Propchange:
sling/trunk/bundles/extensions/settings/src/main/java/org/apache/sling/settings/impl/ServicesListener.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
sling/trunk/bundles/extensions/settings/src/main/java/org/apache/sling/settings/impl/ServicesListener.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url
Propchange:
sling/trunk/bundles/extensions/settings/src/main/java/org/apache/sling/settings/impl/ServicesListener.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified:
sling/trunk/bundles/extensions/settings/src/main/java/org/apache/sling/settings/impl/SlingSettingsServiceImpl.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/settings/src/main/java/org/apache/sling/settings/impl/SlingSettingsServiceImpl.java?rev=1413541&r1=1413540&r2=1413541&view=diff
==============================================================================
---
sling/trunk/bundles/extensions/settings/src/main/java/org/apache/sling/settings/impl/SlingSettingsServiceImpl.java
(original)
+++
sling/trunk/bundles/extensions/settings/src/main/java/org/apache/sling/settings/impl/SlingSettingsServiceImpl.java
Mon Nov 26 10:14:09 2012
@@ -34,6 +34,7 @@ import java.util.List;
import java.util.Set;
import java.util.UUID;
+import org.apache.sling.launchpad.api.StartupHandler;
import org.apache.sling.launchpad.api.StartupMode;
import org.apache.sling.settings.SlingSettingsService;
import org.osgi.framework.BundleContext;
@@ -72,24 +73,13 @@ public class SlingSettingsServiceImpl
* Setup run modes
* @param context The bundle context
*/
- public SlingSettingsServiceImpl(final BundleContext context) {
+ public SlingSettingsServiceImpl(final BundleContext context,
+ final StartupHandler handler) {
this.setupSlingHome(context);
- final boolean isInstall = this.setupSlingId(context);
+ this.setupSlingId(context);
- // Detect if upgrading from a previous version (where OPTIONS_FILE did
not exist),
- // as in terms of run modes this needs to be handled like an install
- final File options = context.getDataFile(OPTIONS_FILE);
- final boolean isUpdate = !isInstall && !options.exists();
-
- final String startupModeObj =
context.getProperty(StartupMode.class.getName());
- final StartupMode mode;
- if ( startupModeObj != null ) {
- mode = StartupMode.valueOf(startupModeObj);
- logger.debug("Settings: Using startup mode : {}", mode);
- } else {
- logger.debug("Settings: Startup mode detection: isInstall={},
isUpdate={}", isInstall, isUpdate);
- mode = isInstall ? StartupMode.INSTALL : (isUpdate ?
StartupMode.UPDATE : StartupMode.RESTART);
- }
+ final StartupMode mode = handler.getMode();
+ logger.debug("Settings: Using startup mode : {}", mode);
this.setupRunModes(context, mode);
@@ -113,7 +103,7 @@ public class SlingSettingsServiceImpl
/**
* Get / create sling id
*/
- private boolean setupSlingId(final BundleContext context) {
+ private void setupSlingId(final BundleContext context) {
// try to read the id from the id file first
final File idFile = context.getDataFile(DATA_FILE);
if ( idFile == null ) {
@@ -126,9 +116,7 @@ public class SlingSettingsServiceImpl
if (slingId == null) {
slingId = UUID.randomUUID().toString();
this.writeSlingId(idFile, this.slingId);
- return true;
}
- return false;
}
private static final class Options implements Serializable {
Modified:
sling/trunk/bundles/extensions/settings/src/test/java/org/apache/sling/settings/impl/RunModeImplTest.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/settings/src/test/java/org/apache/sling/settings/impl/RunModeImplTest.java?rev=1413541&r1=1413540&r2=1413541&view=diff
==============================================================================
---
sling/trunk/bundles/extensions/settings/src/test/java/org/apache/sling/settings/impl/RunModeImplTest.java
(original)
+++
sling/trunk/bundles/extensions/settings/src/test/java/org/apache/sling/settings/impl/RunModeImplTest.java
Mon Nov 26 10:14:09 2012
@@ -30,6 +30,8 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Set;
+import org.apache.sling.launchpad.api.StartupHandler;
+import org.apache.sling.launchpad.api.StartupMode;
import org.apache.sling.settings.SlingSettingsService;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
@@ -44,8 +46,33 @@ import org.osgi.framework.ServiceRegistr
public class RunModeImplTest {
+ private final class StartupHandlerImpl implements StartupHandler {
+
+ private final StartupMode mode;
+
+ public StartupHandlerImpl() {
+ this(StartupMode.INSTALL);
+ }
+
+ public StartupHandlerImpl(final StartupMode mode) {
+ this.mode = mode;
+ }
+
+ public void waitWithStartup(final boolean flag) {
+ // nothing to do
+ }
+
+ public boolean isFinished() {
+ return false;
+ }
+
+ public StartupMode getMode() {
+ return this.mode;
+ }
+ };
+
private void assertParse(String str, String [] expected) {
- final SlingSettingsService rm = new SlingSettingsServiceImpl(new
BundleContextMock(str, null, null));
+ final SlingSettingsService rm = new SlingSettingsServiceImpl(new
BundleContextMock(str, null, null), new StartupHandlerImpl());
final Set<String> modes = rm.getRunModes();
final String[] actual = modes.toArray(new String[modes.size()]);
assertArrayEquals("Parsed runModes match for '" + str + "'", expected,
actual);
@@ -57,7 +84,7 @@ public class RunModeImplTest {
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) {
@@ -69,77 +96,77 @@ public class RunModeImplTest {
}
@org.junit.Test public void testMatchesNotEmpty() {
- final SlingSettingsService rm = new SlingSettingsServiceImpl(new
BundleContextMock("foo,bar", null, null));
+ final SlingSettingsService rm = new SlingSettingsServiceImpl(new
BundleContextMock("foo,bar", null, null), new StartupHandlerImpl());
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));
+ final SlingSettingsService rm = new SlingSettingsServiceImpl(new
BundleContextMock("foo,bar", "a,b,c|d,e,f", null), new StartupHandlerImpl());
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));
+ final SlingSettingsService rm = new SlingSettingsServiceImpl(new
BundleContextMock("", "a,b,c|d,e,f", null), new StartupHandlerImpl());
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));
+ final SlingSettingsService rm = new SlingSettingsServiceImpl(new
BundleContextMock("foo,bar,c,e", "a,b,c|d,e,f", null), new
StartupHandlerImpl());
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));
+ final SlingSettingsService rm = new SlingSettingsServiceImpl(new
BundleContextMock("foo,bar,c,e,f,a", "a,b,c|d,e,f", null), new
StartupHandlerImpl());
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));
+ final SlingSettingsService rm = new SlingSettingsServiceImpl(new
BundleContextMock("foo,bar,c,f,a,d", "a,b,c|d,e,f", null), new
StartupHandlerImpl());
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"));
+ final SlingSettingsService rm = new SlingSettingsServiceImpl(new
BundleContextMock("foo,bar", null, "a,b,c|d,e,f"), new StartupHandlerImpl());
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"));
+ final SlingSettingsService rm = new SlingSettingsServiceImpl(new
BundleContextMock("foo,bar,c,e", null , "a,b,c|d,e,f"), new
StartupHandlerImpl());
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"));
+ final SlingSettingsService rm = new SlingSettingsServiceImpl(new
BundleContextMock("foo,bar,c,e,f,a", null, "a,b,c|d,e,f"), new
StartupHandlerImpl());
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"));
+ final SlingSettingsService rm = new SlingSettingsServiceImpl(new
BundleContextMock("foo,bar,c,d,f,a", null, "a,b,c|d,e,f"), new
StartupHandlerImpl());
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");
-
+
{
// create first context to simulate install
- final SlingSettingsService rm = new SlingSettingsServiceImpl(bc);
+ final SlingSettingsService rm = new SlingSettingsServiceImpl(bc,
new StartupHandlerImpl());
assertActive(rm, true, "foo", "bar", "a", "e");
assertActive(rm, false, "b", "c", "d", "f");
}
-
+
{
- final SlingSettingsService rm = new SlingSettingsServiceImpl(bc);
+ final SlingSettingsService rm = new SlingSettingsServiceImpl(bc,
new StartupHandlerImpl(StartupMode.RESTART));
assertActive(rm, true, "foo", "bar", "a", "e");
assertActive(rm, false, "b", "c", "d", "f");
}
@@ -148,7 +175,7 @@ public class RunModeImplTest {
// mentioned in the .options properties are ignored
bc.update("foo,doo,a,b,c,d,e,f,waa");
{
- final SlingSettingsService rm = new SlingSettingsServiceImpl(bc);
+ final SlingSettingsService rm = new SlingSettingsServiceImpl(bc,
new StartupHandlerImpl(StartupMode.RESTART));
assertActive(rm, true, "foo", "doo", "a", "e", "waa");
assertActive(rm, false, "bar", "b", "c", "d", "f");
}