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

com.sun.enterprise.deployment.annotation.handlers.ResourceHandler Maven / Gradle / Ivy

There is a newer version: 4.1.2.181
Show newest version
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2012 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 com.sun.enterprise.deployment.annotation.handlers;

import com.sun.enterprise.deployment.*;
import com.sun.enterprise.deployment.util.DOLUtils;
import com.sun.enterprise.deployment.annotation.context.ResourceContainerContext;
import com.sun.enterprise.deployment.annotation.context.ResourceContainerContextImpl;
import org.glassfish.apf.AnnotationHandlerFor;
import org.glassfish.apf.AnnotationInfo;
import org.glassfish.apf.AnnotationProcessorException;
import org.glassfish.apf.HandlerProcessingResult;
import org.glassfish.hk2.api.ServiceLocator;
import org.jvnet.hk2.annotations.Service;
import javax.inject.Inject;
import javax.inject.Provider;

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

import javax.annotation.Resource;
import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.Collection;
import java.util.ArrayList;
import java.util.logging.Level;

/**
 * This handler is responsible for handling the javax.annotation.Resource
 * annotation.
 */
@Service
@AnnotationHandlerFor(Resource.class)
public class ResourceHandler extends AbstractResourceHandler {

    @Inject
    private ServiceLocator habitat;

    @Inject 
    private Provider wSDolSupportProvider;

    // Map of all @Resource types that map to env-entries and their
    // corresponding types.  
    // XXX - this needs to be synchronized with the list in
    // com.sun.enterprise.deployment.EnvironmentProperty
    private static final Map envEntryTypes;

    static {

        envEntryTypes = new HashMap();

        envEntryTypes.put(String.class, String.class);

        envEntryTypes.put(Class.class, Class.class);

        envEntryTypes.put(Character.class, Character.class);
        envEntryTypes.put(Character.TYPE, Character.class);
        envEntryTypes.put(char.class, Character.class);

        envEntryTypes.put(Byte.class, Byte.class);
        envEntryTypes.put(Byte.TYPE, Byte.class);
        envEntryTypes.put(byte.class, Byte.class);

        envEntryTypes.put(Short.class, Short.class);
        envEntryTypes.put(Short.TYPE, Short.class);
        envEntryTypes.put(short.class, Short.class);

        envEntryTypes.put(Integer.class, Integer.class);
        envEntryTypes.put(Integer.TYPE, Integer.class);
        envEntryTypes.put(int.class, Integer.class);

        envEntryTypes.put(Long.class, Long.class);        
        envEntryTypes.put(Long.TYPE, Long.class);        
        envEntryTypes.put(long.class, Long.class);        

        envEntryTypes.put(Boolean.class, Boolean.class);
        envEntryTypes.put(Boolean.TYPE, Boolean.class);
        envEntryTypes.put(boolean.class, Boolean.class);

        envEntryTypes.put(Double.class, Double.class);
        envEntryTypes.put(Double.TYPE, Double.class);
        envEntryTypes.put(double.class, Double.class);

        envEntryTypes.put(Float.class, Float.class);
        envEntryTypes.put(Float.TYPE, Float.class);
        envEntryTypes.put(float.class, Float.class);

        envEntryTypes.put(Number.class, Number.class);
    }
        
    public ResourceHandler() {
    }

    /**
     * This entry point is used both for a single @Resource and iteratively
     * from a compound @Resources processor.
     */
    protected HandlerProcessingResult processAnnotation(AnnotationInfo ainfo,
            ResourceContainerContext[] rcContexts)
            throws AnnotationProcessorException {

        Resource resourceAn = (Resource)ainfo.getAnnotation();
        return processResource(ainfo, rcContexts, resourceAn);
    }

    protected HandlerProcessingResult processResource(AnnotationInfo ainfo,
                                   ResourceContainerContext[] rcContexts, 
                                   Resource resourceAn)
        throws AnnotationProcessorException {

        ResourceReferenceDescriptor resourceRefs[] = null;

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

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

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

            defaultResourceType = f.getType();

            target = new InjectionTarget();
            target.setFieldName(f.getName());
            target.setClassName(targetClassName);
            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);

