All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.caucho.ejb.cfg.EjbConfig Maven / Gradle / Ivy

/*
 * Copyright (c) 1998-2018 Caucho Technology -- all rights reserved
 *
 * This file is part of Resin(R) Open Source
 *
 * Each copy or derived work must preserve the copyright notice and this
 * notice unmodified.
 *
 * Resin Open Source is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * Resin Open Source 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, or any warranty
 * of NON-INFRINGEMENT.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Resin Open Source; if not, write to the
 *
 *   Free Software Foundation, Inc.
 *   59 Temple Place, Suite 330
 *   Boston, MA 02111-1307  USA
 *
 * @author Scott Ferguson
 */

package com.caucho.ejb.cfg;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.annotation.sql.DataSourceDefinition;
import javax.annotation.sql.DataSourceDefinitions;
import javax.ejb.ApplicationException;
import javax.ejb.EJBs;
import javax.ejb.MessageDriven;
import javax.ejb.Singleton;
import javax.ejb.Stateful;
import javax.ejb.Stateless;
import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.InjectionTarget;

import com.caucho.config.ConfigException;
import com.caucho.config.gen.ApplicationExceptionConfig;
import com.caucho.config.inject.InjectManager;
import com.caucho.config.types.FileSetType;
import com.caucho.ejb.manager.EjbManager;
import com.caucho.ejb.server.AbstractEjbBeanManager;
import com.caucho.ejb.util.AppExceptionItem;
import com.caucho.java.gen.JavaClassGenerator;
import com.caucho.jms.JmsMessageListener;
import com.caucho.util.L10N;
import com.caucho.vfs.Path;

/**
 * Manages the EJB configuration files.
 */
public class EjbConfig {
  private static final L10N L = new L10N(EjbConfig.class);
  
  protected final EjbManager _ejbManager;

  private ArrayList _fileSetList = new ArrayList();

  private HashMap> _cfgBeans
    = new HashMap>();
  
  private HashSet> _beanSet = new HashSet>();
  
  private ArrayList> _pendingBeans = new ArrayList>();
  private ArrayList> _deployingBeans = new ArrayList>();

  private ArrayList _proxyList
    = new ArrayList();

  private ArrayList _functions
    = new ArrayList();

  private HashMap _messageDestinations;

  private ArrayList _cfgInterceptors
    = new ArrayList();

  private ArrayList _cfgInterceptorBindings
    = new ArrayList();

  private HashMap,ApplicationExceptionConfig> _appExceptionConfig
    = new HashMap,ApplicationExceptionConfig>(); 

  private Map,AppExceptionItem> _appExceptionMap
    = new ConcurrentHashMap,AppExceptionItem>();
  
  private ArrayList> _bindTypes
    = new ArrayList>();

  public EjbConfig(EjbManager ejbContainer)
  {
    _ejbManager = ejbContainer;
  }

  /**
   * Adds a path for an EJB config file to the config list.
   */
  public void addEjbPath(Path path)
    throws ConfigException
  {
    throw new UnsupportedOperationException();
  }

  public void addConfigProxy(EjbBeanConfigProxy proxy)
  {
    _proxyList.add(proxy);
    _beanSet.add(proxy.getEjbClass());
  }

  /**
   * Returns the schema name.
   */
  public String getSchema()
  {
    return "com/caucho/ejb/cfg/resin-ejb.rnc";
  }


  /**
   * Returns the EJB manager.
   */
  public EjbManager getEjbContainer()
  {
    return _ejbManager;
  }

  /**
   * Returns the cfg bean with the given name.
   */
  public EjbBean getBeanConfig(String name)
  {
    assert name != null;

    return _cfgBeans.get(name);
  }

  /**
   * Sets the cfg bean with the given name.
   */
  public void setBeanConfig(String name, EjbBean bean)
  {
    if (name == null || bean == null)
      throw new NullPointerException();

    EjbBean oldBean = _cfgBeans.get(name);

    if (oldBean == bean)
      return;
    else if (oldBean != null) {
      throw new IllegalStateException(L.l("{0}: duplicate bean '{1}' old ejb-class={2} new ejb-class={3}",
                                          this, name,
                                          oldBean, // .getEJBClass().getName()));
                                          bean)); // .getEJBClass().getName()));
    }

    _pendingBeans.add(bean);
    _cfgBeans.put(name, bean);
    
    _beanSet.add(bean.getEJBClass());
  }

