Package com.sun.enterprise.deployment.util

Source Code of com.sun.enterprise.deployment.util.ComponentValidator$EjbIntfInfo

/*
* 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.
*/

/*
* ComponentValidator.java
*
* Created on August 15, 2002, 5:51 PM
*/

package com.sun.enterprise.deployment.util;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.Principal;
import java.security.PrivilegedAction;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.LogRecord;
import javax.security.auth.Subject;

import com.sun.enterprise.deployment.Application;
import com.sun.enterprise.deployment.BundleDescriptor;
import com.sun.enterprise.deployment.EjbBundleDescriptor;
import com.sun.enterprise.deployment.EjbDescriptor;
import com.sun.enterprise.deployment.InjectionCapable;
import com.sun.enterprise.deployment.InjectionTarget;
import com.sun.enterprise.deployment.ManagedBeanDescriptor;
import com.sun.enterprise.deployment.MessageDestinationDescriptor;
import com.sun.enterprise.deployment.MessageDestinationReferenceDescriptor;
import com.sun.enterprise.deployment.ResourceEnvReferenceDescriptor;
import com.sun.enterprise.deployment.ResourceReferenceDescriptor;
import com.sun.enterprise.deployment.RunAsIdentityDescriptor;
import com.sun.enterprise.deployment.ServiceRefPortInfo;
import com.sun.enterprise.deployment.ServiceReferenceDescriptor;
import com.sun.enterprise.deployment.WebServiceEndpoint;
import com.sun.enterprise.deployment.types.EjbReference;
import com.sun.enterprise.deployment.types.MessageDestinationReferencer;
import com.sun.enterprise.util.LocalStringManagerImpl;
import org.glassfish.api.deployment.archive.ArchiveType;

import org.glassfish.logging.annotation.LogMessageInfo;

/**
*
* @author  dochez
*/
public class ComponentValidator extends DefaultDOLVisitor implements ComponentVisitor {

    public static final Logger deplLogger = com.sun.enterprise.deployment.util.DOLUtils.deplLogger;

    @LogMessageInfo(message = "Could not load {0}", level="FINE")
    private static final String LOAD_ERROR = "AS-DEPLOYMENT-00014";

    private static LocalStringManagerImpl localStrings =
            new LocalStringManagerImpl(ComponentValidator.class);

    protected BundleDescriptor bundleDescriptor = null;

    protected Application application;

    /**
     * @return the Application object if any
     */
    protected Application getApplication() {
        return application;
    }

    /**
     * @return the bundleDescriptor we are visiting
     */
    protected BundleDescriptor getBundleDescriptor() {
        return bundleDescriptor;
    }

    @Override
    public void accept(BundleDescriptor bundleDescriptor) {
        this.bundleDescriptor = bundleDescriptor;

        super.accept(bundleDescriptor);
    }

    /**
     * Visits a message destination referencer for the last J2EE
     * component visited
     * @param the message destination referencer
     */
    @Override
    protected void accept(MessageDestinationReferencer msgDestReferencer) {

        // if it is linked to a logical destination
        if( msgDestReferencer.isLinkedToMessageDestination() ) {
            return;
        // if it is referred to a physical destination
        } else if (msgDestReferencer.ownedByMessageDestinationRef() &&
            msgDestReferencer.getMessageDestinationRefOwner(
            ).getJndiName() != null) {
            return;
        } else {
            MessageDestinationDescriptor msgDest =
                msgDestReferencer.resolveLinkName();
            if( msgDest == null ) {
                String linkName =
                    msgDestReferencer.getMessageDestinationLinkName();
                DOLUtils.getDefaultLogger().log(Level.WARNING, "enterprise.deployment.backend.invalidDescriptorMappingFailure",
                    new Object[] {"message-destination", linkName});
            } else {
                if (msgDestReferencer instanceof MessageDestinationReferenceDescriptor) {
                    ((MessageDestinationReferenceDescriptor)msgDestReferencer).setJndiName(msgDest.getJndiName());
                }
            }                                                
        }
    }

    /**
     * @param intfName
     * @return default jndi name for a given interface name
     */
    //XXX this is first implementation. It does not handle two ejb with same
    //    interface in different jar
    protected String getDefaultEjbJndiName(String intfName) {
        return intfName;
    }

    private enum EjbIntfType {
        NONE,
        REMOTE_HOME,
        REMOTE_BUSINESS,
        LOCAL_HOME,
        LOCAL_BUSINESS,
        NO_INTF_LOCAL_BUSINESS
    }

    private static class EjbIntfInfo {

        Set<EjbDescriptor> ejbs;

