You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ol...@apache.org on 2015/11/27 11:23:40 UTC
svn commit: r1716822 - in
/sling/trunk/contrib/launchpad/karaf/org.apache.sling.launchpad.karaf: ./
src/main/java/org/apache/sling/launchpad/karaf/
src/main/java/org/apache/sling/startup/
src/main/java/org/apache/sling/startup/configurable/ src/main/re...
Author: olli
Date: Fri Nov 27 10:23:40 2015
New Revision: 1716822
URL: http://svn.apache.org/viewvc?rev=1716822&view=rev
Log:
SLING-5338 Provide a configurable Startup API implementation
refactor and extend org.apache.sling.launchpad.karaf
Added:
sling/trunk/contrib/launchpad/karaf/org.apache.sling.launchpad.karaf/src/main/java/org/apache/sling/startup/
sling/trunk/contrib/launchpad/karaf/org.apache.sling.launchpad.karaf/src/main/java/org/apache/sling/startup/configurable/
sling/trunk/contrib/launchpad/karaf/org.apache.sling.launchpad.karaf/src/main/java/org/apache/sling/startup/configurable/ConfigurableStartupHandler.java
- copied, changed from r1716821, sling/trunk/contrib/launchpad/karaf/org.apache.sling.launchpad.karaf/src/main/java/org/apache/sling/launchpad/karaf/KarafStartupHandler.java
sling/trunk/contrib/launchpad/karaf/org.apache.sling.launchpad.karaf/src/main/java/org/apache/sling/startup/configurable/ConfigurableStartupHandlerConfiguration.java
sling/trunk/contrib/launchpad/karaf/org.apache.sling.launchpad.karaf/src/main/java/org/apache/sling/startup/configurable/ConfigurableStartupService.java
Removed:
sling/trunk/contrib/launchpad/karaf/org.apache.sling.launchpad.karaf/src/main/java/org/apache/sling/launchpad/karaf/KarafStartupHandler.java
sling/trunk/contrib/launchpad/karaf/org.apache.sling.launchpad.karaf/src/main/resources/
Modified:
sling/trunk/contrib/launchpad/karaf/org.apache.sling.launchpad.karaf/pom.xml
Modified: sling/trunk/contrib/launchpad/karaf/org.apache.sling.launchpad.karaf/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/launchpad/karaf/org.apache.sling.launchpad.karaf/pom.xml?rev=1716822&r1=1716821&r2=1716822&view=diff
==============================================================================
--- sling/trunk/contrib/launchpad/karaf/org.apache.sling.launchpad.karaf/pom.xml (original)
+++ sling/trunk/contrib/launchpad/karaf/org.apache.sling.launchpad.karaf/pom.xml Fri Nov 27 10:23:40 2015
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.sling</groupId>
<artifactId>sling</artifactId>
- <version>25</version>
+ <version>26-SNAPSHOT</version>
<relativePath/>
</parent>
@@ -35,6 +35,10 @@
<name>Apache Sling Launchpad Karaf</name>
<description>Apache Sling Launchpad Karaf</description>
+ <properties>
+ <sling.java.version>8</sling.java.version>
+ </properties>
+
<dependencies>
<!-- Sling -->
<dependency>
@@ -47,12 +51,25 @@
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
+ <version>6.0.0</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.service.cm</artifactId>
+ <version>1.5.0</version>
<scope>provided</scope>
</dependency>
- <!-- Apache Felix -->
<dependency>
- <groupId>org.apache.felix</groupId>
- <artifactId>org.apache.felix.scr.annotations</artifactId>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.service.metatype.annotations</artifactId>
+ <version>1.3.0</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.util.tracker</artifactId>
+ <version>1.5.1</version>
<scope>provided</scope>
</dependency>
<!-- logging -->
@@ -69,18 +86,21 @@
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
- </plugin>
- <plugin>
- <groupId>org.apache.felix</groupId>
- <artifactId>maven-scr-plugin</artifactId>
+ <configuration>
+ <instructions>
+ <Export-Package/>
+ <_metatypeannotations>*</_metatypeannotations>
+ <_dsannotations>*</_dsannotations>
+ </instructions>
+ </configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
- <source>1.6</source>
- <target>1.6</target>
+ <source>1.8</source>
+ <target>1.8</target>
</configuration>
</plugin>
</plugins>
Copied: sling/trunk/contrib/launchpad/karaf/org.apache.sling.launchpad.karaf/src/main/java/org/apache/sling/startup/configurable/ConfigurableStartupHandler.java (from r1716821, sling/trunk/contrib/launchpad/karaf/org.apache.sling.launchpad.karaf/src/main/java/org/apache/sling/launchpad/karaf/KarafStartupHandler.java)
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/launchpad/karaf/org.apache.sling.launchpad.karaf/src/main/java/org/apache/sling/startup/configurable/ConfigurableStartupHandler.java?p2=sling/trunk/contrib/launchpad/karaf/org.apache.sling.launchpad.karaf/src/main/java/org/apache/sling/startup/configurable/ConfigurableStartupHandler.java&p1=sling/trunk/contrib/launchpad/karaf/org.apache.sling.launchpad.karaf/src/main/java/org/apache/sling/launchpad/karaf/KarafStartupHandler.java&r1=1716821&r2=1716822&rev=1716822&view=diff
==============================================================================
--- sling/trunk/contrib/launchpad/karaf/org.apache.sling.launchpad.karaf/src/main/java/org/apache/sling/launchpad/karaf/KarafStartupHandler.java (original)
+++ sling/trunk/contrib/launchpad/karaf/org.apache.sling.launchpad.karaf/src/main/java/org/apache/sling/startup/configurable/ConfigurableStartupHandler.java Fri Nov 27 10:23:40 2015
@@ -16,117 +16,223 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.sling.launchpad.karaf;
+package org.apache.sling.startup.configurable;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.concurrent.atomic.AtomicBoolean;
-import org.apache.felix.scr.annotations.Activate;
-import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.Deactivate;
-import org.apache.felix.scr.annotations.Modified;
-import org.apache.felix.scr.annotations.Property;
-import org.apache.felix.scr.annotations.PropertyOption;
-import org.apache.felix.scr.annotations.Service;
import org.apache.sling.launchpad.api.StartupHandler;
+import org.apache.sling.launchpad.api.StartupListener;
import org.apache.sling.launchpad.api.StartupMode;
+import org.apache.sling.launchpad.api.StartupService;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Modified;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.metatype.annotations.Designate;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-/**
- * TODO
- * figure out when we are finished @see #isFinished()
- */
@Component(
- name = "org.apache.sling.launchpad.karaf.KarafStartupHandler",
- label = "%org.apache.sling.launchpad.karaf.label",
- description = "%org.apache.sling.launchpad.karaf.description",
- metatype = true,
- immediate = true
+ immediate = true,
+ property = Constants.SERVICE_VENDOR + "=The Apache Software Foundation"
)
-@Service
-@Property(name = Constants.SERVICE_VENDOR, value = "The Apache Software Foundation")
-public class KarafStartupHandler implements StartupHandler {
+@Designate(ocd = ConfigurableStartupHandlerConfiguration.class)
+public class ConfigurableStartupHandler implements StartupHandler {
+
+ private ConfigurationAdmin configurationAdmin;
+
+ private BundleContext bundleContext;
+
+ private ServiceListener serviceListener = serviceEvent -> evaluate();
+
+ private ServiceTracker<StartupListener, StartupListener> serviceTracker;
+
+ private ServiceRegistration startupServiceRegistration;
private StartupMode startupMode;
- private static final String STARTUP_MODE_INSTALL = "INSTALL";
+ private String[] requiredServices;
+
+ private boolean reconfigureStartupModeToRestartOnFinish;
+
+ private final AtomicBoolean finished = new AtomicBoolean(false);
- private static final String STARTUP_MODE_RESTART = "RESTART";
+ private final Object lock = new Object();
- private static final String STARTUP_MODE_UPDATE = "UPDATE";
+ private static final String SERVICES_FILTERS_TEMPLATE = "(|%s)";
- /**
- * TODO
- * until fully figured out what happens on INSTALL we use RESTART even on initial startup as Sling is booting and
- * running fine on Karaf with RESTART
- */
- private static final String DEFAULT_STARTUP_MODE = STARTUP_MODE_RESTART;
-
- @Property(
- value = DEFAULT_STARTUP_MODE,
- options = {
- @PropertyOption(name = STARTUP_MODE_INSTALL, value = "install"),
- @PropertyOption(name = STARTUP_MODE_RESTART, value = "restart"),
- @PropertyOption(name = STARTUP_MODE_UPDATE, value = "update")
- })
- private static final String STARTUP_MODE_PARAMETER_NAME = "org.apache.sling.launchpad.startupmode";
+ private final Logger logger = LoggerFactory.getLogger(ConfigurableStartupHandler.class);
- private final Logger logger = LoggerFactory.getLogger(KarafStartupHandler.class);
+ public ConfigurableStartupHandler() {
+ }
- public KarafStartupHandler() {
+ @Reference
+ public void setConfigurationAdmin(final ConfigurationAdmin configurationAdmin) {
+ this.configurationAdmin = configurationAdmin;
}
@Activate
- private void activate(final BundleContext bundleContext, final Map<String, Object> properties) {
- logger.info("activate('{}', '{}')", bundleContext, properties);
- configure(properties);
+ private void activate(final BundleContext bundleContext, final ConfigurableStartupHandlerConfiguration configuration) {
+ logger.info("activating with Startup Mode '{}' and required services '{}'", configuration.startupMode(), configuration.requiredServices());
+ this.bundleContext = bundleContext;
+ configure(configuration);
+ serviceTracker = new ServiceTracker<>(bundleContext, StartupListener.class, new StartupListenerServiceTrackerCustomizer(bundleContext));
+ serviceTracker.open(true);
+ evaluate();
}
@Modified
- private void modified(Map<String, Object> properties) {
- logger.info("modified('{}')", properties);
- configure(properties);
+ private void modified(final ConfigurableStartupHandlerConfiguration configuration) {
+ logger.info("modifying with Startup Mode '{}' and required services '{}'", configuration.startupMode(), configuration.requiredServices());
+ configure(configuration);
}
@Deactivate
- private void deactivate(final BundleContext bundleContext) {
- logger.info("deactivate('{}')", bundleContext);
- }
-
- private void configure(Map<String, Object> properties) {
- logger.info("configure('{}')", properties);
- if (properties == null) {
- properties = new HashMap<String, Object>();
- }
- // startup mode
- String startupMode = (String) properties.get(STARTUP_MODE_PARAMETER_NAME);
- if (startupMode == null) {
- startupMode = DEFAULT_STARTUP_MODE;
+ private void deactivate() {
+ logger.info("deactivating");
+ serviceTracker.close();
+ synchronized (lock) {
+ bundleContext.removeServiceListener(serviceListener);
+ startupServiceRegistration.unregister();
+ startupServiceRegistration = null;
+ bundleContext = null;
}
- this.startupMode = StartupMode.valueOf(startupMode);
- logger.info("configured startup mode: {}", this.startupMode);
}
@Override
public StartupMode getMode() {
- logger.info("getMode(): {}", startupMode);
return startupMode;
}
- // TODO
@Override
public boolean isFinished() {
- logger.info("isFinished()");
- return true;
+ return finished.get();
}
- // TODO
@Override
public void waitWithStartup(boolean flag) {
- logger.info("waitWithStartup({})", flag);
+ logger.warn("Waiting with startup is not supported by this startup handler. Ignoring flag '{}'.", flag);
+ }
+
+ private void configure(final ConfigurableStartupHandlerConfiguration configuration) {
+ synchronized (lock) {
+ startupMode = configuration.startupMode();
+ requiredServices = configuration.requiredServices();
+ reconfigureStartupModeToRestartOnFinish = configuration.reconfigureStartupModeToRestartOnFinish();
+ bundleContext.removeServiceListener(serviceListener);
+ final StringBuilder filters = new StringBuilder();
+ for (final String clazz : requiredServices) {
+ filters.append(String.format("(%s=%s)", Constants.OBJECTCLASS, clazz));
+ }
+ final String filter = String.format(SERVICES_FILTERS_TEMPLATE, filters);
+ try {
+ bundleContext.addServiceListener(serviceListener, filter);
+ } catch (InvalidSyntaxException e) {
+ logger.error(e.getMessage(), e);
+ }
+ }
+ }
+
+ private void evaluate() {
+ logger.info("evaluating");
+ synchronized (lock) {
+ if (!finished.get()) {
+ for (final String clazz : requiredServices) {
+ if (bundleContext.getServiceReference(clazz) == null) {
+ logger.info("Required service of type '{}' is missing.", clazz);
+ return;
+ } else {
+ logger.info("Required service of type '{}' is found.", clazz);
+ }
+ }
+ finished.set(true);
+ for (final StartupListener startupListener : serviceTracker.getServices(new StartupListener[0])) {
+ try {
+ logger.info("Notifying {} about finished startup ('{}').", startupListener, startupMode);
+ startupListener.startupFinished(startupMode);
+ } catch (Exception e) {
+ logger.error(e.getMessage(), e);
+ }
+ }
+ registerStartupService();
+ if (reconfigureStartupModeToRestartOnFinish) {
+ reconfigureStartupMode();
+ }
+ }
+ }
+ }
+
+ private void registerStartupService() {
+ logger.info("registering Startup Service with Startup Mode '{}'", startupMode);
+ final Dictionary<String, Object> properties = new Hashtable<>();
+ properties.put(StartupMode.class.getName(), startupMode.name());
+ properties.put(Constants.SERVICE_DESCRIPTION, "Apache Sling Startup Service");
+ properties.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation");
+ final StartupService startupService = new ConfigurableStartupService(startupMode);
+ startupServiceRegistration = bundleContext.registerService(StartupService.class, startupService, properties);
+ }
+
+ private void reconfigureStartupMode() {
+ try {
+ final String pid = getClass().getName();
+ final Configuration configuration = configurationAdmin.getConfiguration(pid);
+ Dictionary<String, Object> properties = configuration.getProperties();
+ if (properties == null) {
+ properties = new Hashtable<>();
+ }
+ if (!StartupMode.RESTART.name().equals(properties.get("startupMode"))) {
+ properties.put("startupMode", StartupMode.RESTART.name());
+ configuration.update(properties);
+ }
+ } catch (Exception e) {
+ logger.error(e.getMessage(), e);
+ }
+ }
+
+ private class StartupListenerServiceTrackerCustomizer implements ServiceTrackerCustomizer<StartupListener, StartupListener> {
+
+ private final BundleContext bundleContext;
+
+ public StartupListenerServiceTrackerCustomizer(final BundleContext bundleContext) {
+ this.bundleContext = bundleContext;
+ }
+
+ @Override
+ public StartupListener addingService(final ServiceReference<StartupListener> serviceReference) {
+ final StartupListener startupListener = bundleContext.getService(serviceReference);
+ if (startupListener != null) {
+ try {
+ logger.info("Informing {} about startup ('{}', '{}').", new Object[]{startupListener, startupMode, finished});
+ startupListener.inform(startupMode, finished.get());
+ } catch (Exception e) {
+ logger.error(e.getMessage(), e);
+ }
+ }
+ return startupListener;
+ }
+
+ @Override
+ public void modifiedService(final ServiceReference<StartupListener> serviceReference, final StartupListener startupListener) {
+ }
+
+ @Override
+ public void removedService(final ServiceReference<StartupListener> serviceReference, final StartupListener startupListener) {
+ bundleContext.ungetService(serviceReference);
+ }
+
}
}
Added: sling/trunk/contrib/launchpad/karaf/org.apache.sling.launchpad.karaf/src/main/java/org/apache/sling/startup/configurable/ConfigurableStartupHandlerConfiguration.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/launchpad/karaf/org.apache.sling.launchpad.karaf/src/main/java/org/apache/sling/startup/configurable/ConfigurableStartupHandlerConfiguration.java?rev=1716822&view=auto
==============================================================================
--- sling/trunk/contrib/launchpad/karaf/org.apache.sling.launchpad.karaf/src/main/java/org/apache/sling/startup/configurable/ConfigurableStartupHandlerConfiguration.java (added)
+++ sling/trunk/contrib/launchpad/karaf/org.apache.sling.launchpad.karaf/src/main/java/org/apache/sling/startup/configurable/ConfigurableStartupHandlerConfiguration.java Fri Nov 27 10:23:40 2015
@@ -0,0 +1,64 @@
+/*
+ * 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.startup.configurable;
+
+import org.apache.sling.launchpad.api.StartupMode;
+import org.osgi.service.metatype.annotations.AttributeDefinition;
+import org.osgi.service.metatype.annotations.ObjectClassDefinition;
+import org.osgi.service.metatype.annotations.Option;
+
+@ObjectClassDefinition(
+ name = "Apache Sling Configurable StartupHandler",
+ description = ""
+)
+@interface ConfigurableStartupHandlerConfiguration {
+
+ String STARTUP_MODE_INSTALL = "INSTALL";
+
+ String STARTUP_MODE_RESTART = "RESTART";
+
+ String STARTUP_MODE_UPDATE = "UPDATE";
+
+ @AttributeDefinition(
+ name = "Startup Mode",
+ description = "The Startup Mode to announce when Sling's startup has finished.",
+ options = {
+ @Option(label = STARTUP_MODE_INSTALL, value = STARTUP_MODE_INSTALL),
+ @Option(label = STARTUP_MODE_RESTART, value = STARTUP_MODE_RESTART),
+ @Option(label = STARTUP_MODE_UPDATE, value = STARTUP_MODE_UPDATE)
+ }
+ )
+ StartupMode startupMode() default StartupMode.INSTALL;
+
+ @AttributeDefinition(
+ name = "Required services",
+ description = "The services which are required to be present to announce Sling's startup as finished."
+ )
+ String[] requiredServices() default {
+ "org.apache.sling.engine.SlingRequestProcessor",
+ "org.apache.sling.api.resource.ResourceResolverFactory"
+ };
+
+ @AttributeDefinition(
+ name = "Reconfigure Startup Mode to RESTART",
+ description = "If true, the Startup Mode will be reconfigured to RESTART on finished startup for next startup."
+ )
+ boolean reconfigureStartupModeToRestartOnFinish() default true;
+
+}
Added: sling/trunk/contrib/launchpad/karaf/org.apache.sling.launchpad.karaf/src/main/java/org/apache/sling/startup/configurable/ConfigurableStartupService.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/launchpad/karaf/org.apache.sling.launchpad.karaf/src/main/java/org/apache/sling/startup/configurable/ConfigurableStartupService.java?rev=1716822&view=auto
==============================================================================
--- sling/trunk/contrib/launchpad/karaf/org.apache.sling.launchpad.karaf/src/main/java/org/apache/sling/startup/configurable/ConfigurableStartupService.java (added)
+++ sling/trunk/contrib/launchpad/karaf/org.apache.sling.launchpad.karaf/src/main/java/org/apache/sling/startup/configurable/ConfigurableStartupService.java Fri Nov 27 10:23:40 2015
@@ -0,0 +1,37 @@
+/*
+ * 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.startup.configurable;
+
+import org.apache.sling.launchpad.api.StartupMode;
+import org.apache.sling.launchpad.api.StartupService;
+
+public class ConfigurableStartupService implements StartupService {
+
+ private final StartupMode startupMode;
+
+ public ConfigurableStartupService(final StartupMode startupMode) {
+ this.startupMode = startupMode;
+ }
+
+ @Override
+ public StartupMode getStartupMode() {
+ return startupMode;
+ }
+
+}