content: /**
   *
   * 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.aries.blueprint.web;
  
  import java.net.URL;
  import java.util.LinkedList;
  import java.util.List;
  import javax.servlet.ServletContext;
  import javax.servlet.ServletContextEvent;
  import javax.servlet.ServletContextListener;
  
  import org.apache.aries.blueprint.services.BlueprintExtenderService;
  import org.osgi.framework.Bundle;
  import org.osgi.framework.BundleContext;
  import org.osgi.framework.ServiceReference;
  import org.osgi.service.blueprint.container.BlueprintContainer;
  
  /**
   * OSGI Blueprint-aware ServletContextListener which use Aties BlueprintExtenderService
   * to create Blueprint Container for the application bundle and save it as ServletContext attribute
   *  
   */
  public class BlueprintContextListener implements ServletContextListener {
      public static final String CONTAINER_ATTRIBUTE = "org.apache.aries.blueprint.container";
  
      public static final String LOCATION_PARAM = "blueprintLocation";
      public static final String DEFAULT_LOCATION = "OSGI-INF/blueprint.xml";
  
      public static final String BUNDLE_CONTEXT_PARAM = "blueprintContext";
      public static final String DEFAULT_BUNDLE_CONTEXT_ATTRIBUTE = "osgi-bundlecontext";
  
      public void contextInitialized(ServletContextEvent event) {
          ServletContext sc = event.getServletContext();
  
          // Get bundle context
          BundleContext bc = getBundleContext(sc);
          if (bc == null) {
              return;
          }
  
          // Get BlueprintExtenderService
          BlueprintExtenderService blueprintExtender = getBlueprintExtenderService(bc);
          if (blueprintExtender == null) {
              return;
          }
  
          try {
              // Check if the extender has already created a container
              BlueprintContainer container = blueprintExtender.getContainer(bc.getBundle());
  
              if (container == null) {
                  List<Object> blueprintResources = getBlueprintAppList(sc, bc.getBundle());
                  if (blueprintResources.isEmpty()) {
                      // The extender is expected to scan a bundle
                      container = blueprintExtender.createContainer(bc.getBundle());
                  } else {
                      // Use specified resources to create a container
                      container = blueprintExtender.createContainer(bc.getBundle(), blueprintResources);
                  }
              }
              if (container == null) {
                  sc.log("Failed to startup blueprint container.");
              } else {
                  sc.setAttribute(CONTAINER_ATTRIBUTE, container);
              }
          } catch (Exception e) {
              sc.log("Failed to startup blueprint container. " + e, e);
          }
      }
  
      public void contextDestroyed(ServletContextEvent event) {
          ServletContext sc = event.getServletContext();
          BlueprintContainer container = (BlueprintContainer)sc.getAttribute(CONTAINER_ATTRIBUTE);
          if (container == null) {
              return;
          }
  
          BundleContext bc = getBundleContext(sc);
          if (bc == null) {
              return;
          }
  
          BlueprintExtenderService blueprintExtender = getBlueprintExtenderService(bc);
          if (blueprintExtender == null) {
              return;
          }
  
          blueprintExtender.destroyContainer(bc.getBundle(), container);
      }
  
      private List<Object> getBlueprintAppList(ServletContext sc, Bundle applicationBundle) {
          String location = sc.getInitParameter(LOCATION_PARAM);
          if (location == null) {
              location = DEFAULT_LOCATION;
          }
  
          List<Object> blueprintResources = new LinkedList<Object>();
          URL entry = applicationBundle.getEntry(location);
          if (entry != null) {
              blueprintResources.add(entry);
          }
  
          return blueprintResources;
      }
  
      private BundleContext getBundleContext(ServletContext sc) {
          String bundleContextAttributeName = sc
                  .getInitParameter(BUNDLE_CONTEXT_PARAM);
          if (bundleContextAttributeName == null) {
              bundleContextAttributeName = DEFAULT_BUNDLE_CONTEXT_ATTRIBUTE;
          }
  
          BundleContext bc = (BundleContext) sc.getAttribute(bundleContextAttributeName);
          if (bc == null) {
              sc.log("Failed to startup blueprint container: no BundleContext is available");
          }
          return bc;
      }
  
      private BlueprintExtenderService getBlueprintExtenderService(BundleContext bc) {
          ServiceReference sref = bc
                  .getServiceReference(BlueprintExtenderService.class.getName());
          if (sref != null) {
              return (BlueprintExtenderService) bc.getService(sref);
          } else {
              return null;
          }
      }
  }
  