        // Only set when there is one ejb in the set.
        // Otherwise, value = NONE
        EjbIntfType intfType;
    }


    @Override
    protected void accept(EjbReference ejbRef) {

        DOLUtils.getDefaultLogger().fine("Visiting Ref" + ejbRef);
    if (ejbRef.getEjbDescriptor()!=null)
            return;

        // let's try to derive the ejb-ref-type first it is not defined
        if (ejbRef.getType() == null) {
            // if it's EJB30 (no home/local home), it must be session
            if (ejbRef.isEJB30ClientView()) {
                ejbRef.setType("Session");
            } else {
                // if home interface has findByPrimaryKey method,
                // it's entity, otherwise it's session
                String homeIntf = ejbRef.getEjbHomeInterface();
                BundleDescriptor referringJar = ejbRef.getReferringBundleDescriptor();
                if (referringJar == null) {
                    referringJar = getBundleDescriptor();
                }          
                ClassLoader classLoader = referringJar.getClassLoader();

                Class<?> clazz = null;
                try {
                    clazz = classLoader.loadClass(homeIntf);
                    for (Method method : clazz.getDeclaredMethods()) {
                        if (method.getName().equals("findByPrimaryKey")) {
                            ejbRef.setType("Entity");
                            break;
                        }
                    }
                    if (ejbRef.getType() == null) {
                        ejbRef.setType("Session");
                    }
                } catch(Exception e) {
                  LogRecord lr = new LogRecord(Level.FINE, LOAD_ERROR);
                  Object args[] = { homeIntf };
                  lr.setParameters(args);
                  lr.setThrown(e);
                  deplLogger.log(lr);
                }
            }
        }
 
        //
        // NOTE : In the 3.0 local/remote business view, the local vs.
        // remote designation is not always detectable from the interface
        // itself.
        //
        // That means
        //
        // 1) we need to figure it out during this stage of the processing
        // 2) the EjbReferenceDescriptor.isLocal() operations shouldn't be
        //    be used before the post-application validation stage since its
        //    value would be unreliable.
        // 3) We can't write out the standard deployment descriptors to XML
        //    until the full application has been processed, including this
        //    validation stage.
        //
        // During @EJB processing, setLocal() is set to false if
        // local vs. remote is ambiguous.  setLocal() is set to true within this
        // method upon successfuly resolution to a local business interface.
        //

        if (ejbRef.getJndiName()!=null && ejbRef.getJndiName().length()!=0) {


            // ok this is getting a little complicated here
            // the jndi name is not null, if this is a remote ref, proceed with resolution
            // if this is a local ref, proceed with resolution only if ejb-link is null           
            if (!ejbRef.isLocal() || (ejbRef.isLocal() && ejbRef.getLinkName()==null)) {
                DOLUtils.getDefaultLogger().fine("Ref " + ejbRef.getName() + " is bound to Ejb with JNDI Name " + ejbRef.getJndiName());
                if (getEjbDescriptors() != null) {
                    for (Iterator iter = getEjbDescriptors().iterator(); iter.hasNext(); ) {
                        EjbDescriptor ejb = (EjbDescriptor) iter.next();
                        if (ejbRef.getJndiName().equals(ejb.getJndiName())) {
                            ejbRef.setEjbDescriptor(ejb);
                            return;
                        }
                    }
                }
            }
        }

        // If the reference does not have an ejb-link or jndi-name or lookup string associated
        // with it, attempt to resolve it by checking against all the ejbs
        // within the application.  If no match is found, just fall through
        // and let the existing error-checking logic kick in.
        if (( (ejbRef.getJndiName() == null) ||
              (ejbRef.getJndiName().length() == 0) )
            &&
            ( (ejbRef.getLinkName() == null) ||
              (ejbRef.getLinkName().length() == 0) )
            && !ejbRef.hasLookupName() ) {

            Map<String, EjbIntfInfo> ejbIntfInfoMap = getEjbIntfMap();
            if ( ejbIntfInfoMap.size() > 0 ) {

                String interfaceToMatch = ejbRef.isEJB30ClientView() ?
                    ejbRef.getEjbInterface() : ejbRef.getEjbHomeInterface();
                if ( interfaceToMatch == null ) {
                  String msg = localStrings.getLocalString(
                          "enterprise.deployment.util.no_remoteinterface",
                          "Cannot resolve reference {0} because it does not declare a remote interface or " +
                                  "remote home interface of target bean",
                          new Object[]{ejbRef});
                  throw new IllegalArgumentException(msg);
                }
                EjbIntfInfo intfInfo = ejbIntfInfoMap.get(interfaceToMatch);

                // make sure exactly one match
                if ( intfInfo != null ) {
                    int numMatches = intfInfo.ejbs.size();
                    if( numMatches == 1 ) {
                        EjbDescriptor target = intfInfo.ejbs.iterator().next();

                        BundleDescriptor targetModule =
                            target.getEjbBundleDescriptor();
                        BundleDescriptor sourceModule =
                            ejbRef.getReferringBundleDescriptor();

                        Application app = targetModule.getApplication();

                        //
                        // It's much cleaner to derive the ejb-link value
                        // and set that instead of the descriptor.  This way,
                        // if there are multiple ejb-jars within the .ear that
                        // each have an ejb with the target bean's ejb-name,
                        // there won't be any ambiguity about which one is
                        // the correct target.  It's not so much a problem
                        // during this phase of the processing, but if the
                        // fully-qualified ejb-link name is required and is not
                        // written out, there could be non-deterministic
                        // behavior when the application is re-loaded.
                        // Let the ejb-link processing logic handle the
                        // conversion to ejb descriptor.
                        //

                        // If the ejb reference and the target ejb are defined
                        // within the same ejb-jar, the ejb-link will only
                        // be set to ejb-name.  This is done regardless of
                        // whether the ejb-jar is within an .ear or is
                        // stand-alone.  The ejb-link processing
                        // logic will always check the current ejb-jar
                        // first so there won't be any ambiguity. 
                        String ejbLinkName = target.getName();
                        if (!sourceModule.isPackagedAsSingleModule(targetModule)) {
                            String relativeUri = null;
                            if( sourceModule == app ) {
                                // Now that dependencies can be defined within application.xml
                                // it's possible for source module to be the Application object.
                                // In this case, just use the target module uri as the relative
                                // uri.
                                relativeUri = targetModule.getModuleDescriptor().getArchiveUri();
                            } else {
                                // Since there are at least two modules, we
                                // must be within an application.
                                relativeUri = getApplication().getRelativeUri(sourceModule, targetModule);
                            }
                            ejbLinkName = relativeUri + "#" + ejbLinkName;
                        }

                        ejbRef.setLinkName(ejbLinkName);

                    } else {
                        String msg = localStrings.getLocalString(
                                "enterprise.deployment.util.multiple_ejbs_with_interface",
                                "Cannot resolve reference {0} because there are {1} ejbs in the application with interface {2}.",
                                new Object[] {ejbRef, numMatches, interfaceToMatch});
                        throw new IllegalArgumentException(msg);
                    }
                }                         
            }
        }

        // now all cases fall back here, we need to resolve through the link-name   
        if (ejbRef.getLinkName()==null) {


            // if no link name if present, and this is a local ref, this is an
            // error (unless there is a lookup string) because we must resolve all
            // local refs within the app and we cannot resolve it
            if (ejbRef.isLocal()) {
                if( ejbRef.hasLookupName() ) {
                    return;
                }
                DOLUtils.getDefaultLogger().severe("Cannot resolve reference " + ejbRef);
                throw new RuntimeException("Cannot resolve reference " + ejbRef);
            } else {
                // this is a remote interface, jndi will eventually contain the referenced
                // ejb ref, apply default jndi name if there is none
                if (!ejbRef.hasJndiName() && !ejbRef.hasLookupName()) {
                    String jndiName = getDefaultEjbJndiName(
                        ejbRef.isEJB30ClientView() ?
                        ejbRef.getEjbInterface() : ejbRef.getEjbHomeInterface());
                    ejbRef.setJndiName(jndiName);
                    DOLUtils.getDefaultLogger().fine("Applying default to ejb reference: " + ejbRef);
                }

                return;
            }                         
        }       
       
        // Beginning of ejb-link resolution
       
        // save anticipated types for checking if interfaces are compatible
        String homeClassName = ejbRef.getEjbHomeInterface();
        String intfClassName = ejbRef.getEjbInterface();

        // save anticipated type for checking if bean type is compatible
        String type = ejbRef.getType();
       
        EjbDescriptor ejbReferee=null;
           
        String linkName = ejbRef.getLinkName();
        int ind = linkName.lastIndexOf('#');
        if ( ind != -1 ) {
            // link has a relative path from referring EJB JAR,
            // of form "../products/product.jar#ProductEJB"
            String ejbName = linkName.substring(ind+1);
            String jarPath = linkName.substring(0, ind);           
            BundleDescriptor referringJar = ejbRef.getReferringBundleDescriptor();
            if (referringJar==null) {
                ejbRef.setReferringBundleDescriptor(getBundleDescriptor());
                referringJar = getBundleDescriptor();
            }          
           
            if (getApplication()!=null) {
                BundleDescriptor refereeJar = null;
                if( referringJar instanceof Application ) {
                    refereeJar = ((Application)referringJar).getModuleByUri(jarPath);
                } else {
                 refereeJar =
                    getApplication().getRelativeBundle(referringJar, jarPath);
                }
                if( (refereeJar != null) &&
                    refereeJar instanceof EjbBundleDescriptor ) {
                    // this will throw an exception if ejb is not found
                    ejbReferee =
                       ((EjbBundleDescriptor)refereeJar).getEjbByName(ejbName);
                }
            }
        }
        else {

            // Handle an unqualified ejb-link, which is just an ejb-name.

            // If we're in an application and currently processing an
            // ejb-reference defined within an ejb-jar, first check
            // the current ejb-jar for an ejb-name match.  From a spec
            // perspective, the deployer can't depend on this behavior,
            // but it's still better to have deterministic results.  In
            // addition, in the case of automatic-linking, the fully-qualified
            // "#" ejb-link syntax is not used when the ejb reference and
            // target ejb are within the same ejb-jar.  Checking the
            // ejb-jar first will ensure the correct linking behavior for
            // that case.
            Application app = getApplication();
            EjbBundleDescriptor ebd = getEjbBundleDescriptor();
            if (app != null && ebd != null && ebd.hasEjbByName(linkName)) {
                ejbReferee = ebd.getEjbByName(linkName);
            } else if (app != null && app.hasEjbByName(linkName)) {
                ejbReferee = app.getEjbByName(ejbRef.getLinkName());
            } else if (getEjbDescriptor()!=null) {
                try {
                    ejbReferee = getEjbDescriptor().getEjbBundleDescriptor().getEjbByName(ejbRef.getLinkName());
                } catch (IllegalArgumentException e) {
                    // this may happen when we have no application and the ejb ref
                    // cannot be resolved to a ejb in the bundle. The ref will
                    // probably be resolved when the application is assembled.
                    DOLUtils.getDefaultLogger().warning("Unresolved <ejb-link>: "+linkName);
                    return;
                }
                   
            }
        }

        if (ejbReferee==null) {
            // we could not resolve through the ejb-link. if this is a local ref, this
            // is an error, if this is a remote ref, this should be also an error at
            // runtime but maybe the jndi name will be specified by deployer so
            // a warning should suffice
            if (ejbRef.isLocal()) {
                DOLUtils.getDefaultLogger().severe("Unresolved <ejb-link>: "+linkName);
                throw new RuntimeException("Error: Unresolved <ejb-link>: "+linkName);
            } else {
                final ArchiveType moduleType = ejbRef.getReferringBundleDescriptor().getModuleType();
                if(moduleType != null && moduleType.equals(DOLUtils.carType())) {
                    // Because no annotation processing is done within ACC runtime, this case typically
                    // arises for remote @EJB annotations, so don't log it as warning.
                    DOLUtils.getDefaultLogger().fine("Unresolved <ejb-link>: "+linkName);
                } else {
                    DOLUtils.getDefaultLogger().warning("Unresolved <ejb-link>: "+linkName);
                }
                return;
            }
        } else {

            if( ejbRef.isEJB30ClientView() ) {

                BundleDescriptor referringBundle =
                    ejbRef.getReferringBundleDescriptor();

                // If we can verify that the current ejb 3.0 reference is defined
                // in any Application Client module or in a stand-alone web module
                // it must be remote business.
                if( ( (referringBundle == null) && (getEjbBundleDescriptor() == null) )
                    ||
                    ((referringBundle != null) && (referringBundle.getModuleType() == DOLUtils.carType()))
                    ||
                    ( (getApplication() == null) &&
                      (referringBundle.getModuleType() != null && referringBundle.getModuleType().equals(DOLUtils.warType())) ) ) {

                    ejbRef.setLocal(false);

                    // Double-check that target has a remote business interface of this
                    // type.  This will handle the common error case that the target
                    // EJB has intended to support a remote business interface but
                    // has not used @Remote to specify it, in which case
                    // the interface was assigned the default of local business.

                    if( !ejbReferee.getRemoteBusinessClassNames().contains
                        (intfClassName) ) {
                        String msg = "Target ejb " + ejbReferee.getName() + " for " +
                            " remote ejb 3.0 reference " + ejbRef.getName() +
                            " does not expose a remote business interface of type " +
                            intfClassName;
                        throw new RuntimeException(msg);
                    }

                } else if(ejbReferee.getLocalBusinessClassNames().contains(intfClassName)) {
                    ejbRef.setLocal(true);
                } else if(ejbReferee.getRemoteBusinessClassNames().contains(intfClassName)) {
                    ejbRef.setLocal(false);
                } else {
                    if (ejbReferee.isLocalBean()) {
                        ejbRef.setLocal(true);
                    } else {
                        String msg = "Warning : Unable to determine local " +
                            " business vs. remote business designation for " +
                            " EJB 3.0 ref " + ejbRef;
                        throw new RuntimeException(msg);
                    }
                }
            }

            ejbRef.setEjbDescriptor(ejbReferee);
        }

        // if we are here, we must have resolved the reference
        if(DOLUtils.getDefaultLogger().isLoggable(Level.FINE)) {
            DOLUtils.getDefaultLogger().fine("Done Visiting " + getEjbDescriptor().getName() + " reference " + ejbRef);
        }

        // check that declared types are compatible with expected values
        // if there is a target ejb descriptor available
            if( ejbRef.isEJB30ClientView() ) {

                Set<String> targetBusinessIntfs = ejbRef.isLocal() ?
                    ejbReferee.getLocalBusinessClassNames() :
                    ejbReferee.getRemoteBusinessClassNames();

                EjbDescriptor ejbDesc = ejbRef.getEjbDescriptor();

                // If it's neither a business interface nor a no-interface view
                if( !targetBusinessIntfs.contains(intfClassName) &&
                    (   ejbDesc.isLocalBean() &&
                        !(intfClassName.equals(ejbReferee.getEjbClassName()))) ) {


                    DOLUtils.getDefaultLogger().log(Level.WARNING,
                           "enterprise.deployment.backend.ejbRefTypeMismatch",
                           new Object[] {ejbRef.getName() , intfClassName,
                           ejbReferee.getName(), ( ejbRef.isLocal() ?
                           "Local Business" : "Remote Business"),
                                             targetBusinessIntfs.toString()});


                    // We can only figure out what the correct type should be
                    // if there is only 1 target remote/local business intf.
                    if( targetBusinessIntfs.size() == 1 ) {
                        Iterator iter = targetBusinessIntfs.iterator();
                        ejbRef.setEjbInterface((String)iter.next());
                    }
                }

            } else {

                String targetHome = ejbRef.isLocal() ?
                    ejbReferee.getLocalHomeClassName() :
                    ejbReferee.getHomeClassName();

                if( !homeClassName.equals(targetHome) ) {

                    DOLUtils.getDefaultLogger().log(Level.WARNING,
                       "enterprise.deployment.backend.ejbRefTypeMismatch",
                       new Object[] {ejbRef.getName() , homeClassName,
                       ejbReferee.getName(), ( ejbRef.isLocal() ?
                       "Local Home" : "Remote Home"), targetHome});

                    if( targetHome != null ) {
                        ejbRef.setEjbHomeInterface(targetHome);
                    }
                }

                String targetComponentIntf = ejbRef.isLocal() ?
                    ejbReferee.getLocalClassName() :
                    ejbReferee.getRemoteClassName();

                // In some cases for 2.x style @EJBs that point to Entity beans
                // the interface class cannot be derived, so only do the
                // check if the intf is known.
                if( (intfClassName != null) &&
                    !intfClassName.equals(targetComponentIntf) ) {

                    DOLUtils.getDefaultLogger().log(Level.WARNING,
                       "enterprise.deployment.backend.ejbRefTypeMismatch",
                       new Object[] {ejbRef.getName() , intfClassName,
                       ejbReferee.getName(), ( ejbRef.isLocal() ?
                       "Local" : "Remote"), targetComponentIntf});

                    if( targetComponentIntf != null ) {
                        ejbRef.setEjbInterface(targetComponentIntf);
                    }
                }
            }

            // set jndi name in ejb ref
            ejbRef.setJndiName(ejbReferee.getJndiName());

        if (!type.equals(ejbRef.getType())) {
            // if they don't match
            // print a warning and reset the type in ejb ref
            DOLUtils.getDefaultLogger().log(Level.WARNING, "enterprise.deployment.backend.invalidDescriptorMappingFailure",
            new Object[] {ejbRef.getName() , type});

            ejbRef.setType(ejbRef.getType());

        }
    }

