/*
  * 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.ejb3;

import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.management.ObjectName;
import org.jboss.deployment.DeploymentInfo;
import org.jboss.system.ServiceMBeanSupport;
import org.jboss.logging.Logger;

/**
 * An EjbModule represents a collection of beans that are deployed as a unit.
 *
 * @author <a href="mailto:bill@jboss.org">Bill Burke</a>
 * @version $Revision$
 */
public class Ejb3Module extends ServiceMBeanSupport implements Ejb3ModuleMBean
{
   public final static String BASE_EJB3_JMX_NAME = "jboss.j2ee:service=EJB3";
   private static final Logger log = Logger.getLogger(Ejb3Module.class);

   private Ejb3JmxDeployment deployment;
   private DeploymentInfo di;

   private static class EARImpl implements EAR
   {
      private ConcurrentHashMap<String, Ejb3Deployment> deployments = new ConcurrentHashMap<String, Ejb3Deployment>();
      private String shortName;
      private String baseName;

      public EARImpl(String shortName)
      {
         this.shortName = shortName;
         int idx = shortName.lastIndexOf('.');
         baseName = shortName.substring(0, idx);
      }

      public Collection<Ejb3Deployment> getEjbDeployments()
      {
         return deployments.values();
      }

      public void register(Ejb3Deployment deployment)
      {
         deployments.put(deployment.getDeploymentUnit().getShortName(), deployment);
      }

      public void unregister(Ejb3Deployment deployment)
      {
         deployments.remove(deployment.getDeploymentUnit().getShortName());
      }

      public Ejb3Deployment findRelativeDeployment(String relativeName)
      {
         String relativeShortName = relativeName.substring(3);
         return deployments.get(relativeShortName);
      }

      public String getShortName()
      {
         return shortName;
      }

      public String getBaseName()
      {
         return baseName;
      }

   }

   public Ejb3Module(DeploymentInfo di)
   {
      EAR ear = null;
      if (di.parent != null)
      {
         if (di.parent.shortName.endsWith(".ear") || di.parent.shortName.endsWith(".ear/"))
         {
            synchronized(di.parent.context)
            {
               ear = (EAR)di.parent.context.get("EJB3_EAR_METADATA");
               if (ear == null)
               {
                  ear = new EARImpl(di.parent.shortName);
                  di.parent.context.put("EJB3_EAR_METADATA", ear);
               }
            }
         }
      }
      deployment = new Ejb3JmxDeployment(di, ear);
      if (ear != null)
      {
         ear.register(deployment);
      }
      this.di = di;
   }

   protected void createService() throws Exception
   {
      super.createService();
      ClassLoader old = Thread.currentThread().getContextClassLoader();
      try
      {
         Thread.currentThread().setContextClassLoader(di.ucl);
         deployment.create();
      }
      finally
      {
         Thread.currentThread().setContextClassLoader(old);
      }
   }

   protected void startService() throws Exception
   {
      ClassLoader old = Thread.currentThread().getContextClassLoader();
      try
      {
         Thread.currentThread().setContextClassLoader(di.ucl);
         deployment.start();
      }
      finally
      {
         Thread.currentThread().setContextClassLoader(old);
      }
      super.startService();

   }

   protected void stopService() throws Exception
   {
      ClassLoader old = Thread.currentThread().getContextClassLoader();
      try
      {
         Thread.currentThread().setContextClassLoader(di.ucl);
         deployment.stop();
      }
      finally
      {
         Thread.currentThread().setContextClassLoader(old);
      }
      super.stopService();
   }

   protected void destroyService() throws Exception
   {
      ClassLoader old = Thread.currentThread().getContextClassLoader();
      try
      {
         Thread.currentThread().setContextClassLoader(di.ucl);
         deployment.destroy();
      }
      finally
      {
         Thread.currentThread().setContextClassLoader(old);
      }
      super.destroyService();
   }

   public Container getContainer(ObjectName name)
   {
      return deployment.getContainer(name);
   }

   public Map getContainers()
   {
      return deployment.getEjbContainers();
   }
}
