Package org.apache.felix.deploymentadmin.spi

Source Code of org.apache.felix.deploymentadmin.spi.UpdateCommand

/*
* 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.felix.deploymentadmin.spi;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

import org.apache.felix.deploymentadmin.AbstractDeploymentPackage;
import org.apache.felix.deploymentadmin.AbstractInfo;
import org.apache.felix.deploymentadmin.BundleInfoImpl;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Version;
import org.osgi.service.deploymentadmin.DeploymentException;
import org.osgi.service.log.LogService;

/**
* Command that installs all bundles described in the source deployment package
* of a deployment session. If a bundle was already defined in the target
* deployment package of the same session it is updated, otherwise the bundle is
* simply installed.
*/
public class UpdateCommand extends Command {

    protected void doExecute(DeploymentSessionImpl session) throws Exception {
        AbstractDeploymentPackage source = session.getSourceAbstractDeploymentPackage();
        AbstractDeploymentPackage targetPackage = session.getTargetAbstractDeploymentPackage();
        BundleContext context = session.getBundleContext();
        LogService log = session.getLog();

        Map expectedBundles = new HashMap();
        AbstractInfo[] bundleInfos = (AbstractInfo[]) source.getBundleInfos();
        for (int i = 0; i < bundleInfos.length; i++) {
            AbstractInfo bundleInfo = bundleInfos[i];
            if (!bundleInfo.isMissing()) {
                expectedBundles.put(bundleInfo.getPath(), bundleInfo);
            }
        }

        try {
            while (!expectedBundles.isEmpty()) {
                AbstractInfo entry = source.getNextEntry();
                if (entry == null) {
                    throw new DeploymentException(CODE_OTHER_ERROR, "Expected more bundles in the stream: " + expectedBundles.keySet());
                }

                String name = entry.getPath();
                BundleInfoImpl bundleInfo = (BundleInfoImpl) expectedBundles.remove(name);
                if (bundleInfo == null) {
                    throw new DeploymentException(CODE_OTHER_ERROR, "Resource '" + name + "' is not described in the manifest.");
                }

                String bsn = bundleInfo.getSymbolicName();
                Version sourceVersion = bundleInfo.getVersion();

                Bundle bundle = targetPackage.getBundle(bsn);
                try {
                    if (bundle == null) {
                        // new bundle, install it
                        bundle = context.installBundle(BUNDLE_LOCATION_PREFIX + bsn, new BundleInputStream(source.getCurrentEntryStream()));
                        addRollback(new UninstallBundleRunnable(bundle, log));
                    }
                    else {
                        // existing bundle, update it
                        Version currentVersion = getVersion(bundle);
                        if (!sourceVersion.equals(currentVersion)) {
                            bundle.update(new BundleInputStream(source.getCurrentEntryStream()));
                            addRollback(new UpdateBundleRunnable(bundle, targetPackage, log));
                        }
                    }
                }
                catch (Exception be) {
                    if (isCancelled()) {
                        return;
                    }
                    throw new DeploymentException(CODE_OTHER_ERROR, "Could not install new bundle '" + name + "' (" + bsn + ")", be);
                }

                if (!bundle.getSymbolicName().equals(bsn)) {
                    throw new DeploymentException(CODE_BUNDLE_NAME_ERROR, "Installed/updated bundle symbolicname (" + bundle.getSymbolicName() + ") do not match what was installed/updated: " + bsn);
                }

                Version targetVersion = getVersion(bundle);
                if (!sourceVersion.equals(targetVersion)) {
                    throw new DeploymentException(CODE_OTHER_ERROR, "Installed/updated bundle version (" + targetVersion + ") do not match what was installed/updated: " + sourceVersion
                        + ", offending bundle = " + bsn);
                }
            }
        }
        catch (IOException e) {
            throw new DeploymentException(CODE_OTHER_ERROR, "Problem while reading stream", e);
        }
    }

    private Version getVersion(Bundle bundle) {
        return Version.parseVersion((String) bundle.getHeaders().get(BUNDLE_VERSION));
    }

    private static class UninstallBundleRunnable extends AbstractAction {
        private final Bundle m_bundle;
        private final LogService m_log;

        public UninstallBundleRunnable(Bundle bundle, LogService log) {
            m_bundle = bundle;
            m_log = log;
        }

        protected void doRun() throws Exception {
            m_bundle.uninstall();
        }

        protected void onFailure(Exception e) {
            m_log.log(LogService.LOG_WARNING, "Could not rollback update of bundle '" + m_bundle.getSymbolicName() + "'", e);
        }
    }

    private static class UpdateBundleRunnable extends AbstractAction {
        private final AbstractDeploymentPackage m_targetPackage;
        private final Bundle m_bundle;
        private final LogService m_log;

        public UpdateBundleRunnable(Bundle bundle, AbstractDeploymentPackage targetPackage, LogService log) {
            m_bundle = bundle;
            m_targetPackage = targetPackage;
            m_log = log;
        }

        protected void doRun() throws Exception {
            InputStream is = null;
            try {
                is = m_targetPackage.getBundleStream(m_bundle.getSymbolicName());
                if (is != null) {
                    m_bundle.update(is);
                }
                else {
                    throw new RuntimeException("Unable to get inputstream for bundle " + m_bundle.getSymbolicName());
                }
            }
            finally {
                closeSilently(is);
            }
        }

        protected void onFailure(Exception e) {
            m_log.log(LogService.LOG_WARNING, "Could not rollback update of bundle '" + m_bundle.getSymbolicName() + "'", e);
        }
    }

    private final class BundleInputStream extends InputStream {
        private final InputStream m_inputStream;

        private BundleInputStream(InputStream jarInputStream) {
            m_inputStream = jarInputStream;
        }

        public int read() throws IOException {
            checkCancel();
            return m_inputStream.read();
        }

        public int read(byte[] buffer) throws IOException {
            checkCancel();
            return m_inputStream.read(buffer);
        }

        public int read(byte[] buffer, int off, int len) throws IOException {
            checkCancel();
            return m_inputStream.read(buffer, off, len);
        }

        private void checkCancel() throws IOException {
            if (isCancelled()) {
                throw new IOException("Stream was cancelled");
            }
        }
    }
}
TOP

Related Classes of org.apache.felix.deploymentadmin.spi.UpdateCommand

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.