    protected Collection getEjbDescriptors() {
        if (getApplication() != null) {
            return getApplication().getEjbDescriptors();
        } else if (getEjbBundleDescriptor()!=null) {
            return getEjbBundleDescriptor().getEjbs();
        } else {
            return new HashSet<EjbDescriptor>();
        }
    }

    protected EjbDescriptor getEjbDescriptor() {
        return null;
    }

    protected EjbBundleDescriptor getEjbBundleDescriptor() {
        return null;
    }

    /**
     * Returns a map of interface name -> EjbIntfInfo based on all the ejbs
     * within the application or stand-alone module.  Only RemoteHome,
     * RemoteBusiness, LocalHome, and LocalBusiness are eligible for map.
     */
    private Map<String, EjbIntfInfo> getEjbIntfMap() {
        Map<String, EjbIntfInfo> intfInfoMap = new HashMap<String, EjbIntfInfo>();

        for(Iterator iter = getEjbDescriptors().iterator(); iter.hasNext(); ) {
            EjbDescriptor next = (EjbDescriptor) iter.next();
            if( next.isRemoteInterfacesSupported() ) {
                addIntfInfo(intfInfoMap, next.getHomeClassName(),
                            EjbIntfType.REMOTE_HOME, next);
            }

            if( next.isRemoteBusinessInterfacesSupported() ) {
                for(String nextIntf : next.getRemoteBusinessClassNames()) {
                    addIntfInfo(intfInfoMap, nextIntf,
                                EjbIntfType.REMOTE_BUSINESS, next);
                }
            }

            if( next.isLocalInterfacesSupported() ) {
                addIntfInfo(intfInfoMap, next.getLocalHomeClassName(),
                            EjbIntfType.LOCAL_HOME, next);
            }

            if( next.isLocalBusinessInterfacesSupported() ) {
                for(String nextIntf : next.getLocalBusinessClassNames()) {
                    addIntfInfo(intfInfoMap, nextIntf,
                                EjbIntfType.LOCAL_BUSINESS, next);
                }
            }

            if (next.isLocalBean()) {
                addIntfInfo(intfInfoMap, next.getEjbClassName(),
                                EjbIntfType.NO_INTF_LOCAL_BUSINESS, next);
            }

        }

        return intfInfoMap;
    }

