Package org.jboss.forge.furnace.impl

Source Code of org.jboss.forge.furnace.impl.AddonRunnable$AddonContainerStartup

/*
* Copyright 2013 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Eclipse Public License version 1.0, available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.jboss.forge.furnace.impl;

import java.util.concurrent.Callable;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.enterprise.inject.spi.BeanManager;

import org.jboss.forge.furnace.Furnace;
import org.jboss.forge.furnace.addons.Addon;
import org.jboss.forge.furnace.addons.AddonDependency;
import org.jboss.forge.furnace.addons.AddonStatus;
import org.jboss.forge.furnace.event.PostStartup;
import org.jboss.forge.furnace.event.PreShutdown;
import org.jboss.forge.furnace.lock.LockMode;
import org.jboss.forge.furnace.modules.AddonResourceLoader;
import org.jboss.forge.furnace.modules.ModularURLScanner;
import org.jboss.forge.furnace.modules.ModularWeld;
import org.jboss.forge.furnace.modules.ModuleScanResult;
import org.jboss.forge.furnace.services.ServiceRegistry;
import org.jboss.forge.furnace.util.Addons;
import org.jboss.forge.furnace.util.Assert;
import org.jboss.forge.furnace.util.BeanManagerUtils;
import org.jboss.forge.furnace.util.ClassLoaders;
import org.jboss.weld.environment.se.Weld;
import org.jboss.weld.environment.se.WeldContainer;
import org.jboss.weld.resources.spi.ResourceLoader;

/**
* Loads an {@link Addon}
*/
public final class AddonRunnable implements Runnable
{
   private static final Logger logger = Logger.getLogger(AddonRunnable.class.getName());

   private Furnace forge;
   private AddonImpl addon;
   private AddonContainerStartup container;

   private Callable<Object> shutdownCallable = new Callable<Object>()
   {
      @Override
      public Object call() throws Exception
      {
         addon.setStatus(AddonStatus.LOADED);
         return null;
      }
   };

   public AddonRunnable(Furnace forge, AddonImpl addon)
   {
      this.forge = forge;
      this.addon = addon;
   }

   public void shutdown()
   {
      try
      {
         forge.getLockManager().performLocked(LockMode.READ, new Callable<Void>()
         {
            @Override
            public Void call() throws Exception
            {
               logger.info("< Stopping container [" + addon.getId() + "] [" + addon.getRepository().getRootDirectory()
                        + "]");
               long start = System.currentTimeMillis();
               ClassLoaders.executeIn(addon.getClassLoader(), shutdownCallable);
               logger.info("<< Stopped container [" + addon.getId() + "] - "
                        + (System.currentTimeMillis() - start) + "ms");
               return null;
            }
         });
      }
      catch (RuntimeException e)
      {
         logger.log(Level.SEVERE, "Failed to shut down addon " + addon.getId(), e);
         throw e;
      }
   }

   @Override
   public void run()
   {
      Thread currentThread = Thread.currentThread();
      String name = currentThread.getName();
      currentThread.setName(addon.getId().toCoordinates());
      try
      {
         forge.getLockManager().performLocked(LockMode.READ, new Callable<Void>()
         {
            @Override
            public Void call() throws Exception
            {
               logger.info("> Starting container [" + addon.getId() + "] [" + addon.getRepository().getRootDirectory()
                        + "]");
               long start = System.currentTimeMillis();
               container = new AddonContainerStartup();
               shutdownCallable = ClassLoaders.executeIn(addon.getClassLoader(), container);
               logger.info(">> Started container [" + addon.getId() + "] - "
                        + (System.currentTimeMillis() - start) + "ms");
               return null;
            }
         });

         if (container.postStartupTask != null)
            ClassLoaders.executeIn(addon.getClassLoader(), container.postStartupTask);
      }
      catch (Throwable e)
      {
         logger.log(Level.SEVERE, "Failed to start addon [" + addon.getId() + "] with module [" + addon.getModule()
                  + "]", e);
         throw new RuntimeException(e);
      }
      finally
      {
         ((AddonRegistryImpl) forge.getAddonRegistry()).finishedStarting(addon);
         currentThread.setName(name);
      }
   }

   public AddonImpl getAddon()
   {
      return addon;
   }

   public class AddonContainerStartup implements Callable<Callable<Object>>
   {
      private Callable<Void> postStartupTask;

