Package com.caucho.ejb.manager

Source Code of com.caucho.ejb.manager.EjbContainer$ServerCmp

/*
* Copyright (c) 1998-2010 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.manager;

import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.InjectionTarget;
import javax.jms.ConnectionFactory;

import com.caucho.amber.manager.AmberContainer;
import com.caucho.amber.manager.AmberPersistenceUnit;
import com.caucho.config.ConfigException;
import com.caucho.ejb.cfg.EjbConfigManager;
import com.caucho.ejb.cfg.EjbRootConfig;
import com.caucho.ejb.protocol.EjbProtocolManager;
import com.caucho.ejb.server.AbstractServer;
import com.caucho.java.WorkDir;
import com.caucho.loader.Environment;
import com.caucho.loader.EnvironmentClassLoader;
import com.caucho.loader.EnvironmentListener;
import com.caucho.loader.EnvironmentLocal;
import com.caucho.loader.SimpleLoader;
import com.caucho.loader.enhancer.ScanClass;
import com.caucho.loader.enhancer.ScanClassAllow;
import com.caucho.loader.enhancer.ScanListener;
import com.caucho.loader.enhancer.ScanMatch;
import com.caucho.util.CharBuffer;
import com.caucho.util.L10N;
import com.caucho.vfs.JarPath;
import com.caucho.vfs.Path;

/**
* Environment-based container.
*/
public class EjbContainer implements ScanListener, EnvironmentListener {
  private static final L10N L = new L10N(EjbContainer.class);
  private static final Logger log = Logger.getLogger(EjbContainer.class
      .getName());

  private static final EnvironmentLocal<EjbContainer> _localContainer
    = new EnvironmentLocal<EjbContainer>();

  private final EnvironmentClassLoader _classLoader;
  private final ClassLoader _tempClassLoader;

  private final EjbContainer _parentContainer;

  private final EjbConfigManager _configManager;
  private final EjbProtocolManager _protocolManager;

  private AmberPersistenceUnit _ejbPersistenceUnit;

  private HashSet<String> _ejbUrls = new HashSet<String>();

  //
  // configuration
  //

  private boolean _isAutoCompile = true;
  private Path _workDir;

  private ConnectionFactory _jmsConnectionFactory;
  private int _messageConsumerMax = 5;

  //
  // active servers
  //

  private ArrayList<AbstractServer> _serverList = new ArrayList<AbstractServer>();

  private EjbContainer(ClassLoader loader)
  {
    _parentContainer = _localContainer.get(loader);

    _classLoader = Environment.getEnvironmentClassLoader(loader);

    _tempClassLoader = _classLoader.getNewTempClassLoader();

    _localContainer.set(this, _classLoader);

    if (_parentContainer != null)
      copyContainerDefaults(_parentContainer);

    // _ejbAdmin = new EJBAdmin(this);

    _protocolManager = new EjbProtocolManager(this);

    _configManager = new EjbConfigManager(this);

    _workDir = WorkDir.getLocalWorkDir().lookup("ejb");

    _classLoader.addScanListener(this);

    Environment.addEnvironmentListener(this);
  }

  /**
   * Returns the local container.
   */
  public static EjbContainer create()
  {
    return create(Thread.currentThread().getContextClassLoader());
  }

  /**
   * Returns the local container.
   */
  public static EjbContainer create(ClassLoader loader)
  {
    synchronized (_localContainer) {
      EjbContainer container = _localContainer.getLevel(loader);

      if (container == null) {
        container = new EjbContainer(loader);

        _localContainer.set(container, loader);
      }

      return container;
    }
  }

  /**
   * Returns the local container.
   */
  public static EjbContainer getCurrent()
  {
    return getCurrent(Thread.currentThread().getContextClassLoader());
  }

  /**
   * Returns the current environment container.
   */
  public static EjbContainer getCurrent(ClassLoader loader)
  {
    synchronized (_localContainer) {
      return _localContainer.get(loader);
    }
  }

  /**
   * Returns the parent loader
   */
  public EnvironmentClassLoader getClassLoader()
  {
    return _classLoader;
  }

  /**
   * Returns the introspection class loader
   */
  public ClassLoader getIntrospectionClassLoader()
  {
    return _tempClassLoader;
  }

  /**
   * Returns the configuration manager.
   */
  public EjbConfigManager getConfigManager()
  {
    return _configManager;
  }