    private void addIntfInfo(Map<String, EjbIntfInfo> intfInfoMap,
                             String intf, EjbIntfType intfType,
                             EjbDescriptor ejbDesc) {

        EjbIntfInfo intfInfo = intfInfoMap.get(intf);
        if( intfInfo == null ) {
            EjbIntfInfo newInfo = new EjbIntfInfo();
            newInfo.ejbs = new HashSet<EjbDescriptor>();
            newInfo.ejbs.add(ejbDesc);
            newInfo.intfType = intfType;
            intfInfoMap.put(intf, newInfo);
        } else {
            intfInfo.ejbs.add(ejbDesc);
            // Since there's more than one match, reset intf type.
            intfInfo.intfType = EjbIntfType.NONE;
        }

    }

    /**
     * Visits a service reference for the last J2EE component visited
     *
     * @param the service reference
     */
    @Override
    protected void accept(ServiceReferenceDescriptor serviceRef) {

        Set portsInfo = serviceRef.getPortsInfo();

        for(Iterator iter = portsInfo.iterator(); iter.hasNext();) {
            ServiceRefPortInfo next = (ServiceRefPortInfo) iter.next();

            if( next.hasPortComponentLinkName() &&
                !next.isLinkedToPortComponent() ) {
                WebServiceEndpoint portComponentLink = next.resolveLinkName();
                if( portComponentLink == null ) {
                    String linkName = next.getPortComponentLinkName();
                    DOLUtils.getDefaultLogger().log(Level.WARNING, "enterprise.deployment.backend.invalidDescriptorMappingFailure",
                        new Object[] {"port-component" , linkName});
                }                                                  
            }

        }
    }   

