Package com.caucho.config.inject

Source Code of com.caucho.config.inject.InjectScanManager$AnnType

/*
* Copyright (c) 1998-2011 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.config.inject;

import java.lang.annotation.Annotation;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.caucho.loader.EnvironmentClassLoader;
import com.caucho.loader.enhancer.ScanClass;
import com.caucho.loader.enhancer.ScanListener;
import com.caucho.util.CharBuffer;
import com.caucho.vfs.Path;

/**
* The web beans container for a given environment.
*/
class InjectScanManager implements ScanListener {
  private static final Logger log
    = Logger.getLogger(InjectScanManager.class.getName());

  private InjectManager _injectManager;

  private final HashMap<Path, ScanRootContext> _scanRootMap
    = new HashMap<Path, ScanRootContext>();

  private final ArrayList<ScanRootContext> _pendingScanRootList
    = new ArrayList<ScanRootContext>();

  private final ConcurrentHashMap<String, InjectScanClass> _scanClassMap
    = new ConcurrentHashMap<String, InjectScanClass>();

  private final ConcurrentHashMap<NameKey, AnnType> _annotationMap
    = new ConcurrentHashMap<NameKey, AnnType>();

  private boolean _isCustomExtension;

  private ArrayList<InjectScanClass> _pendingScanClassList
    = new ArrayList<InjectScanClass>();

  InjectScanManager(InjectManager injectManager)
  {
    _injectManager = injectManager;
  }

  /**
   * Returns the injection manager.
   */
  public InjectManager getInjectManager()
  {
    return _injectManager;
  }

  /**
   * True if a custom extension exists.
   */
  public void setIsCustomExtension(boolean isCustomExtension)
  {
    _isCustomExtension = isCustomExtension;

    if (isCustomExtension) {
      for (InjectScanClass scanClass : _scanClassMap.values()) {
        scanClass.register();
      }
    }
  }

  public boolean isCustomExtension()
  {
    return _isCustomExtension;
  }

  public ArrayList<ScanRootContext> getPendingScanRootList()
  {
    ArrayList<ScanRootContext> contextList
      = new ArrayList<ScanRootContext>(_pendingScanRootList);

    _pendingScanRootList.clear();

    return contextList;
  }

  public boolean isPending()
  {
    return _pendingScanClassList.size() > 0 || _pendingScanRootList.size() > 0;
  }

  public void addDiscoveredClass(InjectScanClass injectScanClass)
  {
    if (! _pendingScanClassList.contains(injectScanClass)) {
      _pendingScanClassList.add(injectScanClass);
    }
  }

  /**
   * discovers pending beans.
   */
  public void discover()
  {
    ArrayList<InjectScanClass> pendingScanClassList
      = new ArrayList<InjectScanClass>(_pendingScanClassList);

    _pendingScanClassList.clear();

    for (InjectScanClass scanClass : pendingScanClassList) {
      getInjectManager().discoverBean(scanClass);
    }
  }

  //
  // ScanListener

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

  @Override
  public boolean isRootScannable(Path root, String packageRoot)
  {
    ScanRootContext context = _scanRootMap.get(root);
    List<Path> beansXmlOverride = _injectManager.getBeansXmlOverride(root);

    Path scanRoot = root;

    if (packageRoot != null) {
      scanRoot = scanRoot.lookup(packageRoot.replace('.', '/'));
    }
   
    if (beansXmlOverride == null) {
      // TODO Should resin-beans.xml be included in this check?
      if (packageRoot != null) {
        if (! scanRoot.lookup("beans.xml").canRead()
            && ! scanRoot.lookup("META-INF/beans.xml").canRead()) {
          return false;
        }
      } else if (! (root.lookup("META-INF/beans.xml").canRead()
                    || (root.getFullPath().endsWith("WEB-INF/classes/")
                        && root.lookup("../beans.xml").canRead()))) {
        return false;
      }
    }

    if (context == null) {
      context = new ScanRootContext(scanRoot, packageRoot);
      _scanRootMap.put(root, context);
      _pendingScanRootList.add(context);
    }

    if (context.isScanComplete())
      return false;
    else {
      if (log.isLoggable(Level.FINER))
        log.finer("CanDI scanning " + root.getURL());

      context.setScanComplete(true);
      return true;
    }
  }

  /**
   * Checks if the class can be a simple class
   */
  @Override
  public ScanClass scanClass(Path root,
                             String packageRoot,
                             String className,
                             int modifiers)
  {
    // ioc/0j0k - package private allowed

    if (Modifier.isPrivate(modifiers))
      return null;
    else {
      InjectScanClass scanClass = createScanClass(className);

      scanClass.setScanClass();

      return scanClass;
    }
  }

  InjectScanClass getScanClass(String className)
  {
    return _scanClassMap.get(className);
  }

  InjectScanClass createScanClass(String className)
  {
    InjectScanClass scanClass = _scanClassMap.get(className);

    if (scanClass == null) {
      scanClass = new InjectScanClass(className, this);
      InjectScanClass oldScanClass;
      oldScanClass = _scanClassMap.putIfAbsent(className, scanClass);

      if (oldScanClass != null)
        scanClass = oldScanClass;
    }

    return scanClass;
  }

  /**
   * Loads an annotation for scanning.
   */
  public AnnType loadAnnotation(char[] buffer, int offset, int length)
    throws ClassNotFoundException
  {
    NameKey key = new NameKey(buffer, offset, length);

    AnnType annType = _annotationMap.get(key);

    if (annType != null)
      return annType;

    ClassLoader loader = getInjectManager().getClassLoader();

    String className = new String(buffer, offset, length);

    Class<?> cl = Class.forName(className, false, loader);

    annType = new AnnType(cl);

    _annotationMap.put(key.dup(), annType);

    return annType;
  }

  @Override
  public boolean isScanMatchAnnotation(CharBuffer string)
  {
    return false;
  }

  @Override
  public void classMatchEvent(EnvironmentClassLoader loader, Path root,
      String className)
  {
  }

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

  static class NameKey {
    private char[] _buffer;
    private int _offset;
    private int _length;

    NameKey(char[] buffer, int offset, int length)
    {
      _buffer = buffer;
      _offset = offset;
      _length = length;
    }

    public NameKey dup()
    {
      char[] buffer = new char[_length];

      System.arraycopy(_buffer, _offset, buffer, 0, _length);

      _buffer = buffer;
      _offset = 0;

      return this;
    }

    public int hashCode()
    {
      char[] buffer = _buffer;
      int offset = _offset;
      int length = _length;
      int hash = length;

      for (length--; length >= 0; length--) {
        char value = buffer[offset + length];

        hash = 65521 * hash + value;
      }

      return hash;
    }

    public boolean equals(Object o)
    {
      if (!(o instanceof NameKey))
        return false;

      NameKey key = (NameKey) o;

      if (_length != key._length)
        return false;

      char[] bufferA = _buffer;
      char[] bufferB = key._buffer;

      int offsetA = _offset;
      int offsetB = key._offset;

      for (int i = _length - 1; i >= 0; i--) {
        if (bufferA[offsetA + i] != bufferB[offsetB + i])
          return false;
      }

      return true;
    }
  }

  static class AnnType {
    private Class<?> _type;
    private Annotation[] _annotations;

    AnnType(Class<?> type)
    {
      _type = type;
    }

    public Class<?> getType()
    {
      return _type;
    }

    public Annotation[] getAnnotations()
    {
      if (_annotations == null)
        _annotations = _type.getAnnotations();

      return _annotations;
    }
  }
}
TOP

Related Classes of com.caucho.config.inject.InjectScanManager$AnnType

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.