  public EjbContainer getParent()
  {
    return _parentContainer;
  }

  /**
   * Returns the protocol manager.
   */
  public EjbProtocolManager getProtocolManager()
  {
    return _protocolManager;
  }

  /**
   * Returns the amber persistence unit for ejb.
   */
  public AmberPersistenceUnit createEjbPersistenceUnit()
  {
    if (_ejbPersistenceUnit == null) {
      try {
        AmberContainer amber = AmberContainer.create(_classLoader);

        _ejbPersistenceUnit = amber.createPersistenceUnit("resin-ejb");
        _ejbPersistenceUnit.setBytecodeGenerator(false);
        ClassLoader loader = SimpleLoader.create(getWorkDir());
        _ejbPersistenceUnit.setEnhancedLoader(loader);
        _ejbPersistenceUnit.initLoaders();
        // _ejbPersistenceUnit.setTableCacheTimeout(_entityCacheTimeout);
      } catch (RuntimeException e) {
        throw e;
      } catch (Exception e) {
        throw ConfigException.create(e);
      }
    }

    return _ejbPersistenceUnit;
  }

  //
  // configuration
  //

  /**
   * true if beans should be auto-compiled
   */
  public void setAutoCompile(boolean isAutoCompile)
  {
    _isAutoCompile = isAutoCompile;
  }

  /**
   * true if beans should be auto-compiled
   */
  public boolean isAutoCompile()
  {
    return _isAutoCompile;
  }

  /**
   * The work directory for EJB-generated files
   */
  public void setWorkDir(Path workDir)
  {
    _workDir = workDir;
  }

  /**
   * The work directory for EJB-generated files
   */
  public Path getWorkDir()
  {
    return _workDir;
  }

  /**
   * The JMS connection factory for the container.
   */
  public void setJmsConnectionFactory(ConnectionFactory factory)
  {
    _jmsConnectionFactory = factory;
  }

  /**
   * Sets the JMS connection factory for the container.
   */
  public ConnectionFactory getJmsConnectionFactory()
  {
    return _jmsConnectionFactory;
  }

  /**
   * Sets the consumer maximum for the container.
   */
  public void setMessageConsumerMax(int consumerMax)
  {
    _messageConsumerMax = consumerMax;
  }

  /**
   * The consumer maximum for the container.
   */
  public int getMessageConsumerMax()
  {
    return _messageConsumerMax;
  }

  /**
   * Copy defaults from the parent container when first created.
   */
  private void copyContainerDefaults(EjbContainer parent)
  {
    _isAutoCompile = parent._isAutoCompile;
    _jmsConnectionFactory = parent._jmsConnectionFactory;
    _messageConsumerMax = parent._messageConsumerMax;
  }

  //
  // Bean configuration and management
  //

  public <T> void createBean(AnnotatedType<T> type, InjectionTarget<T> injectionTarget)
  {
    _configManager.addAnnotatedType(type, injectionTarget);
  }

  //
  // AbstractServer management
  //

  /**
   * Adds a server.
   */
  public void addServer(AbstractServer<?> server)
  {
    _serverList.add(server);

    getProtocolManager().addServer(server);
  }

  /**
   * Returns the server specified by the ejbName, or null if not found.
   */
  public AbstractServer getServer(String ejbName)
  {
    for (AbstractServer server : _serverList) {
      if (server.getEJBName().equals(ejbName)) {
        return server;
      }
    }

    return null;
  }

  /**
   * Returns the server specified by the path and ejbName, or null if not found.
   */
  public AbstractServer getServer(Path path, String ejbName)
  {
    String mappedName = path.getFullPath() + "#" + ejbName;

    for (AbstractServer server : _serverList) {
      if (mappedName.equals(server.getId())) {
        return server;
      }
    }

    return null;
  }

  //
  // ScanListener
  //

  /**
   * Since EJB doesn't bytecode enhance, it's priority 1
   */
  public int getScanPriority()
  {
    return 1;
  }

  /**
   * Adds a root URL
   */
  public void addRoot(Path root)
  {
    if (root.getURL().endsWith(".jar"))
      root = JarPath.create(root);

    // XXX: ejb/0fbn
    Path ejbJar = root.lookup("META-INF/ejb-jar.xml");
    if (ejbJar.canRead())
      getConfigManager().addEjbPath(ejbJar);

    _ejbUrls.add(root.getURL());
  }

