Package org.glassfish.ejb.deployment.annotation.handlers

Source Code of org.glassfish.ejb.deployment.annotation.handlers.EJBHandler

/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2011 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License").  You
* may not use this file except in compliance with the License.  You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt.  See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license."  If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above.  However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/

package org.glassfish.ejb.deployment.annotation.handlers;

import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

import java.util.logging.Level;

import javax.ejb.EJB;
import javax.ejb.EJBHome;
import javax.ejb.EJBLocalHome;
import javax.ejb.Local;
import javax.ejb.Remote;

import com.sun.enterprise.deployment.EjbEntityDescriptor;
import com.sun.enterprise.deployment.EjbReferenceDescriptor;
import com.sun.enterprise.deployment.EjbSessionDescriptor;
import com.sun.enterprise.deployment.InjectionTarget;
import com.sun.enterprise.deployment.MetadataSource;
import org.glassfish.apf.AnnotationInfo;
import org.glassfish.apf.AnnotationProcessorException;
import org.glassfish.apf.HandlerProcessingResult;
import com.sun.enterprise.deployment.annotation.context.ResourceContainerContext;
import com.sun.enterprise.deployment.annotation.handlers.AbstractResourceHandler;
import org.jvnet.hk2.annotations.Service;

import static com.sun.enterprise.util.StringUtils.ok;

/**
* This handler is responsible for handling the javax.ejb.EJB
*
* @author Shing Wai Chan
*/
@Service
public class EJBHandler extends AbstractResourceHandler {
   
    public EJBHandler() {
    }

    /**
     * @return the annoation type this annotation handler is handling
     */
    public Class<? extends Annotation> getAnnotationType() {
        return EJB.class;
    }

    /**
     * Process a particular annotation which type is the same as the
     * one returned by @see getAnnotationType(). All information
     * pertinent to the annotation and its context is encapsulated
     * in the passed AnnotationInfo instance.
     *
     * @param ainfo the annotation information
     * @param rcContexts an array of ResourceContainerContext
     * @return HandlerProcessingResult
     */
    protected HandlerProcessingResult processAnnotation(AnnotationInfo ainfo,
            ResourceContainerContext[] rcContexts)
            throws AnnotationProcessorException {

        EJB ejbAn = (EJB)ainfo.getAnnotation();
        return processEJB(ainfo, rcContexts, ejbAn);
    }


    /**
     * Process a particular annotation whose type is the same as the
     * one returned by @see getAnnotationType(). All information
     * pertinent to the annotation and its context is encapsulated
     * in the passed AnnotationInfo instance.
     *
     * @param ainfo the annotation information
     * @param rcContexts an array of ResourceContainerContext
     * @param ejbAn
     * @return HandlerProcessingResult
     */
    protected HandlerProcessingResult processEJB(AnnotationInfo ainfo,
            ResourceContainerContext[] rcContexts, EJB ejbAn)
            throws AnnotationProcessorException {
        EjbReferenceDescriptor ejbRefs[] = null;

        String defaultLogicalName = null;
        Class defaultBeanInterface = null;
        InjectionTarget target = null;

        if (ElementType.FIELD.equals(ainfo.getElementType())) {
            Field f = (Field)ainfo.getAnnotatedElement();
            String targetClassName = f.getDeclaringClass().getName();

            defaultLogicalName = targetClassName + "/" + f.getName();

            defaultBeanInterface = f.getType();

            target = new InjectionTarget();
            target.setClassName(targetClassName);
            target.setFieldName(f.getName());
            target.setMetadataSource(MetadataSource.ANNOTATION);
           
        } else if (ElementType.METHOD.equals(ainfo.getElementType())) {

            Method m = (Method)ainfo.getAnnotatedElement();
            String targetClassName = m.getDeclaringClass().getName();

            validateInjectionMethod(m, ainfo);

            // Derive javabean property name.
            String propertyName = getInjectionMethodPropertyName(m, ainfo);

            defaultLogicalName = targetClassName + "/" + propertyName;

            defaultBeanInterface = m.getParameterTypes()[0];

            target = new InjectionTarget();
            target.setClassName(targetClassName);
            target.setMethodName(m.getName());
            target.setMetadataSource(MetadataSource.ANNOTATION);
           
        } else if( ElementType.TYPE.equals(ainfo.getElementType()) ) {
            // name() and beanInterface() are required for TYPE-level @EJB
            if (ejbAn.name().equals("") ||
                    ejbAn.beanInterface() == Object.class ) {
                Class c = (Class) ainfo.getAnnotatedElement();
                log(Level.SEVERE, ainfo,
                    localStrings.getLocalString(
                    "enterprise.deployment.annotation.handlers.invalidtypelevelejb",
                    "Invalid TYPE-level @EJB with name() = [{0}] and " +
                    "beanInterface = [{1}] in {2}.  Each TYPE-level @EJB " +
                    "must specify both name() and beanInterface().",
                    new Object[] { ejbAn.name(), ejbAn.beanInterface(), c }));
                return getDefaultFailedResult();
            }
        } else {
            // can't happen
            return getDefaultFailedResult();
        }

        // NOTE that default value is Object.class, not null
        Class beanInterface = (ejbAn.beanInterface() == Object.class) ?
            defaultBeanInterface : ejbAn.beanInterface();
        String logicalName = ejbAn.name().equals("") ?
            defaultLogicalName : ejbAn.name();

        ejbRefs = getEjbReferenceDescriptors(logicalName, rcContexts);
        for (EjbReferenceDescriptor ejbRef : ejbRefs) {
            if (target != null)
                ejbRef.addInjectionTarget(target);

            if (!ok(ejbRef.getName()))  // a new one
                ejbRef.setName(logicalName);

            // merge type information
            setEjbType(ejbRef, beanInterface);

            // merge description
            if (!ok(ejbRef.getDescription()) && ok(ejbAn.description()))
                ejbRef.setDescription(ejbAn.description());

            // merge lookup-name and mapped-name
            if (!ejbRef.hasLookupName() && ok(ejbAn.lookup()))
                ejbRef.setLookupName(ejbAn.lookup());
            if (!ok(ejbRef.getMappedName()) && ok(ejbAn.mappedName()))
                ejbRef.setMappedName(ejbAn.mappedName());

            // merge beanName/linkName
            if (!ok(ejbRef.getLinkName()) && ok(ejbAn.beanName()))
                ejbRef.setLinkName(ejbAn.beanName());
        }

        return getDefaultProcessedResult();
    }

