blob: edb4502a8cace2deb905965e331de9d87d9643b9 [file] [log] [blame]
/*
* 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 org.apache.felix.deploymentadmin.AbstractDeploymentPackage;
import org.apache.felix.deploymentadmin.BundleInfoImpl;
import org.osgi.framework.Bundle;
import org.osgi.framework.FrameworkEvent;
import org.osgi.framework.FrameworkListener;
import org.osgi.service.log.LogService;
import org.osgi.service.packageadmin.PackageAdmin;
/**
* Command that starts all bundles described in the source deployment package of
* a deployment session.
*/
public class StartBundleCommand extends Command {
private final RefreshPackagesMonitor m_refreshMonitor = new RefreshPackagesMonitor();
protected void doExecute(DeploymentSessionImpl session) throws Exception {
AbstractDeploymentPackage source = session.getSourceAbstractDeploymentPackage();
PackageAdmin packageAdmin = session.getPackageAdmin();
RefreshPackagesListener listener = new RefreshPackagesListener();
LogService log = session.getLog();
session.getBundleContext().addFrameworkListener(listener);
packageAdmin.refreshPackages(null);
m_refreshMonitor.waitForRefresh();
session.getBundleContext().removeFrameworkListener(listener);
// start source bundles
BundleInfoImpl[] bundleInfos = source.getOrderedBundleInfos();
for (int i = 0; i < bundleInfos.length; i++) {
BundleInfoImpl bundleInfoImpl = bundleInfos[i];
if (!bundleInfoImpl.isCustomizer()) {
String symbolicName = bundleInfoImpl.getSymbolicName();
Bundle bundle = source.getBundle(symbolicName);
if (bundle != null) {
if (isFragmentBundle(bundle)) {
log.log(LogService.LOG_INFO, "Skipping fragment bundle '" + symbolicName + "'");
}
else {
try {
bundle.start();
}
catch (Exception be) {
log.log(LogService.LOG_WARNING, "Could not start bundle '" + symbolicName + "'", be);
}
}
}
else {
log.log(LogService.LOG_WARNING, "Could not start bundle '" + symbolicName + "' because it is not present in the framework");
}
}
}
}
/**
* RefreshPackagesListener is only listing to FrameworkEvents of the type
* PACKAGES_REFRESHED. It will notify any object waiting the completion of a
* refreshpackages() call.
*/
private class RefreshPackagesListener implements FrameworkListener {
public void frameworkEvent(FrameworkEvent event) {
if (event.getType() == FrameworkEvent.PACKAGES_REFRESHED) {
m_refreshMonitor.proceed();
}
}
}
/**
* Use this monitor when its desired to wait for the completion of the
* asynchronous PackageAdmin.refreshPackages() call.
*/
private static class RefreshPackagesMonitor {
private static final int REFRESH_TIMEOUT = 10000;
private volatile boolean m_alreadyNotified = false;
/**
* Waits for the completion of the PackageAdmin.refreshPackages() call.
* Because its not sure whether all OSGi framework implementations
* implement this method as specified we have build in a timeout. So if
* a event about the completion of the refreshpackages() is never
* received, we continue after the timeout whether the refresh was done
* or not.
*/
public synchronized void waitForRefresh() {
if (!m_alreadyNotified) {
try {
wait(REFRESH_TIMEOUT);
}
catch (InterruptedException ie) {}
finally {
m_alreadyNotified = false;
}
}
else {
// just reset the misted notification variable, this Monitor
// object might be reused.
m_alreadyNotified = false;
}
}
/**
* After a PACKAGES_REFRESHED event notify all the parties interested in
* the completion of the PackageAdmin.refreshPackages() call.
*/
public synchronized void proceed() {
m_alreadyNotified = true;
notifyAll();
}
}
}