  /**
   * Returns the interceptor with the given class name.
   */
  public Interceptor getInterceptor(String className)
  {
    assert className != null;

    for (Interceptor interceptor : _cfgInterceptors) {
      if (interceptor.getInterceptorClass().equals(className))
        return interceptor;
    }

    return null;
  }

  /**
   * Adds an interceptor.
   */
  public void addInterceptor(Interceptor interceptor)
  {
    if (interceptor == null)
      throw new NullPointerException();

    _cfgInterceptors.add(interceptor);
  }

  /**
   * Returns the interceptor bindings for a given ejb name.
   */
  public ArrayList
  getInterceptorBinding(String ejbName,
                        boolean isExcludeDefault)
  {
    assert ejbName != null;

    ArrayList bindings 
      = new ArrayList();
    
    for (InterceptorBinding binding : _cfgInterceptorBindings) {
      if (binding.getEjbName().equals(ejbName))
        bindings.add(binding);
      else if (binding.getEjbName().equals("*") && ! isExcludeDefault) {
        bindings.add(binding);
      }
    }

    return bindings;
  }

  /**
   * Adds an application exception.
   */
  public void addApplicationException(ApplicationExceptionConfig applicationException)
  {
    Class appExnClass = applicationException.getExceptionClass();

    _appExceptionConfig.put(appExnClass, applicationException);
  }

  /**
   * Returns the application exceptions.
   */
  public AppExceptionItem getApplicationException(Class exn,
                                                  boolean isSystem)
  {
    AppExceptionItem appExn = _appExceptionMap.get(exn);
    
    if (appExn == null) {
      appExn = createApplicationException(exn, isSystem);
      
      _appExceptionMap.put(exn, appExn);
    }
    
    return appExn;
  }
  
  private AppExceptionItem createApplicationException(Class exn, 
                                                      boolean isSystem)
  {
    if (exn == Error.class || exn == RuntimeException.class)
      return new AppExceptionItem(false, true, true);
    else if (exn == Exception.class)
      return new AppExceptionItem(true, false, true);
    
    ApplicationExceptionConfig cfg = _appExceptionConfig.get(exn);
    
    if (cfg != null) {
      return new AppExceptionItem(true, cfg.isRollback(), cfg.isInherited());
    }
    
    ApplicationException appExn = exn.getAnnotation(ApplicationException.class);
    
    if (appExn != null) {
      // ejb/1276
      return new AppExceptionItem(true, appExn.rollback(), appExn.inherited());
    }
    
    AppExceptionItem parentItem = getApplicationException(exn.getSuperclass(),
                                                          isSystem);

    if (parentItem.isInherited())
      return parentItem;
    else if (isSystem)
      return new AppExceptionItem(false, true, true);
    else
      return new AppExceptionItem(true, false, true);
    
  }
  
  /**
   * Binds an interceptor to an ejb.
   */
  public void addInterceptorBinding(InterceptorBinding interceptorBinding)
  {
    _cfgInterceptorBindings.add(interceptorBinding);
  }

  /**
   * Adds the message destination mapping
   */
  public void addMessageDestination(MessageDestination messageDestination)
  {
    if (_messageDestinations == null)
      _messageDestinations = new HashMap();

    String name = messageDestination.getMessageDestinationName();

    _messageDestinations.put(name, messageDestination);
  }

  public MessageDestination getMessageDestination(String name)
  {
    if (_messageDestinations == null)
      return null;

    return _messageDestinations.get(name);
  }
  
  public boolean isConfiguredBean(Class beanType)
  {
    return _beanSet.contains(beanType);
  }

