This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-installer-factory-subsystems.git
commit e794198ff84fb758979ad6f797c1c4fc70d00693 Author: Carsten Ziegeler <[email protected]> AuthorDate: Wed Aug 6 16:20:32 2014 +0000 Initial subsystem support for the OSGi installer git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1616266 13f79535-47bb-0310-9956-ffa450edef68 --- pom.xml | 86 ++++++ .../factories/subsystems/impl/Activator.java | 100 +++++++ .../subsystems/impl/InstallSubsystemTask.java | 60 ++++ .../subsystems/impl/SubsystemInstaller.java | 304 +++++++++++++++++++++ .../subsystems/impl/UninstallSubsystemTask.java | 73 +++++ .../subsystems/impl/UpdateSubsystemTask.java | 77 ++++++ 6 files changed, 700 insertions(+) diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..d3f0918 --- /dev/null +++ b/pom.xml @@ -0,0 +1,86 @@ +<!-- + 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. +--> +<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</artifactId> + <version>18</version> + <relativePath>../../../parent/pom.xml</relativePath> + </parent> + + <artifactId>org.apache.sling.installer.factory.subsystems</artifactId> + <version>0.0.1-SNAPSHOT</version> + <packaging>bundle</packaging> + + <name>Apache Sling Subsystems Installer</name> + <description> + Provides support for subsystems to the Apache Sling OSGi installer + </description> + + <scm> + <connection>scm:svn:http://svn.apache.org/repos/asf/sling/trunk/installer/factories/subsystems</connection> + <developerConnection> scm:svn:https://svn.apache.org/repos/asf/sling/trunk/installer/factories/subsystems</developerConnection> + <url>http://svn.apache.org/viewvc/sling/trunk/installer/factories/subsystems/</url> + </scm> + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Bundle-Activator> + org.apache.sling.installer.factories.subsystems.impl.Activator + </Bundle-Activator> + <Private-Package> + org.apache.sling.installer.factories.subsystems.impl.* + </Private-Package> + </instructions> + </configuration> + </plugin> + </plugins> + </build> + + <dependencies> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + <version>5.0.0</version> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>5.0.0</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.apache.sling</groupId> + <artifactId>org.apache.sling.installer.api</artifactId> + <version>1.0.0</version> + <scope>provided</scope> + </dependency> + </dependencies> +</project> diff --git a/src/main/java/org/apache/sling/installer/factories/subsystems/impl/Activator.java b/src/main/java/org/apache/sling/installer/factories/subsystems/impl/Activator.java new file mode 100644 index 0000000..2a4e173 --- /dev/null +++ b/src/main/java/org/apache/sling/installer/factories/subsystems/impl/Activator.java @@ -0,0 +1,100 @@ +/* + * 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.installer.factories.subsystems.impl; + +import java.util.Dictionary; +import java.util.Hashtable; + +import org.apache.sling.installer.api.tasks.InstallTaskFactory; +import org.apache.sling.installer.api.tasks.ResourceTransformer; +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.ServiceRegistration; +import org.osgi.service.subsystem.Subsystem; +import org.osgi.service.subsystem.SubsystemConstants; +import org.osgi.util.tracker.ServiceTracker; +import org.osgi.util.tracker.ServiceTrackerCustomizer; + +public class Activator implements BundleActivator { + + /** The service tracker for the root subsystem */ + private ServiceTracker<Subsystem, Subsystem> rootSubsystemTracker; + + /** The service registration for the installer service. */ + private ServiceRegistration<?> serviceReg; + + /** + * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext) + */ + public void start(final BundleContext context) throws Exception { + this.rootSubsystemTracker = new ServiceTracker<Subsystem, Subsystem>(context, + "&(" + Constants.OBJECTCLASS + "=" + Subsystem.class.getName() + ")" + + "(" + SubsystemConstants.SUBSYSTEM_ID_PROPERTY + "=0)", + + new ServiceTrackerCustomizer<Subsystem, Subsystem>() { + + public Subsystem addingService(final ServiceReference<Subsystem> reference) { + final Subsystem service = context.getService(reference); + if ( service != null ) { + registerInstaller(context, service); + } + return service; + } + + public void modifiedService(final ServiceReference<Subsystem> reference, final Subsystem service) { + // nothing to do + } + + public void removedService(final ServiceReference<Subsystem> reference, final Subsystem service) { + unregisterInstaller(); + } + + }); + this.rootSubsystemTracker.open(); + } + + /** + * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext) + */ + public void stop(final BundleContext context) throws Exception { + if ( this.rootSubsystemTracker != null ) { + this.rootSubsystemTracker.close(); + this.rootSubsystemTracker = null; + } + this.unregisterInstaller(); + } + + private void registerInstaller(final BundleContext context, final Subsystem rootSubsystem) { + final Dictionary<String, Object> props = new Hashtable<String, Object>(); + props.put(Constants.SERVICE_DESCRIPTION, "Apache Sling Installer Support for Subsystems"); + props.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation"); + this.serviceReg = context.registerService( + new String[] {ResourceTransformer.class.getName(), InstallTaskFactory.class.getName()}, + new SubsystemInstaller(rootSubsystem, context), props); + } + + private void unregisterInstaller() { + if ( serviceReg != null ) { + serviceReg.unregister(); + serviceReg = null; + } + } +} diff --git a/src/main/java/org/apache/sling/installer/factories/subsystems/impl/InstallSubsystemTask.java b/src/main/java/org/apache/sling/installer/factories/subsystems/impl/InstallSubsystemTask.java new file mode 100644 index 0000000..3f1e10f --- /dev/null +++ b/src/main/java/org/apache/sling/installer/factories/subsystems/impl/InstallSubsystemTask.java @@ -0,0 +1,60 @@ +/* + * 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.installer.factories.subsystems.impl; + +import java.io.IOException; + +import org.apache.sling.installer.api.tasks.ChangeStateTask; +import org.apache.sling.installer.api.tasks.InstallTask; +import org.apache.sling.installer.api.tasks.InstallationContext; +import org.apache.sling.installer.api.tasks.ResourceState; +import org.apache.sling.installer.api.tasks.TaskResource; +import org.apache.sling.installer.api.tasks.TaskResourceGroup; +import org.osgi.service.subsystem.Subsystem; + +public class InstallSubsystemTask extends InstallTask { + + private static final String INSTALL_ORDER = "53-"; + + private final Subsystem rootSubsystem; + + public InstallSubsystemTask(final TaskResourceGroup grp, final Subsystem rootSubsystem) { + super(grp); + this.rootSubsystem = rootSubsystem; + } + + @Override + public void execute(final InstallationContext ctx) { + final TaskResource tr = this.getResource(); + ctx.log("Installing new subsystem from {}", tr); + + try { + this.rootSubsystem.install(tr.getURL(), tr.getInputStream()); + ctx.addTaskToCurrentCycle(new ChangeStateTask(this.getResourceGroup(), ResourceState.INSTALLED)); + } catch (final IOException e) { + ctx.log("Unable to install subsystem {} : {}", tr, e); + ctx.addTaskToCurrentCycle(new ChangeStateTask(this.getResourceGroup(), ResourceState.IGNORED)); + } + } + + @Override + public String getSortKey() { + return INSTALL_ORDER + getResource().getURL(); + } +} diff --git a/src/main/java/org/apache/sling/installer/factories/subsystems/impl/SubsystemInstaller.java b/src/main/java/org/apache/sling/installer/factories/subsystems/impl/SubsystemInstaller.java new file mode 100644 index 0000000..2b4b3c5 --- /dev/null +++ b/src/main/java/org/apache/sling/installer/factories/subsystems/impl/SubsystemInstaller.java @@ -0,0 +1,304 @@ +/* + * 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.installer.factories.subsystems.impl; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.jar.JarInputStream; +import java.util.jar.Manifest; + +import org.apache.sling.installer.api.InstallableResource; +import org.apache.sling.installer.api.tasks.ChangeStateTask; +import org.apache.sling.installer.api.tasks.InstallTask; +import org.apache.sling.installer.api.tasks.InstallTaskFactory; +import org.apache.sling.installer.api.tasks.RegisteredResource; +import org.apache.sling.installer.api.tasks.ResourceState; +import org.apache.sling.installer.api.tasks.ResourceTransformer; +import org.apache.sling.installer.api.tasks.TaskResource; +import org.apache.sling.installer.api.tasks.TaskResourceGroup; +import org.apache.sling.installer.api.tasks.TransformationResult; +import org.osgi.framework.BundleContext; +import org.osgi.framework.InvalidSyntaxException; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.Version; +import org.osgi.service.subsystem.Subsystem; +import org.osgi.service.subsystem.SubsystemConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This is an extension for the OSGi installer + * It listens for files ending with ".esa" and a proper manifest. Though subsystems does + * not require a complete manifest, the installer supports only subsystems with the + * basic info. + */ +public class SubsystemInstaller + implements ResourceTransformer, InstallTaskFactory { + + private static final String TYPE_SUBSYSTEM = "esa"; + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + private final Subsystem rootSubsystem; + + private final BundleContext bundleContext; + + public SubsystemInstaller(final Subsystem root, final BundleContext bundleContext) { + this.rootSubsystem = root; + this.bundleContext = bundleContext; + } + + /** + * @see org.apache.sling.installer.api.tasks.ResourceTransformer#transform(org.apache.sling.installer.api.tasks.RegisteredResource) + */ + public TransformationResult[] transform(final RegisteredResource resource) { + if ( resource.getType().equals(InstallableResource.TYPE_FILE) ) { + if ( resource.getURL().endsWith("." + TYPE_SUBSYSTEM) ) { + logger.info("Found potential subsystem resource {}", resource); + final SubsystemInfo headers = readSubsystemHeaders(resource); + if ( headers != null ) { + // check the version for validity + boolean validVersion = true; + try { + new Version(headers.version); + } catch (final IllegalArgumentException iae) { + logger.info("Rejecting subsystem {} from {} due to invalid version information: {}.", + new Object[] {headers.symbolicName, resource, headers.version}); + validVersion = false; + } + if ( validVersion ) { + final Map<String, Object> attr = new HashMap<String, Object>(); + attr.put(SubsystemConstants.SUBSYSTEM_SYMBOLICNAME, headers.symbolicName); + attr.put(SubsystemConstants.SUBSYSTEM_VERSION, headers.version); + + final TransformationResult tr = new TransformationResult(); + tr.setId(headers.symbolicName); + tr.setResourceType(TYPE_SUBSYSTEM); + tr.setAttributes(attr); + tr.setVersion(new Version(headers.version)); + + return new TransformationResult[] {tr}; + } + + } else { + logger.info("Subsystem resource does not have required headers."); + } + } + } + return null; + } + + /** + * Check that the required attributes are available. + * This is just a sanity check + */ + private SubsystemInfo checkResource(final TaskResourceGroup toActivate) { + final TaskResource rsrc = toActivate.getActiveResource(); + + SubsystemInfo result = null; + final String symbolicName = (String) rsrc.getAttribute(SubsystemConstants.SUBSYSTEM_SYMBOLICNAME); + if ( symbolicName == null ) { + logger.error("Subsystem resource is missing symbolic name {}", rsrc); + } else { + final String version = (String)rsrc.getAttribute(SubsystemConstants.SUBSYSTEM_VERSION); + if ( version == null ) { + logger.error("Subsystem resource is missing version {}", rsrc); + } else { + // check the version for validity + boolean validVersion = true; + try { + new Version(version); + } catch (final IllegalArgumentException iae) { + logger.info("Rejecting subsystem {} from {} due to invalid version information: {}.", + new Object[] {symbolicName, rsrc, version}); + validVersion = false; + } + if ( validVersion ) { + result = new SubsystemInfo(); + result.symbolicName = symbolicName; + result.version = version; + } + } + } + return result; + } + + private ServiceReference<Subsystem> getSubsystemReference(final String symbolicName) { + // search a subsystem with the symbolic name + ServiceReference<Subsystem> ref = null; + try { + final Collection<ServiceReference<Subsystem>> refs = this.bundleContext.getServiceReferences(Subsystem.class, "(subsystem.symbolicName=" + symbolicName + ")"); + if ( refs.size() > 0 ) { + ref = refs.iterator().next(); + } + } catch (final InvalidSyntaxException e) { + logger.error("Problem searching for subsystem with symbolic name " + symbolicName, e); + } + return ref; + } + + /** + * @see org.apache.sling.installer.api.tasks.InstallTaskFactory#createTask(org.apache.sling.installer.api.tasks.TaskResourceGroup) + */ + public InstallTask createTask(final TaskResourceGroup toActivate) { + final InstallTask result; + + final TaskResource rsrc = toActivate.getActiveResource(); + if ( rsrc.getType().equals(TYPE_SUBSYSTEM) ) { + + // check if the required info is available + final SubsystemInfo info = checkResource(toActivate); + if ( info == null ) { + // ignore as info is missing + result = new ChangeStateTask(toActivate, ResourceState.IGNORED); + } else { + // search a subsystem with the symbolic name + final ServiceReference<Subsystem> ref = this.getSubsystemReference(info.symbolicName); + + final Version newVersion = new Version(info.version); + final Version oldVersion = (ref == null ? null : (Version)ref.getProperty("subsystem.version")); + + // Install + if ( rsrc.getState() == ResourceState.INSTALL ) { + if ( oldVersion != null ) { + + final int compare = oldVersion.compareTo(newVersion); + if (compare < 0) { + // installed version is lower -> update + result = new UpdateSubsystemTask(toActivate, this.bundleContext, ref, this.rootSubsystem); + } else { + // TODO - support SNAPSHOT? + logger.debug("{} is not installed, subsystem with same or higher version is already installed: {}", info, newVersion); + result = new ChangeStateTask(toActivate, ResourceState.IGNORED); + } + } else { + result = new InstallSubsystemTask(toActivate, this.rootSubsystem); + } + + // Uninstall + } else if ( rsrc.getState() == ResourceState.UNINSTALL ) { + if ( oldVersion == null ) { + logger.error("Nothing to uninstall. {} is currently not installed.", info); + result = new ChangeStateTask(toActivate, ResourceState.IGNORED); + } else { + + final int compare = oldVersion.compareTo(newVersion); + if ( compare == 0 ) { + result = new UninstallSubsystemTask(toActivate, this.bundleContext, ref); + } else { + logger.error("Nothing to uninstall. {} is currently not installed, different version is installed {}", info, oldVersion); + result = new ChangeStateTask(toActivate, ResourceState.IGNORED); + } + } + } else { + result = null; + } + } + } else { + result = null; + } + return result; + } + + /** + * Read the manifest from supplied input stream, which is closed before return. + */ + private static Manifest getManifest(final RegisteredResource rsrc, final Logger logger) + throws IOException { + final InputStream ins = rsrc.getInputStream(); + + Manifest result = null; + + if ( ins != null ) { + JarInputStream jis = null; + try { + jis = new JarInputStream(ins); + result = jis.getManifest(); + + // SLING-2288 : if this is a jar file, but the manifest is not the first entry + // log a warning + if ( rsrc.getURL().endsWith(".jar") && result == null ) { + logger.warn("Resource {} does not have the manifest as its first entry in the archive. If this is " + + "a subsystem, make sure to put the manifest first in the jar file.", rsrc.getURL()); + } + } finally { + + // close the jar stream or the input stream, if the jar + // stream is set, we don't need to close the input stream + // since closing the jar stream closes the input stream + if (jis != null) { + try { + jis.close(); + } catch (IOException ignore) { + } + } else { + try { + ins.close(); + } catch (IOException ignore) { + } + } + } + } + return result; + } + + final static public class SubsystemInfo { + public String symbolicName; + public String version; + @Override + + public String toString() { + return "Subsystem[symbolicName=" + symbolicName + ", version=" + + version + "]"; + } + + } + + /** + * Read the subsystem info from the manifest (if available) + */ + private SubsystemInfo readSubsystemHeaders(final RegisteredResource resource) { + try { + final Manifest m = SubsystemInstaller.getManifest(resource, logger); + if (m != null) { + final String sn = m.getMainAttributes().getValue(SubsystemConstants.SUBSYSTEM_SYMBOLICNAME); + if (sn != null) { + final String v = m.getMainAttributes().getValue(SubsystemConstants.SUBSYSTEM_VERSION); + final int paramPos = sn.indexOf(';'); + final String symbolicName = (paramPos == -1 ? sn : sn.substring(0, paramPos)); + final SubsystemInfo headers = new SubsystemInfo(); + headers.symbolicName = symbolicName; + headers.version = v; + + // if no version is specified, use default version + if ( headers.version == null ) { + headers.version = "0.0.0.0"; + } + return headers; + } + } + } catch (final IOException ignore) { + // ignore + } + return null; + } +} diff --git a/src/main/java/org/apache/sling/installer/factories/subsystems/impl/UninstallSubsystemTask.java b/src/main/java/org/apache/sling/installer/factories/subsystems/impl/UninstallSubsystemTask.java new file mode 100644 index 0000000..4ae0dab --- /dev/null +++ b/src/main/java/org/apache/sling/installer/factories/subsystems/impl/UninstallSubsystemTask.java @@ -0,0 +1,73 @@ +/* + * 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.installer.factories.subsystems.impl; + +import org.apache.sling.installer.api.tasks.ChangeStateTask; +import org.apache.sling.installer.api.tasks.InstallTask; +import org.apache.sling.installer.api.tasks.InstallationContext; +import org.apache.sling.installer.api.tasks.ResourceState; +import org.apache.sling.installer.api.tasks.TaskResource; +import org.apache.sling.installer.api.tasks.TaskResourceGroup; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; +import org.osgi.service.subsystem.Subsystem; + +public class UninstallSubsystemTask extends InstallTask { + + private static final String INSTALL_ORDER = "52-"; + + private final ServiceReference<Subsystem> subsystemReference; + + private final BundleContext bundleContext; + + public UninstallSubsystemTask(final TaskResourceGroup grp, + final BundleContext bundleContext, + final ServiceReference<Subsystem> ref) { + super(grp); + this.bundleContext = bundleContext; + this.subsystemReference = ref; + } + + @Override + public void execute(final InstallationContext ctx) { + final TaskResource tr = this.getResource(); + ctx.log("Uninstalling subsystem from {}", tr); + + Subsystem subsystem = null; + try { + subsystem = this.bundleContext.getService(this.subsystemReference); + if ( subsystem != null ) { + subsystem.uninstall(); + ctx.addTaskToCurrentCycle(new ChangeStateTask(this.getResourceGroup(), ResourceState.UNINSTALLED)); + } else { + ctx.log("Unable to uninstall subsystem {}.", tr); + ctx.addTaskToCurrentCycle(new ChangeStateTask(this.getResourceGroup(), ResourceState.IGNORED)); + } + } finally { + if ( subsystem != null ) { + this.bundleContext.ungetService(this.subsystemReference); + } + } + } + + @Override + public String getSortKey() { + return INSTALL_ORDER + getResource().getURL(); + } +} diff --git a/src/main/java/org/apache/sling/installer/factories/subsystems/impl/UpdateSubsystemTask.java b/src/main/java/org/apache/sling/installer/factories/subsystems/impl/UpdateSubsystemTask.java new file mode 100644 index 0000000..3da254b --- /dev/null +++ b/src/main/java/org/apache/sling/installer/factories/subsystems/impl/UpdateSubsystemTask.java @@ -0,0 +1,77 @@ +/* + * 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.installer.factories.subsystems.impl; + +import org.apache.sling.installer.api.tasks.ChangeStateTask; +import org.apache.sling.installer.api.tasks.InstallTask; +import org.apache.sling.installer.api.tasks.InstallationContext; +import org.apache.sling.installer.api.tasks.ResourceState; +import org.apache.sling.installer.api.tasks.TaskResource; +import org.apache.sling.installer.api.tasks.TaskResourceGroup; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; +import org.osgi.service.subsystem.Subsystem; + +public class UpdateSubsystemTask extends InstallTask { + + private static final String INSTALL_ORDER = "54-"; + + private final Subsystem rootSubsystem; + + private final ServiceReference<Subsystem> subsystemReference; + + private final BundleContext bundleContext; + + public UpdateSubsystemTask(final TaskResourceGroup grp, + final BundleContext bundleContext, + final ServiceReference<Subsystem> ref, + final Subsystem rootSubsystem) { + super(grp); + this.bundleContext = bundleContext; + this.subsystemReference = ref; + this.rootSubsystem = rootSubsystem; + } + + @Override + public void execute(final InstallationContext ctx) { + final TaskResource tr = this.getResource(); + ctx.log("Updating subsystem from {}", tr); + + Subsystem subsystem = null; + try { + subsystem = this.bundleContext.getService(this.subsystemReference); + if ( subsystem != null ) { + subsystem.uninstall(); + ctx.addTaskToCurrentCycle(new InstallSubsystemTask(this.getResourceGroup(), this.rootSubsystem)); + } else { + ctx.log("Unable to update subsystem {}.", tr); + ctx.addTaskToCurrentCycle(new ChangeStateTask(this.getResourceGroup(), ResourceState.IGNORED)); + } + } finally { + if ( subsystem != null ) { + this.bundleContext.ungetService(this.subsystemReference); + } + } + } + + @Override + public String getSortKey() { + return INSTALL_ORDER + getResource().getURL(); + } +} -- To stop receiving notification emails like this one, please contact "[email protected]" <[email protected]>.