    @Override
    protected void accept(ResourceReferenceDescriptor resRef) {
        computeRuntimeDefault(resRef);
    }

    @Override
    protected void accept(ResourceEnvReferenceDescriptor resourceEnvRef) {

        if (resourceEnvRef.getJndiName() == null ||
                resourceEnvRef.getJndiName().length() == 0) {
            Map<String, ManagedBeanDescriptor> managedBeanMap = getManagedBeanMap();
            String refType = resourceEnvRef.getRefType();
            if( managedBeanMap.containsKey(refType) ) {
                ManagedBeanDescriptor desc = managedBeanMap.get(refType);

                // In app-client, keep lookup local to JVM so it doesn't need to access
                // server's global JNDI namespace for managed bean.
                String jndiName = ( bundleDescriptor.getModuleType() == DOLUtils.carType() )
                        ?  desc.getAppJndiName() : desc.getGlobalJndiName();

                resourceEnvRef.setJndiName(jndiName);
                resourceEnvRef.setIsManagedBean(true);
                resourceEnvRef.setManagedBeanDescriptor(desc);
            }
        }

        computeRuntimeDefault(resourceEnvRef);
    }

    protected void accept(MessageDestinationReferenceDescriptor msgDestRef) {
        computeRuntimeDefault(msgDestRef);
    }

    @Override
    protected void accept(MessageDestinationDescriptor msgDest) {
        computeRuntimeDefault(msgDest);
    }

    /**
     * visits all entries within the component environment for which
     * isInjectable() == true.
     * @param injectable InjectionCapable environment dependency
     */
    protected void accept(InjectionCapable injectable) {
        acceptWithCL(injectable);
        acceptWithoutCL(injectable);
    }

    // we need to split the accept(InjectionCapable) into two parts:
    // one needs classloader and one doesn't. This is needed because
    // in the standalone war case, the classloader is not created
    // untill the web module is being started.

    protected void acceptWithCL(InjectionCapable injectable) {
        // If parsed from deployment descriptor, we need to determine whether
        // the inject target name refers to an injection field or an
        // injection method for each injection target
        for (InjectionTarget target : injectable.getInjectionTargets()) {
            if( (target.getFieldName() == null) &&
                    (target.getMethodName() == null) ) {

                String injectTargetName = target.getTargetName();
                String targetClassName  = target.getClassName();
                ClassLoader classLoader = getBundleDescriptor().getClassLoader();

                Class targetClazz = null;

                try {

                    targetClazz = classLoader.loadClass(targetClassName);

                } catch(ClassNotFoundException cnfe) {
                    // @@@
                    // Don't treat this as a fatal error for now.  One known issue
                    // is that all .xml, even web.xml, is processed within the
                    // appclient container during startup.  In that case, there
                    // are issues with finding .classes in .wars due to the
                    // structure of the returned client .jar and the way the
                    // classloader is formed.
                    DOLUtils.getDefaultLogger().fine
                            ("Injection class " + targetClassName + " not found for " +
                            injectable);
                    return;
                }

                // Spec requires that we attempt to match on method before field.
                boolean matched = false;

                // The only information we have is method name, so iterate
                // through the methods find a match.  There is no overloading
                // allowed for injection methods, so any match is considered
                // the only possible match.

                String setterMethodName = TypeUtil.
                        propertyNameToSetterMethod(injectTargetName);

                // method can have any access type so use getDeclaredMethods()
                for(Method next : targetClazz.getDeclaredMethods()) {
                    // only when the method name matches and the method
                    // has exactly one parameter, we find a match
                    if( next.getName().equals(setterMethodName) &&
                        next.getParameterTypes().length == 1) {
                        target.setMethodName(next.getName());
                        if( injectable.getInjectResourceType() == null ) {
                            Class[] paramTypes = next.getParameterTypes();
                            if (paramTypes.length == 1) {
                                String resourceType = paramTypes[0].getName();
                                injectable.setInjectResourceType(resourceType);
                            }
                        }
                        matched = true;
                        break;
                    }
                }

               if( !matched ) {

                    // In the case of injection fields, inject target name ==
                    // field name.  Field can have any access type.
                    try {
                        Field f = targetClazz.getDeclaredField(injectTargetName);
                        target.setFieldName(injectTargetName);
                        if( injectable.getInjectResourceType() == null ) {
                            String resourceType = f.getType().getName();
                            injectable.setInjectResourceType(resourceType);
                        }
                        matched = true;
                    } catch(NoSuchFieldException nsfe) {
                        String msg = "No matching injection setter method or " +
                                "injection field found for injection property " +
                                injectTargetName + " on class " + targetClassName +
                                " for component dependency " + injectable;

                        throw new RuntimeException(msg, nsfe);
                    }
                }
            }
        }
    }

    protected void acceptWithoutCL(InjectionCapable injectable) {
    }

    /**
     * Set a default RunAs principal to given RunAsIdentityDescriptor
     * if necessary.
     * @param runAs
     * @param application
     * @exception RuntimeException
     */
    protected void computeRunAsPrincipalDefault(RunAsIdentityDescriptor runAs,
            Application application) {

        // for backward compatibile
        if (runAs != null &&
                (runAs.getRoleName() == null ||
                    runAs.getRoleName().length() == 0)) {
            DOLUtils.getDefaultLogger().log(Level.WARNING,
            "enterprise.deployment.backend.emptyRoleName");
            return;
        }

        if (runAs != null &&
                (runAs.getPrincipal() == null ||
                    runAs.getPrincipal().length() == 0) &&
                application != null && application.getRoleMapper() != null) {

            String principalName = null;
            String roleName = runAs.getRoleName();

            final Subject fs = (Subject)application.getRoleMapper().getRoleToSubjectMapping().get(roleName);
            if (fs != null) {
                principalName = (String)AccessController.doPrivileged(new PrivilegedAction() {
                    @Override
                    public Object run() {
                        Set<Principal> pset = fs.getPrincipals();
                        Principal prin = null;
                        if (pset.size() > 0) {
                            prin = (Principal)pset.iterator().next();
                            DOLUtils.getDefaultLogger().log(Level.WARNING,
                            "enterprise.deployment.backend.computeRunAsPrincipal",
                            new Object[] { prin.getName() });
                        }
                        return (prin != null) ? prin.getName() : null;
                    }
                });
            }

            if (principalName == null || principalName.length() == 0) {
                throw new RuntimeException("The RunAs role " + "\"" + roleName + "\"" +
                    " is not mapped to a principal.");
            }
            runAs.setPrincipal(principalName);
        }
    }