      @Override
      public Callable<Object> call() throws Exception
      {
         try
         {
            ResourceLoader resourceLoader = new AddonResourceLoader(addon);
            ModularURLScanner scanner = new ModularURLScanner(resourceLoader, "META-INF/beans.xml");
            ModuleScanResult scanResult = scanner.scan();

            Callable<Object> shutdownCallback = null;

            if (scanResult.getDiscoveredResourceUrls().isEmpty())
            {
               /*
                * This is an import-only addon and does not require weld, nor provide remote services.
                */
               addon.setServiceRegistry(new NullServiceRegistry());
               addon.setStatus(AddonStatus.STARTED);

               shutdownCallback = new Callable<Object>()
               {
                  @Override
                  public Object call() throws Exception
                  {
                     addon.setStatus(AddonStatus.LOADED);
                     return null;
                  }
               };
            }
            else
            {
               final Weld weld = new ModularWeld(scanResult);
               WeldContainer container;
               container = weld.initialize();

               final BeanManager manager = container.getBeanManager();
               Assert.notNull(manager, "BeanManager was null");

               AddonRepositoryProducer repositoryProducer = BeanManagerUtils.getContextualInstance(manager,
                        AddonRepositoryProducer.class);
               repositoryProducer.setRepository(addon.getRepository());

               FurnaceProducer forgeProducer = BeanManagerUtils.getContextualInstance(manager, FurnaceProducer.class);
               forgeProducer.setForge(forge);

               AddonProducer addonProducer = BeanManagerUtils.getContextualInstance(manager, AddonProducer.class);
               addonProducer.setAddon(addon);

               AddonRegistryProducer addonRegistryProducer = BeanManagerUtils.getContextualInstance(manager,
                        AddonRegistryProducer.class);
               addonRegistryProducer.setRegistry(forge.getAddonRegistry());

               ContainerServiceExtension extension = BeanManagerUtils.getContextualInstance(manager,
                        ContainerServiceExtension.class);
               ServiceRegistryProducer serviceRegistryProducer = BeanManagerUtils.getContextualInstance(manager,
                        ServiceRegistryProducer.class);
               serviceRegistryProducer.setServiceRegistry(new ServiceRegistryImpl(forge.getLockManager(), addon,
                        manager, extension));

               ServiceRegistry registry = BeanManagerUtils.getContextualInstance(manager, ServiceRegistry.class);
               Assert.notNull(registry, "Service registry was null.");
               addon.setServiceRegistry(registry);

               logger.info("Services loaded from addon [" + addon.getId() + "] -  " + registry.getExportedTypes());

               shutdownCallback = new Callable<Object>()
               {
                  @Override
                  public Object call() throws Exception
                  {
                     try
                     {
                        manager.fireEvent(new PreShutdown());
                     }
                     catch (Exception e)
                     {
                        logger.log(Level.SEVERE, "Failed to execute pre-Shutdown event.", e);
                     }
                     finally
                     {
                        addon.setStatus(AddonStatus.LOADED);
                     }

                     weld.shutdown();
                     return null;
                  }
               };

               postStartupTask = new Callable<Void>()
               {
                  @Override
                  public Void call() throws Exception
                  {
                     for (AddonDependency dependency : addon.getDependencies())
                     {
                        if (dependency.getDependency().getStatus().isLoaded())
                           Addons.waitUntilStarted(dependency.getDependency());
                     }

                     addon.setStatus(AddonStatus.STARTED);

                     manager.fireEvent(new PostStartup());
                     return null;
                  }
               };
            }

            return shutdownCallback;
         }
         catch (Exception e)
         {
            addon.setStatus(AddonStatus.FAILED);
            throw e;
         }
      }
   }

   @Override
   public int hashCode()
   {
      final int prime = 31;
      int result = 1;
      result = prime * result + ((addon == null) ? 0 : addon.hashCode());
      return result;
   }

   @Override
   public boolean equals(Object obj)
   {
      if (this == obj)
         return true;
      if (obj == null)
         return false;
      if (getClass() != obj.getClass())
         return false;
      AddonRunnable other = (AddonRunnable) obj;
      if (addon == null)
      {
         if (other.addon != null)
            return false;
      }
      else if (!addon.equals(other.addon))
         return false;
      return true;
   }
}
TOP

Related Classes of org.jboss.forge.furnace.impl.AddonRunnable$AddonContainerStartup

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.