Package org.apache.geronimo.connector.deployment

Source Code of org.apache.geronimo.connector.deployment.ResourceRefBuilder

/**
*  Licensed to the Apache Software Foundation (ASF) under one or more
*  contributor license agreements.  See the NOTICE file distributed with
*  this work for additional information regarding copyright ownership.
*  The ASF licenses this file to You under the Apache License, Version 2.0
*  (the "License"); you may not use this file except in compliance with
*  the License.  You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/

package org.apache.geronimo.connector.deployment;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;
import javax.resource.ResourceException;
import javax.xml.namespace.QName;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.geronimo.common.DeploymentException;
import org.apache.geronimo.gbean.AbstractName;
import org.apache.geronimo.gbean.AbstractNameQuery;
import org.apache.geronimo.gbean.GBeanInfo;
import org.apache.geronimo.gbean.GBeanInfoBuilder;
import org.apache.geronimo.gbean.SingleElementCollection;
import org.apache.geronimo.j2ee.deployment.CorbaGBeanNameSource;
import org.apache.geronimo.j2ee.deployment.Module;
import org.apache.geronimo.j2ee.deployment.annotation.AnnotatedApp;
import org.apache.geronimo.j2ee.deployment.annotation.ResourceAnnotationHelper;
import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
import org.apache.geronimo.kernel.GBeanNotFoundException;
import org.apache.geronimo.kernel.repository.Artifact;
import org.apache.geronimo.kernel.repository.Dependency;
import org.apache.geronimo.kernel.repository.Environment;
import org.apache.geronimo.naming.deployment.AbstractNamingBuilder;
import org.apache.geronimo.naming.deployment.ResourceEnvironmentBuilder;
import org.apache.geronimo.naming.deployment.ResourceEnvironmentSetter;
import org.apache.geronimo.naming.reference.JndiReference;
import org.apache.geronimo.naming.reference.ORBReference;
import org.apache.geronimo.naming.reference.ResourceReferenceFactory;
import org.apache.geronimo.naming.reference.URLReference;
import org.apache.geronimo.xbeans.geronimo.naming.GerPatternType;
import org.apache.geronimo.xbeans.geronimo.naming.GerResourceRefDocument;
import org.apache.geronimo.xbeans.geronimo.naming.GerResourceRefType;
import org.apache.geronimo.xbeans.javaee6.DescriptionType;
import org.apache.geronimo.xbeans.javaee6.FullyQualifiedClassType;
import org.apache.geronimo.xbeans.javaee6.InjectionTargetType;
import org.apache.geronimo.xbeans.javaee6.JndiNameType;
import org.apache.geronimo.xbeans.javaee6.ResAuthType;
import org.apache.geronimo.xbeans.javaee6.ResSharingScopeType;
import org.apache.geronimo.xbeans.javaee6.ResourceRefType;
import org.apache.geronimo.xbeans.javaee6.XsdStringType;
import org.apache.geronimo.deployment.service.EnvironmentBuilder;
import org.apache.xmlbeans.QNameSet;
import org.apache.xmlbeans.XmlObject;
import org.omg.CORBA.ORB;
import org.osgi.framework.Bundle;

/**
* @version $Rev: 933722 $ $Date: 2010-04-13 14:02:09 -0400 (Tue, 13 Apr 2010) $
*/
public class ResourceRefBuilder extends AbstractNamingBuilder implements ResourceEnvironmentSetter {

    private static final Logger log = LoggerFactory.getLogger(ResourceRefBuilder.class);

    private static final QName GER_RESOURCE_REF_QNAME = GerResourceRefDocument.type.getDocumentElementName();
    private static final QNameSet GER_RESOURCE_REF_QNAME_SET = QNameSet.singleton(GER_RESOURCE_REF_QNAME);
    private static final String JAXR_CONNECTION_FACTORY_CLASS = "javax.xml.registry.ConnectionFactory";
    private static final String JAVAX_MAIL_SESSION_CLASS = "javax.mail.Session";