  /**
   * Returns true if the root is a valid scannable root.
   */
  public boolean isRootScannable(Path root)
  {
    if (! root.lookup("META-INF/ejb-jar.xml").canRead()) {
      return false;
    }
    else if (_ejbUrls.contains(root.getURL())) {
      return false;
    }
   
    if (log.isLoggable(Level.FINE))
      log.fine("EJB scanning '" + root.getFullPath() + "'");

    EjbRootConfig context = _configManager.createRootConfig(root);

    if (context.isScanComplete())
      return false;
    else {
      context.setScanComplete(true);
      return true;
    }
  }

  @Override
  public ScanClass scanClass(Path root, String className, int modifiers)
  {
    if (Modifier.isInterface(modifiers))
      return null;
    else if (Modifier.isAbstract(modifiers))
      return null;
    else
      return new EjbScanClass(root, className, this);
  }

  public boolean isScanMatchAnnotation(CharBuffer annotationName)
  {
    if (annotationName.matches("javax.ejb.Stateless")) {
      return true;
    }
    else if (annotationName.matches("javax.ejb.Stateful")) {
      return true;
    }
    else if (annotationName.matches("javax.ejb.MessageDriven")) {
      return true;
    }
    else
      return false;
  }

  /**
   * Callback to note the class matches
   */
  public void classMatchEvent(EnvironmentClassLoader loader,
                              Path root,
                              String className)
  {
    EjbRootConfig config = _configManager.createRootConfig(root);
    config.addClassName(className);
  }
 
  void addScanClass(Path root,
                    String className)
  {
    EjbRootConfig config = _configManager.createRootConfig(root);
    config.addClassName(className);
  }

  //
  // lifecycle methods
  //

  public void init()
  {
  }

  private void config()
  {
    _configManager.start();
  }

  public void start() throws ConfigException
  {
    try {
      AmberContainer.create().start();

      config()// ejb/4200

      Thread thread = Thread.currentThread();
      ClassLoader oldLoader = thread.getContextClassLoader();

      for (AbstractServer server : _serverList) {
        try {
          thread.setContextClassLoader(server.getClassLoader());

          server.start();
        } finally {
          thread.setContextClassLoader(oldLoader);
        }
      }

      AmberContainer.create().start();
    } catch (RuntimeException e) {
      throw e;
    } catch (Exception e) {
      throw ConfigException.create(e);
    }
  }

  /**
   * Closes the container.
   */
  public void destroy()
  {
    /*
     * if (! _lifecycle.toDestroy()) return;
     */

    try {
      ArrayList<AbstractServer> servers;
      servers = new ArrayList<AbstractServer>(_serverList);

      _serverList.clear();

      // only purpose of the sort is to make the qa order consistent
      Collections.sort(servers, new ServerCmp());

      for (AbstractServer server : servers) {
        try {
          getProtocolManager().removeServer(server);
        } catch (Throwable e) {
          log.log(Level.WARNING, e.toString(), e);
        }
      }

      for (AbstractServer server : servers) {
        try {
          server.destroy();
        } catch (Throwable e) {
          log.log(Level.WARNING, e.toString(), e);
        }
      }
    } catch (Throwable e) {
      log.log(Level.WARNING, e.toString(), e);
    }
  }

  /**
   * Handles the case where the environment is configuring
   */
  public void environmentConfigure(EnvironmentClassLoader loader)
  {
    config();
  }

  /**
   * Handles the case where the environment is configuring
   */
  public void environmentBind(EnvironmentClassLoader loader)
  {
  }

  /**
   * Handles the case where the environment is starting (after init).
   */
  public void environmentStart(EnvironmentClassLoader loader)
  {
    start();
  }

  /**
   * Handles the case where the environment is stopping
   */
  public void environmentStop(EnvironmentClassLoader loader)
  {
    destroy();
  }

  public String toString()
  {
    return getClass().getSimpleName() + "[" + _classLoader + "]";
  }

  /**
   * Sorts the servers so they can be destroyed in a consistent order. (To make
   * QA sane.)
   */
  static class ServerCmp implements Comparator<AbstractServer> {
    public int compare(AbstractServer a, AbstractServer b)
    {
      return a.getEJBName().compareTo(b.getEJBName());
    }
  }
}
TOP

Related Classes of com.caucho.ejb.manager.EjbContainer$ServerCmp

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.