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-deploymentpackage.git
commit f6dd25e859f9d4cda726ed313772e4589b6720cd Author: Carsten Ziegeler <[email protected]> AuthorDate: Tue Jan 18 08:03:00 2011 +0000 First version of deployment package support for the installer. git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1060231 13f79535-47bb-0310-9956-ffa450edef68 --- pom.xml | 83 +++++++++++++ .../factories/deploypck/impl/Activator.java | 101 ++++++++++++++++ .../factories/deploypck/impl/DeployPckTask.java | 128 ++++++++++++++++++++ .../deploypck/impl/DeploymentPackageInstaller.java | 129 +++++++++++++++++++++ 4 files changed, 441 insertions(+) diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..63ab30d --- /dev/null +++ b/pom.xml @@ -0,0 +1,83 @@ +<!-- + 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>10</version> + <relativePath>../../../parent/pom.xml</relativePath> + </parent> + + <artifactId>org.apache.sling.installer.factory.deploymentpackage</artifactId> + <version>0.0.1-SNAPSHOT</version> + <packaging>bundle</packaging> + + <name>Apache Sling Deployment Package Installer</name> + <description> + Provides support for deployment packages to the Apache Sling OSGi installer + </description> + + <scm> + <connection>scm:svn:http://svn.apache.org/repos/asf/sling/trunk/installer/factories/deploymentpck</connection> + <developerConnection> scm:svn:https://svn.apache.org/repos/asf/sling/trunk/installer/factories/deploymentpck</developerConnection> + <url>http://svn.apache.org/viewvc/sling/trunk/installer/factories/deploymentpck/</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.deploypck.impl.Activator + </Bundle-Activator> + <Private-Package> + org.apache.sling.installer.factories.deploypck..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> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.compendium</artifactId> + </dependency> + <dependency> + <groupId>org.apache.sling</groupId> + <artifactId>org.apache.sling.installer.core</artifactId> + <version>3.0.1-SNAPSHOT</version> + <scope>provided</scope> + </dependency> + </dependencies> +</project> diff --git a/src/main/java/org/apache/sling/installer/factories/deploypck/impl/Activator.java b/src/main/java/org/apache/sling/installer/factories/deploypck/impl/Activator.java new file mode 100644 index 0000000..f5502c4 --- /dev/null +++ b/src/main/java/org/apache/sling/installer/factories/deploypck/impl/Activator.java @@ -0,0 +1,101 @@ +/* + * 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.deploypck.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.ServiceEvent; +import org.osgi.framework.ServiceListener; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.ServiceRegistration; +import org.osgi.service.deploymentadmin.DeploymentAdmin; + +public class Activator implements ServiceListener, BundleActivator { + + private static final String DEPLOYMENT_ADMIN = "org.osgi.service.deploymentadmin.DeploymentAdmin"; + + /** The bundle context. */ + private BundleContext bundleContext; + + /** The service reference to the deployment admin. */ + private ServiceReference deploymentAdminReference; + + /** The service registration for the install service. */ + private ServiceRegistration serviceReg; + + /** + * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext) + */ + public void start(final BundleContext context) throws Exception { + this.bundleContext = context; + this.bundleContext.addServiceListener(this, "(" + Constants.OBJECTCLASS + + "=" + DEPLOYMENT_ADMIN + ")"); + + } + /** + * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext) + */ + public void stop(final BundleContext context) throws Exception { + this.bundleContext.removeServiceListener(this); + this.unregister(); + this.bundleContext = null; + } + + /** + * Wait for the deployment admin service. + * @see org.osgi.framework.ServiceListener#serviceChanged(org.osgi.framework.ServiceEvent) + */ + public synchronized void serviceChanged(ServiceEvent event) { + if ( event.getType() == ServiceEvent.REGISTERED && this.deploymentAdminReference == null ) { + this.deploymentAdminReference = this.bundleContext.getServiceReference(DEPLOYMENT_ADMIN); + if ( this.deploymentAdminReference != null ) { + final DeploymentAdmin deploymentAdmin = (DeploymentAdmin) this.bundleContext.getService(this.deploymentAdminReference); + if ( deploymentAdmin == null ) { + this.deploymentAdminReference = null; + } else { + final Dictionary<String, Object> props = new Hashtable<String, Object>(); + props.put(Constants.SERVICE_DESCRIPTION, "Apache Sling Installer Support for Deployment Packages"); + props.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation"); + this.serviceReg = this.bundleContext.registerService(new String[] {ResourceTransformer.class.getName(), + InstallTaskFactory.class.getName()}, + new DeploymentPackageInstaller(deploymentAdmin), props); + } + } + } else if ( event.getType() == ServiceEvent.UNREGISTERING && this.deploymentAdminReference != null ) { + this.unregister(); + } + } + + private void unregister() { + if ( this.deploymentAdminReference != null ) { + this.bundleContext.ungetService(this.deploymentAdminReference); + this.deploymentAdminReference = null; + } + if ( serviceReg != null ) { + serviceReg.unregister(); + serviceReg = null; + } + } +} diff --git a/src/main/java/org/apache/sling/installer/factories/deploypck/impl/DeployPckTask.java b/src/main/java/org/apache/sling/installer/factories/deploypck/impl/DeployPckTask.java new file mode 100644 index 0000000..bd8c829 --- /dev/null +++ b/src/main/java/org/apache/sling/installer/factories/deploypck/impl/DeployPckTask.java @@ -0,0 +1,128 @@ +/* + * 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.deploypck.impl; + +import java.io.IOException; +import java.io.InputStream; + +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.Version; +import org.osgi.service.deploymentadmin.DeploymentAdmin; +import org.osgi.service.deploymentadmin.DeploymentException; +import org.osgi.service.deploymentadmin.DeploymentPackage; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DeployPckTask extends InstallTask { + + private static final String INSTALL_ORDER = "55-"; + + private final DeploymentAdmin deploymentAdmin; + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + public DeployPckTask(final TaskResourceGroup grp, final DeploymentAdmin dp) { + super(grp); + this.deploymentAdmin = dp; + } + + @Override + public void execute(final InstallationContext ctx) { + final TaskResource tr = this.getResource(); + + // get and check symbolic name + final String symbolicName = (String)tr.getAttribute(DeploymentPackageInstaller.DEPLOYMENTPACKAGE_SYMBOLICMAME); + if ( symbolicName == null ) { + logger.error("Resource {} has no symbolic name - ignoring.", tr); + this.getResourceGroup().setFinishState(ResourceState.IGNORED); + return; + } + + // get package if available + final DeploymentPackage dp = this.deploymentAdmin.getDeploymentPackage(symbolicName); + + if ( tr.getState() == ResourceState.INSTALL) { + InputStream is = null; + try { + is = tr.getInputStream(); + if ( is == null ) { + // something went wrong + logger.error("Resource {} does not provide an input stream!", tr); + this.getResourceGroup().setFinishState(ResourceState.IGNORED); + } else { + final Version newVersion = new Version((String)tr.getAttribute(DeploymentPackageInstaller.DEPLOYMENTPACKAGE_VERSION)); + // check version + if ( dp != null ) { + final int compare = dp.getVersion().compareTo(newVersion); + if (compare < 0) { + // installed version is lower -> update + this.deploymentAdmin.installDeploymentPackage(is); + ctx.log("Installed deployment package {} : {}", symbolicName, newVersion); + this.getResourceGroup().setFinishState(ResourceState.INSTALLED); + } else if (compare >= 0) { + logger.debug("Deployment package " + symbolicName + " " + newVersion + + " is not installed, package with higher or same version is already installed."); + } + } else { + this.deploymentAdmin.installDeploymentPackage(is); + ctx.log("Installed deployment package {} : {}", symbolicName, newVersion); + this.getResourceGroup().setFinishState(ResourceState.INSTALLED); + } + } + } catch (final DeploymentException e) { + logger.error("Unable to install deployment package {} from resource {}", + symbolicName, + tr); + this.getResourceGroup().setFinishState(ResourceState.IGNORED); + } catch (final IOException ioe) { + logger.error("Unable to install deployment package {} from resource {}", + symbolicName, + tr); + this.getResourceGroup().setFinishState(ResourceState.IGNORED); + } finally { + if ( is != null ) { + try { + is.close(); + } catch (IOException ignore) {} + } + } + } else { // uninstall + if ( dp != null ) { + try { + dp.uninstall(); + } catch (final DeploymentException e) { + logger.error("Unable to uninstall deployment package {} from resource {}", symbolicName, tr); + } + } else { + logger.info("Unable to find deployment package with symbolic name {} for uninstalling.", + symbolicName); + } + this.getResourceGroup().setFinishState(ResourceState.UNINSTALLED); + } + } + + @Override + public String getSortKey() { + return INSTALL_ORDER + getResource().getURL(); + } +} diff --git a/src/main/java/org/apache/sling/installer/factories/deploypck/impl/DeploymentPackageInstaller.java b/src/main/java/org/apache/sling/installer/factories/deploypck/impl/DeploymentPackageInstaller.java new file mode 100644 index 0000000..fa0337f --- /dev/null +++ b/src/main/java/org/apache/sling/installer/factories/deploypck/impl/DeploymentPackageInstaller.java @@ -0,0 +1,129 @@ +/* + * 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.deploypck.impl; + +import java.io.IOException; +import java.io.InputStream; +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.InstallTask; +import org.apache.sling.installer.api.tasks.InstallTaskFactory; +import org.apache.sling.installer.api.tasks.RegisteredResource; +import org.apache.sling.installer.api.tasks.ResourceTransformer; +import org.apache.sling.installer.api.tasks.TaskResourceGroup; +import org.apache.sling.installer.api.tasks.TransformationResult; +import org.osgi.service.deploymentadmin.DeploymentAdmin; + +/** + * This is an extension for the OSGi installer + * It listens for files ending with ".dp" and installs them through + * the deployment package admin. + */ +public class DeploymentPackageInstaller + implements ResourceTransformer, InstallTaskFactory { + + public static final String DEPLOYMENTPACKAGE_SYMBOLICMAME = "DeploymentPackage-SymbolicName"; + public static final String DEPLOYMENTPACKAGE_VERSION = "DeploymentPackage-Version"; + + private static final String TYPE_DP = "dp"; + + private final DeploymentAdmin deploymentAdmin; + + public DeploymentPackageInstaller(final DeploymentAdmin dpA) { + this.deploymentAdmin = dpA; + } + + /** + * @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) ) { + try { + final Manifest m = getManifest(resource.getInputStream()); + if (m != null) { + final String sn = m.getMainAttributes().getValue(DEPLOYMENTPACKAGE_SYMBOLICMAME); + if (sn != null) { + final String v = m.getMainAttributes().getValue(DEPLOYMENTPACKAGE_VERSION); + if (v != null) { + final Map<String, Object> attr = new HashMap<String, Object>(); + attr.put(DEPLOYMENTPACKAGE_SYMBOLICMAME, sn); + attr.put(DEPLOYMENTPACKAGE_VERSION, v.toString()); + + final TransformationResult tr = new TransformationResult(); + tr.setId(sn); + tr.setResourceType(TYPE_DP); + tr.setAttributes(attr); + + return new TransformationResult[] {tr}; + } + } + } + } catch (final IOException ignore) { + // ignore + } + } + return null; + } + + /** + * Read the manifest from supplied input stream, which is closed before return. + */ + private Manifest getManifest(final InputStream ins) throws IOException { + Manifest result = null; + + JarInputStream jis = null; + try { + jis = new JarInputStream(ins); + result= jis.getManifest(); + + } finally { + + // close the jar stream or the inputstream, 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; + } + + /** + * @see org.apache.sling.installer.api.tasks.InstallTaskFactory#createTask(org.apache.sling.installer.api.tasks.TaskResourceGroup) + */ + public InstallTask createTask(final TaskResourceGroup toActivate) { + if ( toActivate.getActiveResource().getType().equals(TYPE_DP) ) { + return new DeployPckTask(toActivate, this.deploymentAdmin); + } + return null; + } +} -- To stop receiving notification emails like this one, please contact "[email protected]" <[email protected]>.