    private final QNameSet resourceRefQNameSet;
    private final Environment corbaEnvironment;
    private final SingleElementCollection corbaGBeanNameSourceCollection;

    public ResourceRefBuilder(Environment defaultEnvironment, Environment corbaEnvironment, String[] eeNamespaces, Collection corbaGBeanNameSourceCollection) {
        super(defaultEnvironment);

        resourceRefQNameSet = buildQNameSet(eeNamespaces, "resource-ref");
        this.corbaEnvironment = corbaEnvironment;
        this.corbaGBeanNameSourceCollection = new SingleElementCollection(corbaGBeanNameSourceCollection);
    }

    protected boolean willMergeEnvironment(XmlObject specDD, XmlObject plan) {
        return specDD.selectChildren(resourceRefQNameSet).length > 0;
    }

    public void buildNaming(XmlObject specDD, XmlObject plan, Module module, Map componentContext) throws DeploymentException {

        // Discover and process any @Resource annotations (if !metadata-complete)
        if ((module != null) && (module.getClassFinder() != null)) {

            // Process all the annotations for this naming builder type
            try {
                ResourceAnnotationHelper.processAnnotations(module.getAnnotatedApp(), module.getClassFinder(), ResourceRefProcessor.INSTANCE);
            }
            catch (Exception e) {
                log.warn("Unable to process @Resource annotations for module" + module.getName(), e);
            }
        }

        List<ResourceRefType> resourceRefsUntyped = convert(specDD.selectChildren(resourceRefQNameSet), J2EE_CONVERTER, ResourceRefType.class, ResourceRefType.type);
        XmlObject[] gerResourceRefsUntyped = plan == null ? NO_REFS : plan.selectChildren(GER_RESOURCE_REF_QNAME_SET);
        Map<String, GerResourceRefType> refMap = mapResourceRefs(gerResourceRefsUntyped);
        List<String> unresolvedRefs = new ArrayList<String>();       
        for (ResourceRefType resourceRef : resourceRefsUntyped) {
            String name = getStringValue(resourceRef.getResRefName());           
            if (lookupJndiContextMap(componentContext, name) != null) {
                // some other builder handled this entry already
                continue;
            }           
            addInjections(name, resourceRef.getInjectionTargetArray(), componentContext);
            String type = getStringValue(resourceRef.getResType());
            GerResourceRefType gerResourceRef = refMap.get(name);
            log.debug("trying to resolve " + name + ", type " + type + ", resourceRef " + gerResourceRef);
           
            Object value = null;
            if (gerResourceRef == null) {
                String lookupName = getStringValue(resourceRef.getLookupName());
                if (lookupName != null) {
                    if (lookupName.equals(getJndiName(name))) {
                        throw new DeploymentException("resource-ref lookup name refers to itself");
                    }
                    value = new JndiReference(lookupName);
                }
            }
           
            if (value == null) {
                value = buildReference(module, name, type, gerResourceRef);
            }
           
            if (value == null) {
                unresolvedRefs.add(name);
            } else {
                put(name, value, getJndiContextMap(componentContext));
            }
           
        }

        if (unresolvedRefs.size() > 0) {
            log.warn("Failed to build reference to resource reference " + unresolvedRefs + " defined in plan file. The corresponding entry in Geronimo deployment descriptor is missing.");
        }
    }

    private Object buildReference(Module module, String name, String type, GerResourceRefType gerResourceRef)
        throws DeploymentException {
        Bundle bundle = module.getEarContext().getDeploymentBundle();
       
        Class iface;
        try {
            iface = bundle.loadClass(type);
        } catch (ClassNotFoundException e) {
            throw new DeploymentException("Could not resource-ref entry class " + type, e);
        }
       
        if (iface == URL.class) {
            if (gerResourceRef == null || !gerResourceRef.isSetUrl()) {
                throw new DeploymentException("No url supplied to resolve: " + name);
            }
            String url = gerResourceRef.getUrl().trim();
            //TODO expose jsr-77 objects for these guys
            try {
                //check for malformed URL
                new URL(url);
            } catch (MalformedURLException e) {
                throw new DeploymentException("Could not convert " + url + " to URL", e);
            }
            return new URLReference(url);
        } else if (ORB.class.isAssignableFrom(iface)) {
            CorbaGBeanNameSource corbaGBeanNameSource = (CorbaGBeanNameSource) corbaGBeanNameSourceCollection.getElement();
            if (corbaGBeanNameSource == null) {
                throw new DeploymentException("No orb setup but there is a orb reference");
            }
            AbstractNameQuery corbaName = corbaGBeanNameSource.getCorbaGBeanName();
            if (corbaName != null) {
                Artifact[] moduleId = module.getConfigId();
                EnvironmentBuilder.mergeEnvironments(module.getEnvironment(), corbaEnvironment);
                return new ORBReference(moduleId, corbaName);
            }
        } else {
            //determine jsr-77 type from interface
            String j2eeType;

            if (JAVAX_MAIL_SESSION_CLASS.equals(type)) {
                j2eeType = NameFactory.JAVA_MAIL_RESOURCE;
            } else if (JAXR_CONNECTION_FACTORY_CLASS.equals(type)) {
                j2eeType = NameFactory.JAXR_CONNECTION_FACTORY;
            } else {
                j2eeType = NameFactory.JCA_CONNECTION_FACTORY;
            }
            try {
                AbstractNameQuery containerId = getResourceContainerId(name, j2eeType, null, gerResourceRef);

                module.getEarContext().findGBean(containerId);

                return new ResourceReferenceFactory<ResourceException>(module.getConfigId(), containerId, iface);
            } catch (GBeanNotFoundException e) {
                StringBuffer errorMessage = new StringBuffer("Unable to resolve resource reference '");
                errorMessage.append(name);
                errorMessage.append("' (");
                if (e.hasMatches()) {
                    errorMessage.append("Found multiple matching resources.  Try being more specific in a resource-ref mapping in your Geronimo deployment plan.\n");
                    for (AbstractName match : e.getMatches()) {
                        errorMessage.append(match).append("\n");
                    }
                } else if (gerResourceRef == null) {
                    errorMessage.append("Could not auto-map to resource.  Try adding a resource-ref mapping to your Geronimo deployment plan.");
                } else if (gerResourceRef.isSetResourceLink()) {
                    errorMessage.append("Could not find resource '");
                    errorMessage.append(gerResourceRef.getResourceLink());
                    errorMessage.append("'.  Perhaps it has not yet been configured, or your application does not have a dependency declared for that resource module?");
                } else {
                    errorMessage.append("Could not find the resource specified in your Geronimo deployment plan:");
                    errorMessage.append(gerResourceRef.getPattern());
                }
                errorMessage.append("\nSearch conducted in current module and dependencies:\n");
                for (Dependency dependency : module.getEnvironment().getDependencies()) {
                    errorMessage.append(dependency).append("\n");
                }
                errorMessage.append(")");

                throw new DeploymentException(errorMessage.toString());
            }
        }
       
        return null;
    }
   
    public void setResourceEnvironment(ResourceEnvironmentBuilder builder, XmlObject[] resourceRefs, GerResourceRefType[] gerResourceRefs) throws DeploymentException {
        List<ResourceRefType> resourceRefList = convert(resourceRefs, J2EE_CONVERTER, ResourceRefType.class, ResourceRefType.type);
        Map refMap = mapResourceRefs(gerResourceRefs);
        Set unshareableResources = new HashSet();
        Set applicationManagedSecurityResources = new HashSet();
        for (ResourceRefType resourceRefType : resourceRefList) {

            String type = resourceRefType.getResType().getStringValue().trim();

            if (!URL.class.getName().equals(type)
                    && !"javax.mail.Session".equals(type)
                    && !JAXR_CONNECTION_FACTORY_CLASS.equals(type)) {

                GerResourceRefType gerResourceRef = (GerResourceRefType) refMap.get(resourceRefType.getResRefName().getStringValue());
                AbstractNameQuery containerId = getResourceContainerId(getStringValue(resourceRefType.getResRefName()), NameFactory.JCA_MANAGED_CONNECTION_FACTORY, null, gerResourceRef);

                if ("Unshareable".equals(getStringValue(resourceRefType.getResSharingScope()))) {
                    unshareableResources.add(containerId);
                }
                if ("Application".equals(getStringValue(resourceRefType.getResAuth()))) {
                    applicationManagedSecurityResources.add(containerId);
                }
            }
        }
        builder.setUnshareableResources(unshareableResources);
        builder.setApplicationManagedSecurityResources(applicationManagedSecurityResources);
    }

    private Map<String, GerResourceRefType> mapResourceRefs(XmlObject[] refs) {
        Map<String, GerResourceRefType> refMap = new HashMap<String, GerResourceRefType>();
        if (refs != null) {
            for (XmlObject ref1 : refs) {
                GerResourceRefType ref = (GerResourceRefType) ref1.copy().changeType(GerResourceRefType.type);
                refMap.put(ref.getRefName().trim(), ref);
            }
        }
        return refMap;
    }

    private AbstractNameQuery getResourceContainerId(String name, String type, URI moduleURI, GerResourceRefType gerResourceRef) {
        AbstractNameQuery containerId;
        String module = moduleURI == null ? null : moduleURI.toString();
        if (gerResourceRef == null) {
            containerId = buildAbstractNameQuery(null, module, name, type, NameFactory.RESOURCE_ADAPTER_MODULE);
        } else if (gerResourceRef.isSetResourceLink()) {
            containerId = buildAbstractNameQuery(null, module, gerResourceRef.getResourceLink().trim(), type, NameFactory.RESOURCE_ADAPTER_MODULE);
        } else {
            //construct name from components
            GerPatternType patternType = gerResourceRef.getPattern();
            containerId = buildAbstractNameQuery(patternType, type, NameFactory.RESOURCE_ADAPTER_MODULE, null);
        }
        return containerId;
    }


    public QNameSet getSpecQNameSet() {
        return resourceRefQNameSet;
    }

    public QNameSet getPlanQNameSet() {
        return GER_RESOURCE_REF_QNAME_SET;
    }

    public static class ResourceRefProcessor extends ResourceAnnotationHelper.ResourceProcessor {

        public static final ResourceRefProcessor INSTANCE = new ResourceRefProcessor();

        private ResourceRefProcessor() {
        }

