/* * 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.util.ArrayList; import java.util.HashSet; import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.sql.DataSourceDefinition; import javax.decorator.Delegate; import javax.ejb.MessageDriven; import javax.ejb.Startup; import javax.ejb.Stateless; import javax.ejb.Stateful; import javax.enterprise.context.NormalScope; import javax.enterprise.event.Observes; import javax.enterprise.inject.Disposes; import javax.enterprise.inject.Produces; import javax.enterprise.inject.Specializes; import javax.enterprise.inject.Stereotype; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Qualifier; import javax.inject.Scope; import com.caucho.config.inject.InjectScanManager.AnnType; import com.caucho.inject.Jndi; import com.caucho.inject.MBean; import com.caucho.loader.enhancer.ScanClass; /** * The web beans container for a given environment. */ class InjectScanClass implements ScanClass { private static final Logger log = Logger.getLogger(InjectScanClass.class.getName()); private static final char []PRODUCES = Produces.class.getName().toCharArray(); private static final char []DISPOSES = Disposes.class.getName().toCharArray(); private static final char []OBSERVES = Observes.class.getName().toCharArray(); private static final char []OBJECT = Object.class.getName().toCharArray(); private static final HashSet<Class<?>> _registerAnnotationSet = new HashSet<Class<?>>(); private static final HashSet<Class<?>> _immediateResourceSet = new HashSet<Class<?>>(); private final String _className; private final InjectScanManager _scanManager; private InjectScanClass _parent; private ArrayList<InjectScanClass> _children; private boolean _isScanClass; private boolean _isRegisterRequired; private boolean _isRegistered; private boolean _isObserves; InjectScanClass(String className, InjectScanManager manager) { _className = className; _scanManager = manager; } /** * Returns the bean's class name. */ public String getClassName() { return _className; } public void setScanClass() { _isScanClass = true; } public boolean isScanClass() { return _isScanClass; } /** * Returns true if registration is required */ public boolean isRegisterRequired() { return _isRegisterRequired; } public boolean isRegistered() { return _isRegistered; } public boolean isObserves() { return _isObserves; } @Override public void addInterface(char[] buffer, int offset, int length) { addParent(new String(buffer, offset, length)); } @Override public void addSuperClass(char[] buffer, int offset, int length) { if (isMatch(buffer, offset, length, OBJECT)) { return; } addParent(new String(buffer, offset, length)); } @Override public void addClassAnnotation(char[] buffer, int offset, int length) { try { AnnType annType = _scanManager.loadAnnotation(buffer, offset, length); if (annType == null) return; if (annType.getType() == Observes.class) setObserves(); if (_isRegisterRequired) { if (_immediateResourceSet.contains(annType.getType())) { _scanManager.addImmediateResource(this); } return; } if (_registerAnnotationSet.contains(annType.getType())) { _isRegisterRequired = true; return; } for (Annotation ann : annType.getAnnotations()) { Class<? extends Annotation> metaAnnType = ann.annotationType(); if (metaAnnType == Stereotype.class) { _isRegisterRequired = true; } else if (metaAnnType == Scope.class) { _isRegisterRequired = true; } else if (metaAnnType == NormalScope.class) { // ioc/02a3 _isRegisterRequired = true; } } } catch (ClassNotFoundException e) { log.log(Level.FINER, e.toString(), e); } } private void setObserves() { _isObserves = true; _isRegisterRequired = true; // ioc/0b25 if (_children != null) { for (InjectScanClass scanClass : _children) { scanClass.setObserves(); } } } @Override public void addPoolString(char[] buffer, int offset, int length) { if (isMatch(buffer, offset, length, PRODUCES)) { _isRegisterRequired = true; } else if (isMatch(buffer, offset, length, DISPOSES)) { _isRegisterRequired = true; } else if (isMatch(buffer, offset, length, OBSERVES)) { setObserves(); } } @Override public boolean finishScan() { if (_isRegisterRequired || _scanManager.isCustomExtension() || _parent != null && _parent.isRegistered()) { register(); } return true; } private void addParent(String className) { InjectScanClass parent = _scanManager.createScanClass(className); parent.addChild(this); if (_parent == null) _parent = parent; } private void addChild(InjectScanClass child) { if (_children == null) _children = new ArrayList<InjectScanClass>(); if (! _children.contains(child)) _children.add(child); if (_isObserves) { child.setObserves(); } } void register() { if (_isScanClass && ! _isRegistered) { _isRegistered = true; _scanManager.addDiscoveredClass(this); } if (_children != null) { for (InjectScanClass child : _children) { child.register(); } } } private boolean isMatch(char []buffer, int offset, int length, char []matchBuffer) { if (length != matchBuffer.length) return false; for (int i = 0; i < length; i++) { if (buffer[offset + i] != matchBuffer[i]) return false; } return true; } public String toString() { return getClass().getSimpleName() + "[" + _className + "]"; } static { _registerAnnotationSet.add(Inject.class); _registerAnnotationSet.add(Named.class); _registerAnnotationSet.add(Specializes.class); _registerAnnotationSet.add(Delegate.class); _registerAnnotationSet.add(Startup.class); _registerAnnotationSet.add(Jndi.class); _registerAnnotationSet.add(MBean.class); _registerAnnotationSet.add(Stateless.class); _registerAnnotationSet.add(Stateful.class); _registerAnnotationSet.add(javax.ejb.Singleton.class); _registerAnnotationSet.add(MessageDriven.class); _registerAnnotationSet.add(Qualifier.class); _registerAnnotationSet.add(DataSourceDefinition.class); _immediateResourceSet.add(DataSourceDefinition.class); } }