/*
 * JBoss, Home of Professional Open Source
 * Copyright 2005, JBoss Inc., and individual contributors as indicated
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.jboss.osgi.spi.framework;

//$Id$

import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.jboss.osgi.spi.FrameworkException;
import org.jboss.osgi.spi.logging.ExportedPackageHelper;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.launch.Framework;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * An abstraction of an OSGi Framework.
 * 
 * In addition to the standard {@link Framework} this implementation also
 * supports properties and initial bundle provisioning.
 * 
 * @author thomas.diesler@jboss.com
 * @since 23-Jan-2009
 */
public abstract class FrameworkIntegration
{
   // Provide logging
   final Logger log = LoggerFactory.getLogger(FrameworkIntegration.class);

   private Map<String, Object> properties = new HashMap<String, Object>();
   private List<URL> autoInstall = new ArrayList<URL>();
   private List<URL> autoStart = new ArrayList<URL>();

   public Map<String, Object> getProperties()
   {
      return properties;
   }

   public void setProperties(Map<String, Object> props)
   {
      this.properties = props;
   }

   public List<URL> getAutoInstall()
   {
      return autoInstall;
   }

   public void setAutoInstall(List<URL> autoInstall)
   {
      this.autoInstall = autoInstall;
   }

   public List<URL> getAutoStart()
   {
      return autoStart;
   }

   public void setAutoStart(List<URL> autoStart)
   {
      this.autoStart = autoStart;
   }

   /** Overwrite to create the framework */
   protected abstract void createFramework(Map<String, Object> properties);

   /** Overwrite to provide the framework */
   protected abstract Framework getFramework();
   
   public Bundle getBundle()
   {
      assertFrameworkStart();
      return getFramework();
   }

   public BundleContext getBundleContext()
   {
      assertFrameworkStart();
      return getFramework().getBundleContext();
   }

   public void create()
   {
      createFramework(properties);
   }

   public void start()
   {
      // Create the Framework instance
      assertFrameworkCreate();
      
      // Start the System Bundle
      try
      {
         getFramework().start();
      }
      catch (BundleException ex)
      {
         throw new FrameworkException("Cannot start system bundle", ex);
      }
      
      // Get system bundle context
      BundleContext context = getFramework().getBundleContext();
      if (context == null)
         throw new FrameworkException("Cannot obtain system context");

      // Log the the framework packages
      ExportedPackageHelper packageHelper = new ExportedPackageHelper(context);
      packageHelper.logExportedPackages(getBundle());
      
      Map<URL, Bundle> autoBundles = new HashMap<URL, Bundle>();

      // Add the autoStart bundles to autoInstall
      for (URL bundleURL : autoStart)
      {
         autoInstall.add(bundleURL);
      }

      // Install autoInstall bundles
      for (URL bundleURL : autoInstall)
      {
         try
         {
            Bundle bundle = context.installBundle(bundleURL.toString());
            long bundleId = bundle.getBundleId();
            log.info("Installed bundle [" + bundleId + "]: " + bundle.getSymbolicName());
            autoBundles.put(bundleURL, bundle);
         }
         catch (BundleException ex)
         {
            stop();
            throw new IllegalStateException("Cannot install bundle: " + bundleURL, ex);
         }
      }

      // Start autoStart bundles
      for (URL bundleURL : autoStart)
      {
         try
         {
            Bundle bundle = autoBundles.get(bundleURL);
            if (bundle != null)
            {
               bundle.start();
               packageHelper.logExportedPackages(bundle);
               log.info("Started bundle: " + bundle.getSymbolicName());
            }
         }
         catch (BundleException ex)
         {
            stop();
            throw new IllegalStateException("Cannot start bundle: " + bundleURL, ex);
         }
      }
   }

   public void stop()
   {
      Framework framework = getFramework();
      if (framework != null)
      {
         try
         {
            framework.stop();
            framework.waitForStop(5000);
            framework = null;
            log.debug("SystemBundle STOPPED");
         }
         catch (BundleException ex)
         {
            log.error("Cannot stop Framework", ex);
         }
         catch (InterruptedException ex)
         {
            log.error("Cannot stop Framework", ex);
         }
      }
   }

   private void assertFrameworkCreate()
   {
      if (getFramework() == null)
         create();
   }

   private void assertFrameworkStart()
   {
      assertFrameworkCreate();
      if ((getFramework().getState() & Bundle.ACTIVE) == 0)
         start();
   }
}
@@ -2069,24 +2069,60 @@
 st%3CURL%3E();%0A%0A
+   private Framework framework;%0A   %0A
    public Ma
@@ -2633,226 +2633,8 @@
  %7D%0A%0A
-   /** Overwrite to create the framework */%0A   protected abstract void createFramework(Map%3CString, Object%3E properties);%0A%0A   /** Overwrite to provide the framework */%0A   protected abstract Framework getFramework();%0A   %0A
    p
@@ -2874,66 +2874,392 @@
 lic 
-void create()%0A   %7B%0A      createFramework(properties);%0A   %7D
+Framework getFramework()%0A   %7B%0A      if (framework == null)%0A         framework = createFramework(properties);%0A      %0A      return framework;%0A   %7D%0A%0A   public void create()%0A   %7B%0A      if (framework == null)%0A         framework = createFramework(properties);%0A   %7D%0A%0A   /** Overwrite to create the framework */%0A   protected abstract Framework createFramework(Map%3CString, Object%3E properties);
 %0A%0A  

Upgrade equinox integration