/* * 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 WARRANTIESOR 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.aries.application.runtime.impl; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.aries.application.DeploymentContent; import org.apache.aries.application.DeploymentMetadata; import org.apache.aries.application.management.AriesApplication; import org.apache.aries.application.management.AriesApplicationContext; import org.apache.aries.application.management.BundleInfo; import org.apache.aries.application.management.ManagementException; import org.apache.aries.application.management.spi.resolve.AriesApplicationResolver; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.BundleException; import org.osgi.framework.ServiceException; import org.osgi.framework.ServiceReference; import org.osgi.framework.Version; import org.osgi.service.packageadmin.PackageAdmin; public class ApplicationContextImpl implements AriesApplicationContext { private AriesApplication _application; private Map<BundleInfo, Bundle> _bundles; private ApplicationState _state; private BundleContext _bundleContext; public ApplicationContextImpl (BundleContext b, AriesApplication app) throws BundleException, ManagementException { _bundleContext = b; _application = app; _bundles = new HashMap<BundleInfo, Bundle>(); DeploymentMetadata meta = _application.getDeploymentMetadata(); AriesApplicationResolver resolver = null; PackageAdmin packageAdmin = null; ServiceReference resolverRef = b.getServiceReference(AriesApplicationResolver.class.getName()); ServiceReference packageAdminRef = b.getServiceReference(PackageAdmin.class.getName()); try { resolver = getService(resolverRef, AriesApplicationResolver.class); packageAdmin = getService(packageAdminRef, PackageAdmin.class); List<DeploymentContent> bundlesToInstall = new ArrayList<DeploymentContent>(meta.getApplicationDeploymentContents()); bundlesToInstall.addAll(meta.getApplicationProvisionBundles()); bundlesToInstall.addAll(meta.getDeployedUseBundle()); for (DeploymentContent content : bundlesToInstall) { String bundleSymbolicName = content.getContentName(); Version bundleVersion = content.getExactVersion(); // Step 1: See if bundle is already installed in the framework if (findBundleInFramework(packageAdmin, bundleSymbolicName, bundleVersion) != null) { continue; } // Step 2: See if the bundle is included in the application BundleInfo bundleInfo = findBundleInfoInApplication(bundleSymbolicName, bundleVersion); if (bundleInfo == null) { // Step 3: Lookup bundle location using the resolver bundleInfo = findBundleInfoUsingResolver(resolver, bundleSymbolicName, bundleVersion); } if (bundleInfo == null) { throw new ManagementException("Cound not find bundles: " + bundleSymbolicName + "_" + bundleVersion); } Bundle bundle = _bundleContext.installBundle(bundleInfo.getLocation()); _bundles.put(bundleInfo, bundle); } } catch (BundleException be) { for (Bundle bundle : _bundles.values()) { bundle.uninstall(); } _bundles.clear(); throw be; } finally { if (resolver != null) { b.ungetService(resolverRef); } if (packageAdmin != null) { b.ungetService(packageAdminRef); } } _state = ApplicationState.INSTALLED; } private <T> T getService(ServiceReference ref, Class<T> type) throws ManagementException { Object service = null; if (ref != null) { service = _bundleContext.getService(ref); } if (service == null) { throw new ManagementException(new ServiceException(type.getName(), ServiceException.UNREGISTERED)); } return type.cast(service); } private Bundle findBundleInFramework(PackageAdmin admin, String symbolicName, Version version) { String exactVersion = "[" + version + "," + version + "]"; Bundle[] bundles = admin.getBundles(symbolicName, exactVersion); if (bundles != null && bundles.length == 1) { return bundles[0]; } else { return null; } } private BundleInfo findBundleInfoInApplication(String symbolicName, Version version) { for (BundleInfo info : _application.getBundleInfo()) { if (info.getSymbolicName().equals(symbolicName) && info.getVersion().equals(version)) { return info; } } return null; } private BundleInfo findBundleInfoUsingResolver(AriesApplicationResolver resolver, String symbolicName, Version version) { return resolver.getBundleInfo(symbolicName, version); } public AriesApplication getApplication() { return _application; } public Set<Bundle> getApplicationContent() { Set<Bundle> result = new HashSet<Bundle>(); for (Map.Entry<BundleInfo, Bundle> entry : _bundles.entrySet()) { result.add (entry.getValue()); } return result; } public ApplicationState getApplicationState() { return _state; } public void start() throws BundleException { _state = ApplicationState.STARTING; List<Bundle> bundlesWeStarted = new ArrayList<Bundle>(); try { for (Bundle b : _bundles.values()) { if (b.getState() != Bundle.ACTIVE) { b.start(Bundle.START_ACTIVATION_POLICY); bundlesWeStarted.add(b); } } } catch (BundleException be) { for (Bundle b : bundlesWeStarted) { try { b.stop(); } catch (BundleException be2) { // we are doing tidyup here, so we don't want to replace the bundle exception // that occurred during start with one from stop. We also want to try to stop // all the bundles we started even if some bundles wouldn't stop. } } _state = ApplicationState.INSTALLED; throw be; } _state = ApplicationState.ACTIVE; } public void stop() throws BundleException { for (Map.Entry<BundleInfo, Bundle> entry : _bundles.entrySet()) { Bundle b = entry.getValue(); b.stop(); } _state = ApplicationState.RESOLVED; } public void setState(ApplicationState state) { _state = state; } }