    /**
     * Return EjbReferenceDescriptors with given name if exists or a new
     * one without name being set.
     * @param logicalName
     * @param rcContexts
     * @return an array of EjbReferenceDescriptor
     */
    private EjbReferenceDescriptor[] getEjbReferenceDescriptors(
            String logicalName, ResourceContainerContext[] rcContexts) {
        EjbReferenceDescriptor ejbRefs[] =
                new EjbReferenceDescriptor[rcContexts.length];
        for (int i = 0; i < rcContexts.length; i++) {
            EjbReferenceDescriptor ejbRef =
                (EjbReferenceDescriptor)rcContexts[i].getEjbReference(logicalName);
            if (ejbRef == null) {
                ejbRef = new EjbReferenceDescriptor();
                rcContexts[i].addEjbReferenceDescriptor(ejbRef);
            }
            ejbRefs[i] = ejbRef;
        }

        return ejbRefs;
    }

    /**
     * Set the type information for the EJB, but only if it hasn't
     * already been set by the deployment descriptor.
     */
    private void setEjbType(EjbReferenceDescriptor ejbRef,
                                         Class beanInterface) {
        if (EJBHome.class.isAssignableFrom(beanInterface) ||
                EJBLocalHome.class.isAssignableFrom(beanInterface)) {
            setEjbHomeType(ejbRef, beanInterface);
        } else {
            setEjbIntfType(ejbRef, beanInterface);
        }
    }

    /**
     * Set the type information for the EJB starting with the EJB business
     * interface, but only if it hasn't already been set.
     */
    private void setEjbIntfType(EjbReferenceDescriptor ejbRef,
                                        Class beanInterface) {
        if (ejbRef.getEjbInterface() != null)
            return;

        // only set it if not already set by DD
        ejbRef.setEjbInterface(beanInterface.getName());

        if (beanInterface.getAnnotation(Local.class) != null) {
            ejbRef.setLocal(true);
        } else {
            // If beanInterface has @Remote annotation, setLocal(false);
            // If beanInterface has neither @Local nor @Remote,
            // assume remote for now. We can't know for sure until the
            // post-validation stage.  Even though local business will
            // probably be more common than remote business, defaulting
            // to remote business simplifies the post-application
            // validation logic considerably.  See
            // EjbBundleValidator.accept(EjbReferenceDescriptor)
            // for more details.
            ejbRef.setLocal(false);
        }
        ejbRef.setType(EjbSessionDescriptor.TYPE);
    }

    /**
     * Set the type information for the EJB starting with the EJB Home
     * interface, but only if it hasn't already been set.
     */
    private void setEjbHomeType(EjbReferenceDescriptor ejbRef,
                                        Class beanInterface) {

        if (ejbRef.getHomeClassName() != null)
            return;

        // default is Session bean
        String targetBeanType = EjbSessionDescriptor.TYPE;
        ejbRef.setHomeClassName(beanInterface.getName());

        try {
            // Set bean Interface as well so we have all
            // the info that would have been in an ejb-ref/
            // ejb-local-ref
            Method[] methods = beanInterface.getMethods();
            for (Method m : methods) {
                if (m.getName().equals("create")) {
                    ejbRef.setEjbInterface(m.getReturnType().getName());
                    break;
                }
            }
            // Use existence of findByPrimaryKey method on Home to
            // determine target bean type
            for (Method m : methods) {
                if (m.getName().equals("findByPrimaryKey")) {
                    targetBeanType = EjbEntityDescriptor.TYPE;
                    break;
                }
            }
        } catch(Exception e) {
            if (logger.isLoggable(Level.FINE)) {
                logger.log(Level.FINE,
                "component intf / ejb type annotation processing error", e);
            }
        }

        ejbRef.setLocal(EJBLocalHome.class.isAssignableFrom(beanInterface));
        ejbRef.setType(targetBeanType);
    }
}
TOP

Related Classes of org.glassfish.ejb.deployment.annotation.handlers.EJBHandler

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.