  public  void addAnnotatedType(AnnotatedType rawAnnType,
                                   AnnotatedType annType,
                                   InjectionTarget injectTarget, 
                                   String moduleName)
  {
    try {
      Class type = annType.getJavaClass();

      if (findBeanByType(type) != null)
        return;

      if (annType.isAnnotationPresent(Stateless.class)) {
        EjbStatelessBean bean
          = new EjbStatelessBean(this, rawAnnType, annType, moduleName);
        bean.setInjectionTarget(injectTarget);

        Stateless stateless = annType.getAnnotation(Stateless.class);

        if (! "".equals(stateless.name()) && stateless.name() != null)
          bean.setEJBName(stateless.name());

        setBeanConfig(bean.getEJBName(), bean);
      }
      else if (annType.isAnnotationPresent(Stateful.class)) {
        EjbStatefulBean bean
          = new EjbStatefulBean(this, rawAnnType, annType, moduleName);
        bean.setInjectionTarget(injectTarget);
        
        Stateful stateful = annType.getAnnotation(Stateful.class);

        if (! "".equals(stateful.name()) && stateful.name() != null)
          bean.setEJBName(stateful.name());

        setBeanConfig(bean.getEJBName(), bean);
      }
      else if (annType.isAnnotationPresent(Singleton.class)) {
        EjbSingletonBean bean
          = new EjbSingletonBean(this, rawAnnType, annType, moduleName);
        bean.setInjectionTarget(injectTarget);

        Singleton singleton = annType.getAnnotation(Singleton.class);

        if (! "".equals(singleton.name()) && singleton.name() != null)
          bean.setEJBName(singleton.name());

        setBeanConfig(bean.getEJBName(), bean);
      }      
      else if (annType.isAnnotationPresent(MessageDriven.class)) {
        EjbMessageBean bean
          = new EjbMessageBean(this, rawAnnType, annType, moduleName);
        bean.setInjectionTarget(injectTarget);

        setBeanConfig(bean.getEJBName(), bean);
      }
      else if (annType.isAnnotationPresent(JmsMessageListener.class)) {
        JmsMessageListener listener
          = annType.getAnnotation(JmsMessageListener.class);

        EjbMessageBean bean
          = new EjbMessageBean(this, rawAnnType, annType, listener.destination());

        bean.setInjectionTarget(injectTarget);

        setBeanConfig(bean.getEJBName(), bean);
      }
      
      EJBs ejbs = annType.getAnnotation(EJBs.class);
      if (ejbs != null) {
        _bindTypes.add(annType);
      }
      
      // ejb/3042
      DataSourceDefinition dbDef
        = annType.getAnnotation(DataSourceDefinition.class);
      if (dbDef != null) {
        _bindTypes.add(annType);
      }
      
      DataSourceDefinitions dbDefs
        = annType.getAnnotation(DataSourceDefinitions.class);
      if (dbDefs != null) {
        _bindTypes.add(annType);
      }
    } catch (ConfigException e) {
      throw e;
    } catch (Exception e) {
      throw ConfigException.create(e);
    }
  }

  /**
   * Finds an entity bean by its abstract schema.
   */
  @SuppressWarnings("unchecked")
  public  EjbBean findBeanByType(Class type)
  {
    for (EjbBean bean : _cfgBeans.values()) {
      Class cl = bean.getEJBClass();
      
      // ejb/0j03
      if (cl != null && cl.getName().equals(type.getName()))
        return (EjbBean) bean;
    }

    return null;
  }

  /**
   * Adds a function.
   */
  public void addFunction(FunctionSignature sig, String sql)
  {
    _functions.add(sig);
  }

  /**
   * Gets the function list.
   */
  public ArrayList getFunctions()
  {
    return _functions;
  }

  /**
   * Configures the pending beans.
   */
  public void configure()
    throws ConfigException
  {
    findConfigurationFiles();

    try {
      for (EjbBeanConfigProxy configProxy : _proxyList) {
        configProxy.configure();
      }
      
      _proxyList.clear();
      
      ArrayList> beanConfig = new ArrayList>(_pendingBeans);
      _pendingBeans.clear();

      _deployingBeans.addAll(beanConfig);

      /*
      for (EjbBean bean : beanConfig) {
        bean.init();
      }
      */
    } catch (RuntimeException e) {
      throw e;
    } catch (Exception e) {
      throw ConfigException.create(e);
    }
  }