            // prefixing with fully qualified type name 
            defaultLogicalName = targetClassName + "/" + propertyName;

            defaultResourceType = m.getParameterTypes()[0];

            target = new InjectionTarget();
            target.setMethodName(m.getName());
            target.setClassName(targetClassName);
            target.setMetadataSource(MetadataSource.ANNOTATION);

        } else if (ElementType.TYPE.equals(ainfo.getElementType())) {
            // name() and type() are required for TYPE-level @Resource
            if (resourceAn.name().equals("") ||
                    resourceAn.type() == Object.class) {
                Class c = (Class) ainfo.getAnnotatedElement();
                log(Level.SEVERE, ainfo,
                    localStrings.getLocalString(
        "enterprise.deployment.annotation.handlers.invalidtypelevelresource",
                    "Invalid TYPE-level @Resource with name() = [{0}] and " +
                    "type = [{1}] in {2}. Each TYPE-level @Resource must " +
                    "specify both name() and type().",
                    new Object[] { resourceAn.name(), resourceAn.type(), c }));
                return getDefaultFailedResult();
            }
        } else {
            // can't happen
            return getDefaultFailedResult();
        }

        // NOTE that default value is Object.class, not null
        Class resourceType = (resourceAn.type() == Object.class) ?
                defaultResourceType : resourceAn.type();
        String logicalName = resourceAn.name().equals("") ?
                defaultLogicalName : resourceAn.name();

        /*
         * Get corresponding class type.  This does the appropriate
         * mapping for primitives.  For everything else, the type is
         * unchanged.  Really onlt need to do this for simple env-entries,
         * but it shouldn't hurt to do it for everything.
         */
        if (envEntryTypes.containsKey(resourceType))
            resourceType = envEntryTypes.get(resourceType);

        EnvironmentProperty[] descriptors =
            getDescriptors(resourceType, logicalName, rcContexts, resourceAn);

        for (EnvironmentProperty desc : descriptors) {
            if (target != null)
                desc.addInjectionTarget(target);

            if (!ok(desc.getName())) { // a new one
                desc.setName(logicalName);
            }
            if (!ok(desc.getInjectResourceType())) {              
                // if the optional resource type is not set, 
                // set it using the resource type of field/method
                desc.setInjectResourceType(resourceType.getName());
            }

            // merge description
            if (!ok(desc.getDescription()) && ok(resourceAn.description()))
                desc.setDescription(resourceAn.description());

            // merge lookup-name and mapped-name
            if (!desc.hasLookupName() && !desc.isSetValueCalled() &&
                    ok(getResourceLookupValue(resourceAn, ainfo)))
                desc.setLookupName(getResourceLookupValue(resourceAn, ainfo));
            if (!ok(desc.getMappedName()) && ok(resourceAn.mappedName()))
                desc.setMappedName(resourceAn.mappedName());

            // merge authentication-type and shareable
            if (desc instanceof ResourceReferenceDescriptor) {
                ResourceReferenceDescriptor rdesc =
                    (ResourceReferenceDescriptor)desc;
                if (!rdesc.hasAuthorization()) {
                    switch (resourceAn.authenticationType()) {
                    case APPLICATION:
                        rdesc.setAuthorization(
                         ResourceReferenceDescriptor.APPLICATION_AUTHORIZATION);
                        break;
                    case CONTAINER:
                        rdesc.setAuthorization(
                         ResourceReferenceDescriptor.CONTAINER_AUTHORIZATION);
                        break;
                    default:    // should never happen
                        Class c = (Class) ainfo.getAnnotatedElement();
                        log(Level.SEVERE, ainfo,
                            localStrings.getLocalString(
        "enterprise.deployment.annotation.handlers.invalidauthenticationtype",
                            "Invalid AuthenticationType [{0}] in @Resource " +
                            "with name() = [{1}] and " +
                            "type = [{1}] in {2}.",
                            new Object[] { resourceAn.authenticationType(),
                                    resourceAn.name(), resourceAn.type(), c }));
                        return getDefaultFailedResult();
                    }
                }
                if (!rdesc.hasSharingScope()) {
                    rdesc.setSharingScope(resourceAn.shareable() ?
                         ResourceReferenceDescriptor.RESOURCE_SHAREABLE :
                         ResourceReferenceDescriptor.RESOURCE_UNSHAREABLE);
                }
            }
        }

        return getDefaultProcessedResult();
    }

    private EnvironmentProperty[] getDescriptors(Class resourceType,
        String logicalName, ResourceContainerContext[] rcContexts, Resource resourceAn) {
            
        Class webServiceContext = null;
        try {

            WSDolSupport support  = wSDolSupportProvider.get(); 
            if (support!=null) {
                webServiceContext = support.getType("javax.xml.ws.WebServiceContext");
            }
        }   catch(Exception e) {
            // we don't care, either we don't have the class, ot the bundled is not installed
        }
        if (resourceType.getName().equals("javax.jms.Queue") ||
                resourceType.getName().equals("javax.jms.Topic")) {
            return getMessageDestinationReferenceDescriptors(
                                                    logicalName, rcContexts);
        } else if (envEntryTypes.containsKey(resourceType) ||
                resourceType.isEnum()) {
            return getEnvironmentPropertyDescriptors(logicalName, rcContexts,
                                                    resourceAn);
        } else if (resourceType == javax.sql.DataSource.class ||
                resourceType.getName().equals("javax.jms.ConnectionFactory") ||
                resourceType.getName().equals("javax.jms.QueueConnectionFactory") ||
                resourceType.getName().equals("javax.jms.TopicConnectionFactory") ||
                resourceType == webServiceContext ||
                resourceType.getName().equals("javax.mail.Session") || 
                resourceType.getName().equals("java.net.URL") ||
                resourceType.getName().equals("javax.resource.cci.ConnectionFactory") ||
                resourceType == org.omg.CORBA_2_3.ORB.class || 
                resourceType == org.omg.CORBA.ORB.class || 
                resourceType.getName().equals("javax.jms.XAConnectionFactory") ||
                resourceType.getName().equals("javax.jms.XAQueueConnectionFactory") ||
                resourceType.getName().equals("javax.jms.XATopicConnectionFactory") || 
                DOLUtils.isRAConnectionFactory(habitat, resourceType.getName(), ((ResourceContainerContextImpl)rcContexts[0]).getAppFromDescriptor()) ) {
            return getResourceReferenceDescriptors(logicalName, rcContexts);
        } else {
            return getResourceEnvReferenceDescriptors(logicalName,
                                                            rcContexts);
        }
    }

    /**
     * Return ResourceReferenceDescriptors with given name if exists or a new
     * one without name being set.
     * @param logicalName
     * @param rcContexts
     * @return an array of ResourceReferenceDescriptor
     */
    private ResourceReferenceDescriptor[] getResourceReferenceDescriptors(
            String logicalName, ResourceContainerContext[] rcContexts) {
        ResourceReferenceDescriptor resourceRefs[] =
                new ResourceReferenceDescriptor[rcContexts.length];
        for (int i = 0; i < rcContexts.length; i++) {
            ResourceReferenceDescriptor resourceRef =
                rcContexts[i].getResourceReference(logicalName);
            if (resourceRef == null) {
                resourceRef = new ResourceReferenceDescriptor();
                rcContexts[i].addResourceReferenceDescriptor(resourceRef);
            }
            resourceRefs[i] = resourceRef;
        }

        return resourceRefs;
    }

    /**
     * Return MessageDestinationReferenceDescriptors with given name 
     * if exists or a new one without name being set.
     * @param logicName
     * @param rcContexts
     * @return an array of message destination reference descriptors
     */
    private MessageDestinationReferenceDescriptor[] 
        getMessageDestinationReferenceDescriptors
        (String logicName, ResourceContainerContext[] rcContexts) {
            
        MessageDestinationReferenceDescriptor msgDestRefs[] =
                new MessageDestinationReferenceDescriptor[rcContexts.length];
        for (int i = 0; i < rcContexts.length; i++) {
            MessageDestinationReferenceDescriptor msgDestRef =
                rcContexts[i].getMessageDestinationReference(logicName);
            if (msgDestRef == null) {
               msgDestRef = new MessageDestinationReferenceDescriptor();
               rcContexts[i].addMessageDestinationReferenceDescriptor(
                   msgDestRef);
            }
            msgDestRefs[i] = msgDestRef;
        }

        return msgDestRefs;
    }

    /**
     * Return ResourceEnvReferenceDescriptors with given name
     * if exists or a new one without name being set.
     * @param logicName
     * @param rcContexts
     * @return an array of resource env reference descriptors
     */
    private ResourceEnvReferenceDescriptor[]
        getResourceEnvReferenceDescriptors
        (String logicName, ResourceContainerContext[] rcContexts) {

        ResourceEnvReferenceDescriptor resourceEnvRefs[] =
                new ResourceEnvReferenceDescriptor[rcContexts.length];
        for (int i = 0; i < rcContexts.length; i++) {
            ResourceEnvReferenceDescriptor resourceEnvRef =
                rcContexts[i].getResourceEnvReference(logicName);
            if (resourceEnvRef == null) {
               resourceEnvRef = new ResourceEnvReferenceDescriptor();
               rcContexts[i].addResourceEnvReferenceDescriptor(
                   resourceEnvRef);
            }
            resourceEnvRefs[i] = resourceEnvRef;
        }

        return resourceEnvRefs;
    }

    /**
     * Return EnvironmentProperty descriptors with the given name 
     * if it exists or a new one without name being set.
     *
     * @param logicalName       the JNDI name
     * @param rcContexts
     * @return an array of EnvironmentProperty descriptors
     */
    private EnvironmentProperty[] getEnvironmentPropertyDescriptors(
                                    String logicalName,
                                    ResourceContainerContext[] rcContexts,
                                    Resource annotation) {

        Collection envEntries =
            new ArrayList();

        for (int i = 0; i < rcContexts.length; i++) {
            EnvironmentProperty envEntry =
                rcContexts[i].getEnvEntry(logicalName);
            // For @Resource declarations that map to env-entries, if there
            // is no corresponding deployment descriptor entry that has a
            // value and no lookup(), it's treated as if the declaration
            // doesn't exist.
            // A common case is that the @Resource is applied to a field
            // with a default value which was not overridden by the deployer.
            if (envEntry != null) {
                envEntries.add(envEntry);
            } else {
                envEntry = new EnvironmentProperty();
                envEntries.add(envEntry);
                rcContexts[i].addEnvEntryDescriptor(envEntry);
            }
        }

        return envEntries.toArray(new EnvironmentProperty[envEntries.size()]);
    }

    /**
     * Return the value of the "lookup" element of the @Resource annotation.
     * This method handles the case where the Resource class is an older
     * version before the lookup element was added; in that case access to
     * the lookup element will cause a NoSuchMethodError, which is caught
     * and ignored (with a warning message).
     *
     * @return the value of the lookup element
     */
    private String getResourceLookupValue(Resource annotation,
                                            AnnotationInfo ainfo) {
        String lookupValue = "";
        try {
            lookupValue = annotation.lookup();
        } catch(NoSuchMethodError nsme) {
            // Probably means lib endorsed dir is not set and an older version
            // of Resource is being picked up from JDK.
            // Don't treat this as a fatal error.
            try {
                log(Level.WARNING, ainfo,
                    localStrings.getLocalString(
                "enterprise.deployment.annotation.handlers.wrongresourceclass",
                        "Incorrect @Resource annotation class definition - " +
                        "missing lookup attribute"));
            } catch (AnnotationProcessorException ex) { }
        }
        return lookupValue;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy