com.sun.enterprise.deployment.util.ComponentValidator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of payara-micro Show documentation
Show all versions of payara-micro Show documentation
Micro Distribution of the Payara Project
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2014 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.
*/
// Portions Copyright [2019-2020] [Payara Foundation and/or its affiliates]
/*
* 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 final 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 msgDestReferencer 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, DOLUtils.INVALID_DESC_MAPPING,
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 ejbs;
// Only set when there is one ejb in the set.
// Otherwise, value = NONE
EjbIntfType intfType;
}
@Override
protected void accept(EjbReference ejbRef) {
DOLUtils.getDefaultLogger().log(Level.FINE, "Visiting Ref{0}", 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().log(Level.FINE, "Ref {0} is bound to Ejb with JNDI Name {1}", new Object[]{ejbRef.getName(), 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 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().log(Level.SEVERE, "Cannot resolve reference {0}", 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().log(Level.FINE, "Applying default to ejb reference: {0}", 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().log(Level.WARNING, "Unresolved : {0}", 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().log(Level.SEVERE, "Unresolved : {0}", linkName);
throw new RuntimeException("Error: Unresolved : "+linkName);
}
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().log(Level.FINE, "Unresolved : {0}", linkName);
} else {
DOLUtils.getDefaultLogger().log(Level.WARNING, "Unresolved : {0}", linkName);
}
return;
}
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 != 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)) {
if (getEjbDescriptor() != null){
DOLUtils.getDefaultLogger().log(Level.FINE, "Done Visiting {0} reference {1}", new Object[]{getEjbDescriptor().getName(), ejbRef});
}
}
// check that declared types are compatible with expected values
// if there is a target ejb descriptor available
if( ejbRef.isEJB30ClientView() ) {
Set 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(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, DOLUtils.INVALID_DESC_MAPPING,
new Object[] {ejbRef.getName() , type});
ejbRef.setType(ejbRef.getType());
}
}
protected Collection extends EjbDescriptor> getEjbDescriptors() {
if (getApplication() != null) {
return getApplication().getEjbDescriptors();
} else if (getEjbBundleDescriptor()!=null) {
return getEjbBundleDescriptor().getEjbs();
} else {
return new HashSet<>();
}
}
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 getEjbIntfMap() {
Map intfInfoMap = new HashMap<>();
for (EjbDescriptor next : getEjbDescriptors()) {
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 intfInfoMap, String intf, EjbIntfType intfType, EjbDescriptor ejbDesc) {
EjbIntfInfo intfInfo = intfInfoMap.get(intf);
if( intfInfo == null ) {
EjbIntfInfo newInfo = new EjbIntfInfo();
newInfo.ejbs = new HashSet<>();
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 serviceRef 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, DOLUtils.INVALID_DESC_MAPPING,
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 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);
}
/**
* Sets the JNDI name to default if not already set
* @param msgDestRef
*/
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().log(Level.FINE, "Injection class {0} not found for {1}", new Object[]{targetClassName, 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 pset = fs.getPrincipals();
Principal prin = null;
if (pset.size() > 0) {
prin = 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 getManagedBeanMap() {
BundleDescriptor thisBundle = getBundleDescriptor();
Set managedBeans = new HashSet<>();
// 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 managedBeanMap = new HashMap<>();
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("jakarta.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(
"jakarta.transaction.UserTransaction")) {
resourceEnvRef.setJndiName("java:comp/UserTransaction");
}
else if (resourceEnvRef.getRefType() != null && resourceEnvRef.getRefType().equals("jakarta.transaction.TransactionSynchronizationRegistry")) {
resourceEnvRef.setJndiName(
"java:comp/TransactionSynchronizationRegistry");
}
else if (resourceEnvRef.getJndiName() == null ||
resourceEnvRef.getJndiName().length() == 0) {
if (resourceEnvRef.getRefType() != null) {
if (resourceEnvRef.getRefType().equals("jakarta.enterprise.concurrent.ManagedExecutorService")) {
resourceEnvRef.setLookupName("java:comp/DefaultManagedExecutorService");
} else if (resourceEnvRef.getRefType().equals("jakarta.enterprise.concurrent.ManagedScheduledExecutorService")) {
resourceEnvRef.setLookupName("java:comp/DefaultManagedScheduledExecutorService");
} else if (resourceEnvRef.getRefType().equals("jakarta.enterprise.concurrent.ManagedThreadFactory")) {
resourceEnvRef.setLookupName("java:comp/DefaultManagedThreadFactory");
} else if (resourceEnvRef.getRefType().equals("jakarta.enterprise.concurrent.ContextService")) {
resourceEnvRef.setLookupName("java:comp/DefaultContextService");
} else {
resourceEnvRef.setJndiName(getDefaultResourceJndiName(resourceEnvRef.getName()));
}
} else {
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;
}
}