/* * 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.File; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import org.apache.felix.deploymentadmin.AbstractDeploymentPackage; import org.apache.felix.deploymentadmin.Constants; import org.apache.felix.deploymentadmin.DeploymentAdminConfig; import org.apache.felix.deploymentadmin.DeploymentAdminImpl; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.service.deploymentadmin.DeploymentException; import org.osgi.service.deploymentadmin.DeploymentPackage; import org.osgi.service.deploymentadmin.spi.DeploymentSession; import org.osgi.service.log.LogService; import org.osgi.service.packageadmin.PackageAdmin; /** * Represents a running deployment session. */ public class DeploymentSessionImpl implements DeploymentSession, Constants { private final AbstractDeploymentPackage m_target; private final AbstractDeploymentPackage m_source; private final List m_commands; private final DeploymentAdminImpl m_admin; private final DeploymentAdminConfig m_config; private volatile Command m_currentCommand = null; private volatile boolean m_cancelled; public DeploymentSessionImpl(AbstractDeploymentPackage source, AbstractDeploymentPackage target, List commands, DeploymentAdminImpl admin, DeploymentAdminConfig config) { m_source = source; m_target = target; m_commands = commands; m_admin = admin; m_config = config; } /** * Calling this method will cause the commands specified for this session to * be executed. the commands will be rolled back if the session is canceled * or if an exception is caused by one of the commands. * * @throws DeploymentException If the session was canceled ( * <code>DeploymentException.CODE_CANCELLED</code>) or if one of the * commands caused an exception (<code>DeploymentException.*</code>) */ public void call(boolean ignoreExceptions) throws DeploymentException { List executedCommands = new ArrayList(); for (Iterator i = m_commands.iterator(); i.hasNext();) { if (m_cancelled) { // previous command did not pick up on cancel rollback(executedCommands); throw new DeploymentException(CODE_CANCELLED); } m_currentCommand = (Command) i.next(); try { executedCommands.add(m_currentCommand); m_currentCommand.execute(this); } catch (DeploymentException de) { if (!ignoreExceptions) { // XXX catch exception and verify whether it is possible to // have exceptions during a rollback rollback(executedCommands); throw de; } else { m_admin.getLog().log(LogService.LOG_DEBUG, "Ignoring exception as requested!", de); } } } for (Iterator i = m_commands.iterator(); i.hasNext();) { ((Command) i.next()).commit(this); } m_currentCommand = null; } /** * Cancels the session if it is in progress. * * @return true if a session was in progress and now canceled, false * otherwise. */ public boolean cancel() { m_cancelled = true; Command currentCommand = m_currentCommand; if (currentCommand != null) { currentCommand.cancel(); return true; } return false; } /** * Returns the bundle context of the bundle this class is part of. * * @return The <code>BundleContext</code>. */ public BundleContext getBundleContext() { return m_admin.getBundleContext(); } /** * @return the configuration for this session, is guaranteed to remain stable during this session, never * <code>null</code>. */ public DeploymentAdminConfig getConfiguration() { return m_config; } /** * Retrieve the base directory of the persistent storage area according to * OSGi Core R4 6.1.6.10 for the given <code>BundleContext</code>. * * @param bundle of which the storage area will be returned * @return a <code>File</code> that represents the base directory of the * persistent storage area for the bundle */ public File getDataFile(Bundle bundle) { File result = null; BundleContext context = bundle.getBundleContext(); if (context != null) { result = context.getDataFile(""); } else { // TODO this method should not return null or throw an exception; we // need to resolve this... throw new IllegalStateException("Could not retrieve valid bundle context from bundle " + bundle.getSymbolicName()); } if (result == null) { throw new IllegalStateException("Could not retrieve base directory for bundle " + bundle.getSymbolicName()); } return result; } /** * Returns the currently present log service. * * @return The <code>LogService</code>. */ public LogService getLog() { return m_admin.getLog(); } /** * Returns the currently present package admin. * * @return The <code>PackageAdmin</code> */ public PackageAdmin getPackageAdmin() { return m_admin.getPackageAdmin(); } /** * Returns the source deployment package as an * <code>AbstractDeploymentPackage</code>. * * @return The source deployment packge of the session. */ public AbstractDeploymentPackage getSourceAbstractDeploymentPackage() { return m_source; } public DeploymentPackage getSourceDeploymentPackage() { return m_source; } /** * Returns the target deployment package as an * <code>AbstractDeploymentPackage</code>. * * @return The target deployment package of the session. */ public AbstractDeploymentPackage getTargetAbstractDeploymentPackage() { return m_target; } public DeploymentPackage getTargetDeploymentPackage() { return m_target; } private void rollback(List executedCommands) { for (ListIterator i = executedCommands.listIterator(executedCommands.size()); i.hasPrevious();) { Command command = (Command) i.previous(); command.rollback(this); } } }