    /**
     * Get a map of bean class to managed bean descriptor for the managed beans
     * defined within the current module.
     */
    private Map<String, ManagedBeanDescriptor> getManagedBeanMap() {
        BundleDescriptor thisBundle = getBundleDescriptor();

        Set<ManagedBeanDescriptor> managedBeans = new HashSet<ManagedBeanDescriptor>();

        // Make sure we're dealing with the top-level bundle descriptor when looking
        // for managed beans
        if( thisBundle != null ) {
            Object desc = thisBundle.getModuleDescriptor().getDescriptor();
            if( desc instanceof BundleDescriptor ) {
                managedBeans = ((BundleDescriptor)desc).getManagedBeans();
            }
        }

        Map<String, ManagedBeanDescriptor> managedBeanMap = new HashMap<String, ManagedBeanDescriptor>();

        for(ManagedBeanDescriptor managedBean : managedBeans ) {

            String beanClassName = managedBean.getBeanClassName();
            managedBeanMap.put(beanClassName, managedBean);
        }

        return managedBeanMap;

    }

    /**
     * Set runtime default value for ResourceReferenceDescriptor.
     */
    private void computeRuntimeDefault(ResourceReferenceDescriptor resRef) {
        if (resRef.getType() != null && resRef.getType().equals("org.omg.CORBA.ORB")) {
            resRef.setJndiName("java:comp/ORB");
        }

        else if (resRef.getJndiName() == null ||
                resRef.getJndiName().length() == 0) {
            if (resRef.getType() != null) {
                if (resRef.getType().equals("javax.sql.DataSource"))
                    resRef.setLookupName("java:comp/DefaultDataSource");
                else if (resRef.getType().equals("javax.jms.ConnectionFactory"))
                    resRef.setLookupName("java:comp/DefaultJMSConnectionFactory");
                else
                    resRef.setJndiName(getDefaultResourceJndiName(resRef.getName()));
            } else {
                resRef.setJndiName(getDefaultResourceJndiName(resRef.getName()));
            }
        }
    }

    /**
     * Set runtime default value for ResourceEnvReferenceDescriptor.
     */
    private void computeRuntimeDefault(ResourceEnvReferenceDescriptor resourceEnvRef) {
        if (resourceEnvRef.getRefType() != null && resourceEnvRef.getRefType().equals(
            "javax.transaction.UserTransaction")) {
            resourceEnvRef.setJndiName("java:comp/UserTransaction");
        }

        else if (resourceEnvRef.getRefType() != null && resourceEnvRef.getRefType().equals("javax.transaction.TransactionSynchronizationRegistry")) {
            resourceEnvRef.setJndiName(
                "java:comp/TransactionSynchronizationRegistry");
        }

        else if (resourceEnvRef.getJndiName() == null ||
                resourceEnvRef.getJndiName().length() == 0) {
            resourceEnvRef.setJndiName(getDefaultResourceJndiName(resourceEnvRef.getName()));
        }
    }

    /**
     * Set runtime default value for MessageDestinationReferenceDescriptor.
     */
    private void computeRuntimeDefault(MessageDestinationReferenceDescriptor msgDestRef) {
        if (msgDestRef.getJndiName() == null ||
                msgDestRef.getJndiName().length() == 0) {
            msgDestRef.setJndiName(getDefaultResourceJndiName(msgDestRef.getName()));
        }
    }

    /**
     * Set runtime default value for MessageDestinationDescriptor.
     */
    private void computeRuntimeDefault(MessageDestinationDescriptor msgDest) {
        if (msgDest.getJndiName() == null ||
                msgDest.getJndiName().length() == 0) {
            msgDest.setJndiName(getDefaultResourceJndiName(msgDest.getName()));
        }
    }

    /**
     * @param resName
     * @return default jndi name for a given interface resource name
     */
    private String getDefaultResourceJndiName(String resName) {
        return resName;
    }

}
TOP

Related Classes of com.sun.enterprise.deployment.util.ComponentValidator$EjbIntfInfo

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.