        public boolean processResource(AnnotatedApp annotatedApp, Resource annotation, Class cls, Method method, Field field) {
            log.debug("processResource( [annotatedApp] " + annotatedApp.toString() + "," + '\n' +
                    "[annotation] " + annotation.toString() + "," + '\n' +
                    "[cls] " + (cls != null ? cls.getName() : null) + "," + '\n' +
                    "[method] " + (method != null ? method.getName() : null) + "," + '\n' +
                    "[field] " + (field != null ? field.getName() : null) + " ): Entry");

            String resourceName = getResourceName(annotation, method, field);
            String resourceType = getResourceType(annotation, method, field);

            if (resourceType.equals("javax.sql.DataSource") ||
                    resourceType.equals("javax.mail.Session") ||
                    resourceType.equals("java.net.URL") ||
                    resourceType.equals("org.omg.CORBA.ORB") ||
                    resourceType.equals("org.omg.CORBA_2_3.ORB") ||
                    resourceType.equals("org.omg.CORBA_2_4.ORB") ||
                    resourceType.endsWith("ConnectionFactory")) {

                log.debug("processResource(): <resource-ref> found");

                boolean exists = false;
                ResourceRefType[] resourceRefs = annotatedApp.getResourceRefArray();
                for (ResourceRefType resourceRef : resourceRefs) {
                    if (resourceRef.getResRefName().getStringValue().trim().equals(resourceName)) {
                        if (method != null || field != null) {
                            InjectionTargetType[] targets = resourceRef.getInjectionTargetArray();
                            if (!hasTarget(method, field, targets)) {
                                configureInjectionTarget(resourceRef.addNewInjectionTarget(), method, field);
                            }
                        }
                        exists = true;
                        break;
                    }
                }
                if (!exists) {
                    try {

                        log.debug("processResource(): Does not exist in DD: " + resourceName);

                        // Doesn't exist in deployment descriptor -- add new
                        ResourceRefType resourceRef = annotatedApp.addNewResourceRef();

                        //------------------------------------------------------------------------------
                        // <resource-ref> required elements:
                        //------------------------------------------------------------------------------

                        // resource-ref-name
                        JndiNameType resourceRefName = resourceRef.addNewResRefName();
                        resourceRefName.setStringValue(resourceName);

                        if (!resourceType.equals("")) {
                            // resource-ref-type
                            FullyQualifiedClassType qualifiedClass = resourceRef.addNewResType();
                            qualifiedClass.setStringValue(resourceType);
                        }
                        if (method != null || field != null) {
                            // injectionTarget
                            InjectionTargetType injectionTarget = resourceRef.addNewInjectionTarget();
                            configureInjectionTarget(injectionTarget, method, field);
                        }

                        //------------------------------------------------------------------------------
                        // <resource-ref> optional elements:
                        //------------------------------------------------------------------------------

                        // description
                        String descriptionAnnotation = annotation.description();
                        if (!descriptionAnnotation.equals("")) {
                            DescriptionType description = resourceRef.addNewDescription();
                            description.setStringValue(descriptionAnnotation);
                        }

                        // authentication
                        if (annotation.authenticationType() == Resource.AuthenticationType.CONTAINER) {
                            ResAuthType resAuth = resourceRef.addNewResAuth();
                            resAuth.setStringValue("Container");
                        } else if (annotation.authenticationType() == Resource.AuthenticationType.APPLICATION) {
                            ResAuthType resAuth = resourceRef.addNewResAuth();
                            resAuth.setStringValue("Application");
                        }

                        // sharing scope
                        ResSharingScopeType resScope = resourceRef.addNewResSharingScope();
                        resScope.setStringValue(annotation.shareable() ? "Shareable" : "Unshareable");

                        // mappedName
                        String mappdedNameAnnotation = annotation.mappedName();
                        if (!mappdedNameAnnotation.equals("")) {
                            XsdStringType mappedName = resourceRef.addNewMappedName();
                            mappedName.setStringValue(mappdedNameAnnotation);
                        }

                        // lookup
                        String lookup = annotation.lookup();
                        if (!lookup.equals("")) {
                            XsdStringType lookupName = resourceRef.addNewLookupName();
                            lookupName.setStringValue(lookup);
                        }
                    }
                    catch (Exception anyException) {
                        log.debug("ResourceRefBuilder: Exception caught while processing <resource-ref>");
                    }
                }
                return true;
            }
            return false;
        }
    }


    public static final GBeanInfo GBEAN_INFO;

    static {
        GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(ResourceRefBuilder.class, NameFactory.MODULE_BUILDER);
        infoBuilder.addAttribute("eeNamespaces", String[].class, true, true);
        infoBuilder.addAttribute("defaultEnvironment", Environment.class, true, true);
        infoBuilder.addAttribute("corbaEnvironment", Environment.class, true, true);
        infoBuilder.addReference("CorbaGBeanNameSource", CorbaGBeanNameSource.class);

        infoBuilder.setConstructor(new String[]{"defaultEnvironment", "corbaEnvironment", "eeNamespaces", "CorbaGBeanNameSource"});

        GBEAN_INFO = infoBuilder.getBeanInfo();
    }

    public static GBeanInfo getGBeanInfo() {
        return GBEAN_INFO;
    }
}
TOP

Related Classes of org.apache.geronimo.connector.deployment.ResourceRefBuilder

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.