  /**
   * Configures the pending beans.
   */
  private void findConfigurationFiles()
    throws ConfigException
  {
    for (FileSetType fileSet : _fileSetList) {
      for (Path path : fileSet.getPaths()) {
        addEjbPath(path);
      }
    }
  }

  /**
   * Configures the pending beans.
   */
  public void deploy()
    throws ConfigException
  {
    try {
      ClassLoader parentLoader = _ejbManager.getClassLoader();

      Path workDir = _ejbManager.getWorkDir();

      JavaClassGenerator javaGen = new JavaClassGenerator();
      javaGen.setWorkDir(workDir);
      javaGen.setParentLoader(parentLoader);

      ArrayList> deployingBeans
        = new ArrayList>(_deployingBeans);
      _deployingBeans.clear();

      deployBeans(deployingBeans, javaGen);
      
      deployBindings(_bindTypes);
    } catch (RuntimeException e) {
      throw e;
    } catch (Exception e) {
      throw ConfigException.create(e);
    }
  }

  /**
   * Configures the pending beans.
   */
  public void deployBeans(ArrayList> beanConfig,
                          JavaClassGenerator javaGen)
    throws Exception
  {
    Thread thread = Thread.currentThread();
    ClassLoader oldLoader = thread.getContextClassLoader();

    try {
      thread.setContextClassLoader(_ejbManager.getClassLoader());

      // ejb/0g1c, ejb/0f68, ejb/0f69
      ArrayList> beanList = new ArrayList>();

      for (EjbBean bean : beanConfig) {
        if (beanList.contains(bean))
          continue;
        
        bean.init();
        
        deployBean(beanConfig, javaGen, beanList, bean);
      }
    } finally {
      thread.setContextClassLoader(oldLoader);
    }
  }
  
  private  void deployBean(ArrayList> beanConfig,
                              JavaClassGenerator javaGen,
                              ArrayList> beanList,
                              EjbBean bean)
    throws Exception
  {
    Thread thread = Thread.currentThread();
    
    EjbLazyGenerator lazyGenerator
      = new EjbLazyGenerator(bean.getAnnotatedType(), javaGen,
                                bean.getLocalList(), bean.getLocalBean(), 
                                bean.getRemoteList());

    AbstractEjbBeanManager server = initBean(bean, lazyGenerator);
    
    _ejbManager.addServer(server);
    
    ArrayList dependList = bean.getBeanDependList();

    for (String depend : dependList) {
      for (EjbBean b : beanConfig) {
        if (bean == b)
          continue;

        // XXX: what test case is this for?
        if (depend.equals(b.getEJBName())) {
          beanList.add(b);

          /*
          AbstractEjbBeanManager dependServer = initBean(b, lazyGenerator);

          initResources(b, dependServer);
          */

          thread.setContextClassLoader(server.getClassLoader());
        }
      }
    }

    // XXX: 4.0.8 timing issues
    // initResources(bean, server);
  }

  private  AbstractEjbBeanManager
  initBean(EjbBean bean,
           EjbLazyGenerator lazyGenerator)
    throws Exception
  {
    AbstractEjbBeanManager server = bean.deployServer(_ejbManager, lazyGenerator);

    server.init();

    return server;
  }
  
  private void deployBindings(ArrayList> bindTypes)
  {
    InjectManager cdiManager = _ejbManager.getInjectManager();

    for (AnnotatedType annType : bindTypes) {
      // ioc/123q
      cdiManager.getInjectionPointHandler(EJBs.class).introspectType(annType);
      
      cdiManager.getInjectionPointHandler(DataSourceDefinition.class).introspectType(annType);
      cdiManager.getInjectionPointHandler(DataSourceDefinitions.class).introspectType(annType);
    }
  }

  @Override
  public String toString()
  {
    String id = _ejbManager.getClassLoader().getId();
    
    return getClass().getSimpleName() + "[" + id + "]";
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy