From 5c347809aa1b750aeddbb2a2c0bf0adb7bfe22b9 Mon Sep 17 00:00:00 2001 From: Thomas Bitonti Date: Thu, 14 Nov 2019 11:55:00 -0500 Subject: [PATCH 1/3] Wire anno caching into JAXWS 23; augment tracing. --- .../web/WebJaxWsModuleInfoBuilder.java | 161 ++++++++++++------ .../jaxws/web/WebJaxWsModuleInfoBuilder.java | 130 ++++++++++---- 2 files changed, 201 insertions(+), 90 deletions(-) diff --git a/dev/com.ibm.ws.jaxws.2.3.web/src/com/ibm/ws/jaxws23/web/WebJaxWsModuleInfoBuilder.java b/dev/com.ibm.ws.jaxws.2.3.web/src/com/ibm/ws/jaxws23/web/WebJaxWsModuleInfoBuilder.java index e6b4a8b6abe1..33203f1511ad 100644 --- a/dev/com.ibm.ws.jaxws.2.3.web/src/com/ibm/ws/jaxws23/web/WebJaxWsModuleInfoBuilder.java +++ b/dev/com.ibm.ws.jaxws.2.3.web/src/com/ibm/ws/jaxws23/web/WebJaxWsModuleInfoBuilder.java @@ -27,6 +27,7 @@ import com.ibm.websphere.ras.Tr; import com.ibm.websphere.ras.TraceComponent; import com.ibm.ws.container.service.annotations.WebAnnotations; +import com.ibm.ws.container.service.annocache.AnnotationsBetaHelper; import com.ibm.ws.container.service.app.deploy.extended.ExtendedModuleInfo; import com.ibm.ws.jaxws.JaxWsConstants; import com.ibm.ws.jaxws.metadata.EndpointType; @@ -70,81 +71,121 @@ public WebJaxWsModuleInfoBuilder() { @Override public ExtendedModuleInfo build(ModuleMetaData moduleMetaData, Container containerToAdapt, JaxWsModuleInfo jaxWsModuleInfo) throws UnableToAdaptException { - // check if it is router web module for EJB based Web services - if (JaxWsUtils.isEJBModule(JaxWsMetaDataManager.getJaxWsModuleMetaData(moduleMetaData).getModuleContainer())) { + if ( JaxWsUtils.isEJBModule( JaxWsMetaDataManager.getJaxWsModuleMetaData(moduleMetaData).getModuleContainer() ) ) { + if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) { + Tr.debug(tc, "EJB module; ignore web services"); + } return null; } EndpointInfoBuilder endpointInfoBuilder = endpointInfoBuilderSRRef.getService(); - if (endpointInfoBuilder == null) { + if ( endpointInfoBuilder == null ) { if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) { - Tr.debug(tc, "Cannot get the EndpointInfoBuilder, will ignore all the Webservices."); + Tr.debug(tc, "No EndpointInfoBuilder; ignore web services"); } return null; } - WebAnnotations webAnnotations = containerToAdapt.adapt(WebAnnotations.class); + // TODO: The placement of the info store in the context is problematic: + // The value should be removed from the context and managed wholly + // within this builder. + // + // There are two problems: First, the reference persists into the + // postBuild call, where the info store is no longer open. Second, + // obtaining the store is expensive and should be avoided whenever + // possible. + + WebAnnotations webAnnotations = AnnotationsBetaHelper.getWebAnnotations(containerToAdapt); InfoStore infoStore = webAnnotations.getInfoStore(); - EndpointInfoBuilderContext endpointInfoBuilderContext = new EndpointInfoBuilderContext(infoStore, containerToAdapt); - JaxWsModuleInfoBuilderContext jaxWsModuleInfoBuilderContext = new JaxWsModuleInfoBuilderContext(moduleMetaData, containerToAdapt, endpointInfoBuilderContext); + EndpointInfoBuilderContext endpointInfoBuilderContext = + new EndpointInfoBuilderContext(infoStore, containerToAdapt); + + JaxWsModuleInfoBuilderContext jaxWsModuleInfoBuilderContext = + new JaxWsModuleInfoBuilderContext(moduleMetaData, containerToAdapt, endpointInfoBuilderContext); - // Get all servlet name and class pairs in web.xml Map servletNameClassPairsInWebXML = getServletNameClassPairsInWebXML(containerToAdapt); jaxWsModuleInfoBuilderContext.addContextEnv(JaxWsConstants.SERVLET_NAME_CLASS_PAIRS_FOR_EJBSINWAR, servletNameClassPairsInWebXML); - // call the extensions to extra pre build the jaxWsModuleInfo, eg: endponitInfo for EJBs in War - for (JaxWsModuleInfoBuilderExtension extension : extensions) { + // call the extensions to extra pre build the jaxWsModuleInfo, + // eg: endpointInfo for EJBs in War + for ( JaxWsModuleInfoBuilderExtension extension : extensions ) { extension.preBuild(jaxWsModuleInfoBuilderContext, jaxWsModuleInfo); } + webAnnotations.openInfoStore(); // See the TODO, above. This ought to be avoided if possible. + try { - webAnnotations.openInfoStore(); + WebAppConfig webAppConfig = containerToAdapt.adapt(WebAppConfig.class); Set presentedServices = jaxWsModuleInfo.getEndpointImplBeanClassNames(); - WebAppConfig webAppConfig = containerToAdapt.adapt(WebAppConfig.class); setupContextRoot(moduleMetaData, webAppConfig); setupVirtualHostConfig(moduleMetaData, webAppConfig); - if (webAppConfig.isMetadataComplete()) { - // only scan the classes configured in web.xml - processClassesInWebXML(endpointInfoBuilder, endpointInfoBuilderContext, webAppConfig, jaxWsModuleInfo, presentedServices); - } else { - // scan all the classes in the application's classPath - Collection implClassNamesInWebXML = servletNameClassPairsInWebXML.values(); - AnnotationTargets_Targets annotationTargets = webAnnotations.getAnnotationTargets(); - Set serviceClassNames = new HashSet(); + if ( !webAppConfig.isMetadataComplete() ) { + Collection implClassNamesInWebXML = servletNameClassPairsInWebXML.values(); // d95160: The prior implementation obtained classes from the SEED location. // That implementation is not changed by d95160. - serviceClassNames.addAll(annotationTargets.getAnnotatedClasses(WebService.class.getName(), - AnnotationTargets_Targets.POLICY_SEED)); - serviceClassNames.addAll(annotationTargets.getAnnotatedClasses(WebServiceProvider.class.getName(), - AnnotationTargets_Targets.POLICY_SEED)); + AnnotationTargets_Targets annotationTargets = webAnnotations.getAnnotationTargets(); + + Set webServiceClassNames = annotationTargets.getAnnotatedClasses(WebService.class.getName()); + if ( TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled() ) { + Tr.debug(tc, "WebService classes: " + webServiceClassNames); + } + + Set webServiceProviderClassNames = annotationTargets.getAnnotatedClasses(WebServiceProvider.class.getName()); + if ( TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled() ) { + Tr.debug(tc, "WebServiceProvider classes: " + webServiceProviderClassNames); + } - for (String serviceImplBeanClassName : serviceClassNames) { - // if the serviceImplBeanClassName is in web.xml, just ignore here. - if (implClassNamesInWebXML.contains(serviceImplBeanClassName) - || presentedServices.contains(serviceImplBeanClassName) - || !JaxWsUtils.isWebService(infoStore.getDelayableClassInfo(serviceImplBeanClassName))) { + Set serviceClassNames = new HashSet( webServiceClassNames.size() + webServiceProviderClassNames.size() ); + serviceClassNames.addAll(webServiceClassNames); + serviceClassNames.addAll(webServiceProviderClassNames); + + for ( String serviceImplBeanClassName : serviceClassNames ) { + String skipReason; + if ( implClassNamesInWebXML.contains(serviceImplBeanClassName ) ) { + skipReason = "Listed in web.xml"; + } else if ( presentedServices.contains(serviceImplBeanClassName) ) { + skipReason = "Presentation service"; + } else if ( webServiceClassNames.contains(serviceImplBeanClassName) ) { + skipReason = null; + } else if ( !JaxWsUtils.isWebService( infoStore.getDelayableClassInfo(serviceImplBeanClassName)) ) { + skipReason = "Not a web service"; + } else { + skipReason = null; + } + if ( skipReason != null ) { + if ( TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled() ) { + Tr.debug(tc, "Skip [ " + serviceImplBeanClassName + " ]: " + skipReason); + } continue; + } else { + if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) { + Tr.debug(tc, "Process service [ " + serviceImplBeanClassName + " ]"); + } } - jaxWsModuleInfo.addEndpointInfo(serviceImplBeanClassName, - endpointInfoBuilder.build(endpointInfoBuilderContext, serviceImplBeanClassName, EndpointType.SERVLET)); + jaxWsModuleInfo.addEndpointInfo( + serviceImplBeanClassName, + endpointInfoBuilder.build(endpointInfoBuilderContext, serviceImplBeanClassName, EndpointType.SERVLET)); } - // now process the serviceImplBeanClassName in web.xml. - // maybe the serviceImplBeanClassName is in sharedLibs which can not be read by webAnnotations.getAnnotationTargets(). - processClassesInWebXML(endpointInfoBuilder, endpointInfoBuilderContext, webAppConfig, jaxWsModuleInfo, presentedServices); } + + // now process the serviceImplBeanClassName in web.xml. + // maybe the serviceImplBeanClassName is in sharedLibs which + // can not be read by webAnnotations.getAnnotationTargets(). + processClassesInWebXML(endpointInfoBuilder, endpointInfoBuilderContext, webAppConfig, jaxWsModuleInfo, presentedServices); + } finally { webAnnotations.closeInfoStore(); } // call the extensions to extra post build the jaxWsModuleInfo, eg: security settings - for (JaxWsModuleInfoBuilderExtension extension : extensions) { + for ( JaxWsModuleInfoBuilderExtension extension : extensions ) { extension.postBuild(jaxWsModuleInfoBuilderContext, jaxWsModuleInfo); } @@ -197,10 +238,6 @@ public Void run() { /** * Get all the Servlet name and className pairs from web.xml - * - * @param webAppConfig - * @return - * @throws UnableToAdaptException */ private Map getServletNameClassPairsInWebXML(Container containerToAdapt) throws UnableToAdaptException { Map nameClassPairs = new HashMap(); @@ -214,37 +251,53 @@ private Map getServletNameClassPairsInWebXML(Container container } nameClassPairs.put(servletCfg.getServletName(), servletCfg.getClassName()); } + return nameClassPairs; } /** * Process the serviceImplBean classes in web.xml file. - * - * @param ctx - * @param webAppConfig - * @param jaxWsModuleInfo - * @throws Exception */ - private void processClassesInWebXML(EndpointInfoBuilder endpointInfoBuilder, EndpointInfoBuilderContext ctx, WebAppConfig webAppConfig, - JaxWsModuleInfo jaxWsModuleInfo, Set presentedServices) throws UnableToAdaptException { + private void processClassesInWebXML( + EndpointInfoBuilder endpointInfoBuilder, + EndpointInfoBuilderContext ctx, + WebAppConfig webAppConfig, + JaxWsModuleInfo jaxWsModuleInfo, + Set presentedServices) throws UnableToAdaptException { Iterator cfgIter = webAppConfig.getServletInfos(); - - while (cfgIter.hasNext()) { + while ( cfgIter.hasNext() ) { IServletConfig servletCfg = cfgIter.next(); + String servletName = servletCfg.getServletName(); String servletClassName = servletCfg.getClassName(); - if (servletClassName == null - || presentedServices.contains(servletClassName) - || !JaxWsUtils.isWebService(ctx.getInfoStore().getDelayableClassInfo(servletClassName))) { + + String skipReason; + if ( servletClassName == null ) { + skipReason = "Null servlet class name"; + } else if ( presentedServices.contains(servletClassName) ) { + skipReason = "Presented Service"; + } else if ( !JaxWsUtils.isWebService( ctx.getInfoStore().getDelayableClassInfo(servletClassName)) ) { + skipReason = "Not a web service"; + } else { + skipReason = null; + } + if ( skipReason != null ) { + if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) { + Tr.debug(tc, "Skip servlet [ " + servletName + " : " + servletClassName + " ]: " + skipReason); + } continue; + } else { + if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) { + Tr.debug(tc, "Process servlet [ " + servletName + " : " + servletClassName + " ]"); + } } - String servletName = servletCfg.getServletName(); - // add the servletName into EndpointInfoContext env ctx.addContextEnv(JaxWsConstants.ENV_ATTRIBUTE_ENDPOINT_SERVLET_NAME, servletName); - jaxWsModuleInfo.addEndpointInfo(servletName, endpointInfoBuilder.build(ctx, servletClassName, EndpointType.SERVLET)); + jaxWsModuleInfo.addEndpointInfo( + servletName, + endpointInfoBuilder.build(ctx, servletClassName, EndpointType.SERVLET) ); } } } diff --git a/dev/com.ibm.ws.jaxws.web/src/com/ibm/ws/jaxws/web/WebJaxWsModuleInfoBuilder.java b/dev/com.ibm.ws.jaxws.web/src/com/ibm/ws/jaxws/web/WebJaxWsModuleInfoBuilder.java index 8e41d8ec6b7c..4bd6a46d5461 100644 --- a/dev/com.ibm.ws.jaxws.web/src/com/ibm/ws/jaxws/web/WebJaxWsModuleInfoBuilder.java +++ b/dev/com.ibm.ws.jaxws.web/src/com/ibm/ws/jaxws/web/WebJaxWsModuleInfoBuilder.java @@ -72,44 +72,53 @@ public WebJaxWsModuleInfoBuilder() { @Override public ExtendedModuleInfo build(ModuleMetaData moduleMetaData, Container containerToAdapt, JaxWsModuleInfo jaxWsModuleInfo) throws UnableToAdaptException { // check if it is router web module for EJB based Web services - if (JaxWsUtils.isEJBModule(JaxWsMetaDataManager.getJaxWsModuleMetaData(moduleMetaData).getModuleContainer())) { + if ( JaxWsUtils.isEJBModule( JaxWsMetaDataManager.getJaxWsModuleMetaData(moduleMetaData).getModuleContainer() ) ) { + if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) { + Tr.debug(tc, "EJB module; ignore web services"); + } return null; } EndpointInfoBuilder endpointInfoBuilder = endpointInfoBuilderSRRef.getService(); - if (endpointInfoBuilder == null) { + if ( endpointInfoBuilder == null ) { if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) { - Tr.debug(tc, "Cannot get the EndpointInfoBuilder, will ignore all the Webservices."); + Tr.debug(tc, "No EndpointInfoBuilder; ignore web services"); } return null; } - WebAppConfig webAppConfig = containerToAdapt.adapt(WebAppConfig.class); + // TODO: The placement of the info store in the context is problematic: + // The value should be removed from the context and managed wholly + // within this builder. + // + // There are two problems: First, the reference persists into the + // postBuild call, where the info store is no longer open. Second, + // obtaining the store is expensive and should be avoided whenever + // possible. WebAnnotations webAnnotations = AnnotationsBetaHelper.getWebAnnotations(containerToAdapt); InfoStore infoStore = webAnnotations.getInfoStore(); - AnnotationTargets_Targets annotationTargets; - if ( !webAppConfig.isMetadataComplete() ) { - annotationTargets = webAnnotations.getAnnotationTargets(); - } else { - annotationTargets = null; - } + EndpointInfoBuilderContext endpointInfoBuilderContext = + new EndpointInfoBuilderContext(infoStore, containerToAdapt); - EndpointInfoBuilderContext endpointInfoBuilderContext = new EndpointInfoBuilderContext(infoStore, containerToAdapt); - JaxWsModuleInfoBuilderContext jaxWsModuleInfoBuilderContext = new JaxWsModuleInfoBuilderContext(moduleMetaData, containerToAdapt, endpointInfoBuilderContext); + JaxWsModuleInfoBuilderContext jaxWsModuleInfoBuilderContext = + new JaxWsModuleInfoBuilderContext(moduleMetaData, containerToAdapt, endpointInfoBuilderContext); Map servletNameClassPairsInWebXML = getServletNameClassPairsInWebXML(containerToAdapt); jaxWsModuleInfoBuilderContext.addContextEnv(JaxWsConstants.SERVLET_NAME_CLASS_PAIRS_FOR_EJBSINWAR, servletNameClassPairsInWebXML); - // call the extensions to extra pre build the jaxWsModuleInfo, eg: endpointInfo for EJBs in War - for (JaxWsModuleInfoBuilderExtension extension : extensions) { + // call the extensions to extra pre build the jaxWsModuleInfo, + // eg: endpointInfo for EJBs in War + for ( JaxWsModuleInfoBuilderExtension extension : extensions ) { extension.preBuild(jaxWsModuleInfoBuilderContext, jaxWsModuleInfo); } - webAnnotations.openInfoStore(); + webAnnotations.openInfoStore(); // See the TODO, above. This ought to be avoided if possible. try { + WebAppConfig webAppConfig = containerToAdapt.adapt(WebAppConfig.class); + Set presentedServices = jaxWsModuleInfo.getEndpointImplBeanClassNames(); setupContextRoot(moduleMetaData, webAppConfig); setupVirtualHostConfig(moduleMetaData, webAppConfig); @@ -120,20 +129,49 @@ public ExtendedModuleInfo build(ModuleMetaData moduleMetaData, Container contain // d95160: The prior implementation obtained classes from the SEED location. // That implementation is not changed by d95160. - Set serviceClassNames = new HashSet(); + AnnotationTargets_Targets annotationTargets = webAnnotations.getAnnotationTargets(); - serviceClassNames.addAll( annotationTargets.getAnnotatedClasses(WebService.class.getName()) ); - serviceClassNames.addAll( annotationTargets.getAnnotatedClasses(WebServiceProvider.class.getName()) ); + Set webServiceClassNames = annotationTargets.getAnnotatedClasses(WebService.class.getName()); + if ( TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled() ) { + Tr.debug(tc, "WebService classes: " + webServiceClassNames); + } + + Set webServiceProviderClassNames = annotationTargets.getAnnotatedClasses(WebServiceProvider.class.getName()); + if ( TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled() ) { + Tr.debug(tc, "WebServiceProvider classes: " + webServiceProviderClassNames); + } + + Set serviceClassNames = new HashSet( webServiceClassNames.size() + webServiceProviderClassNames.size() ); + serviceClassNames.addAll(webServiceClassNames); + serviceClassNames.addAll(webServiceProviderClassNames); for ( String serviceImplBeanClassName : serviceClassNames ) { - // if the serviceImplBeanClassName is in web.xml, just ignore here. - if ( implClassNamesInWebXML.contains(serviceImplBeanClassName) || - presentedServices.contains(serviceImplBeanClassName) || - !JaxWsUtils.isWebService(infoStore.getDelayableClassInfo(serviceImplBeanClassName)) ) { + String skipReason; + if ( implClassNamesInWebXML.contains(serviceImplBeanClassName ) ) { + skipReason = "Listed in web.xml"; + } else if ( presentedServices.contains(serviceImplBeanClassName) ) { + skipReason = "Presentation service"; + } else if ( webServiceClassNames.contains(serviceImplBeanClassName) ) { + skipReason = null; + } else if ( !JaxWsUtils.isWebService( infoStore.getDelayableClassInfo(serviceImplBeanClassName)) ) { + skipReason = "Not a web service"; + } else { + skipReason = null; + } + if ( skipReason != null ) { + if ( TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled() ) { + Tr.debug(tc, "Skip [ " + serviceImplBeanClassName + " ]: " + skipReason); + } continue; + } else { + if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) { + Tr.debug(tc, "Process service [ " + serviceImplBeanClassName + " ]"); + } } - jaxWsModuleInfo.addEndpointInfo(serviceImplBeanClassName, endpointInfoBuilder.build(endpointInfoBuilderContext, serviceImplBeanClassName, EndpointType.SERVLET)); + jaxWsModuleInfo.addEndpointInfo( + serviceImplBeanClassName, + endpointInfoBuilder.build(endpointInfoBuilderContext, serviceImplBeanClassName, EndpointType.SERVLET)); } } @@ -147,7 +185,7 @@ public ExtendedModuleInfo build(ModuleMetaData moduleMetaData, Container contain } // call the extensions to extra post build the jaxWsModuleInfo, eg: security settings - for (JaxWsModuleInfoBuilderExtension extension : extensions) { + for ( JaxWsModuleInfoBuilderExtension extension : extensions ) { extension.postBuild(jaxWsModuleInfoBuilderContext, jaxWsModuleInfo); } @@ -219,26 +257,46 @@ private Map getServletNameClassPairsInWebXML(Container container /** * Process the serviceImplBean classes in web.xml file. */ - private void processClassesInWebXML(EndpointInfoBuilder endpointInfoBuilder, EndpointInfoBuilderContext ctx, WebAppConfig webAppConfig, - JaxWsModuleInfo jaxWsModuleInfo, Set presentedServices) throws UnableToAdaptException { - - Iterator cfgIter = webAppConfig.getServletInfos(); - - while (cfgIter.hasNext()) { + private void processClassesInWebXML( + EndpointInfoBuilder endpointInfoBuilder, + EndpointInfoBuilderContext ctx, + WebAppConfig webAppConfig, + JaxWsModuleInfo jaxWsModuleInfo, + Set presentedServices) throws UnableToAdaptException { + + Iterator cfgIter = webAppConfig.getServletInfos(); + while ( cfgIter.hasNext() ) { IServletConfig servletCfg = cfgIter.next(); + String servletName = servletCfg.getServletName(); String servletClassName = servletCfg.getClassName(); - if (servletClassName == null - || presentedServices.contains(servletClassName) - || !JaxWsUtils.isWebService(ctx.getInfoStore().getDelayableClassInfo(servletClassName))) { + + String skipReason; + if ( servletClassName == null ) { + skipReason = "Null servlet class name"; + } else if ( presentedServices.contains(servletClassName) ) { + skipReason = "Presented Service"; + } else if ( !JaxWsUtils.isWebService( ctx.getInfoStore().getDelayableClassInfo(servletClassName)) ) { + skipReason = "Not a web service"; + } else { + skipReason = null; + } + if ( skipReason != null ) { + if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) { + Tr.debug(tc, "Skip servlet [ " + servletName + " : " + servletClassName + " ]: " + skipReason); + } continue; + } else { + if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) { + Tr.debug(tc, "Process servlet [ " + servletName + " : " + servletClassName + " ]"); + } } - String servletName = servletCfg.getServletName(); - // add the servletName into EndpointInfoContext env ctx.addContextEnv(JaxWsConstants.ENV_ATTRIBUTE_ENDPOINT_SERVLET_NAME, servletName); - jaxWsModuleInfo.addEndpointInfo(servletName, endpointInfoBuilder.build(ctx, servletClassName, EndpointType.SERVLET)); + jaxWsModuleInfo.addEndpointInfo( + servletName, + endpointInfoBuilder.build(ctx, servletClassName, EndpointType.SERVLET) ); } } } From b9312f4800e14a2de2a2b3b1d46c38756b2c31aa Mon Sep 17 00:00:00 2001 From: Thomas Bitonti Date: Mon, 18 Nov 2019 11:20:09 -0500 Subject: [PATCH 2/3] Wire JaxWsExtensionFactory to anno caching. --- .../webcontainer/JaxWsExtensionFactory.java | 10 ++++++++-- .../jaxws/webcontainer/JaxWsExtensionFactory.java | 14 +++++++++----- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/dev/com.ibm.ws.jaxws.2.3.webcontainer/src/com/ibm/ws/jaxws23/webcontainer/JaxWsExtensionFactory.java b/dev/com.ibm.ws.jaxws.2.3.webcontainer/src/com/ibm/ws/jaxws23/webcontainer/JaxWsExtensionFactory.java index 3a2ea59d93b5..7e232638100c 100644 --- a/dev/com.ibm.ws.jaxws.2.3.webcontainer/src/com/ibm/ws/jaxws23/webcontainer/JaxWsExtensionFactory.java +++ b/dev/com.ibm.ws.jaxws.2.3.webcontainer/src/com/ibm/ws/jaxws23/webcontainer/JaxWsExtensionFactory.java @@ -21,6 +21,7 @@ import com.ibm.websphere.ras.Tr; import com.ibm.websphere.ras.TraceComponent; import com.ibm.ws.container.service.annotations.WebAnnotations; +import com.ibm.ws.container.service.annocache.AnnotationsBetaHelper; import com.ibm.ws.jaxws.JaxWsConstants; import com.ibm.ws.jaxws.endpoint.EndpointPublisher; import com.ibm.ws.jaxws.endpoint.EndpointPublisherManager; @@ -39,6 +40,7 @@ import com.ibm.wsspi.webcontainer.extension.ExtensionProcessor; import com.ibm.wsspi.webcontainer.metadata.WebModuleMetaData; import com.ibm.wsspi.webcontainer.servlet.IServletContext; +import com.ibm.wsspi.anno.info.InfoStore; public class JaxWsExtensionFactory implements ExtensionFactory { @@ -108,8 +110,12 @@ public ExtensionProcessor createExtensionProcessor(IServletContext servletContex WebApp webApp = (WebApp) servletContext; publisherContext.setAttribute(JaxWsWebContainerConstants.NAMESPACE_COLLABORATOR, webApp.getCollaboratorHelper().getWebAppNameSpaceCollaborator()); - publisherContext.setAttribute(JaxWsConstants.ENDPOINT_INFO_BUILDER_CONTEXT, - new EndpointInfoBuilderContext(servletContext.getModuleContainer().adapt(WebAnnotations.class).getInfoStore(), servletContext.getModuleContainer())); + WebAnnotations webAnnotations = AnnotationsBetaHelper.getWebAnnotations(servletContext.getModuleContainer()); + InfoStore infoStore = webAnnotations.getInfoStore(); + + publisherContext.setAttribute( + JaxWsConstants.ENDPOINT_INFO_BUILDER_CONTEXT, + new EndpointInfoBuilderContext(infoStore,servletContext.getModuleContainer())); // get endpoint publisher and do publish EndpointPublisher endpointPublisher = endpointPublisherManagerRef.getServiceWithException().getEndpointPublisher(JaxWsConstants.WEB_ENDPOINT_PUBLISHER_TYPE); diff --git a/dev/com.ibm.ws.jaxws.webcontainer/src/com/ibm/ws/jaxws/webcontainer/JaxWsExtensionFactory.java b/dev/com.ibm.ws.jaxws.webcontainer/src/com/ibm/ws/jaxws/webcontainer/JaxWsExtensionFactory.java index b63e5456e2fd..bd1234fe1c6e 100644 --- a/dev/com.ibm.ws.jaxws.webcontainer/src/com/ibm/ws/jaxws/webcontainer/JaxWsExtensionFactory.java +++ b/dev/com.ibm.ws.jaxws.webcontainer/src/com/ibm/ws/jaxws/webcontainer/JaxWsExtensionFactory.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012 IBM Corporation and others. + * Copyright (c) 2012, 2019 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -21,6 +21,7 @@ import com.ibm.websphere.ras.Tr; import com.ibm.websphere.ras.TraceComponent; import com.ibm.ws.container.service.annotations.WebAnnotations; +import com.ibm.ws.container.service.annocache.AnnotationsBetaHelper; import com.ibm.ws.jaxws.JaxWsConstants; import com.ibm.ws.jaxws.endpoint.EndpointPublisher; import com.ibm.ws.jaxws.endpoint.EndpointPublisherManager; @@ -39,6 +40,7 @@ import com.ibm.wsspi.webcontainer.extension.ExtensionProcessor; import com.ibm.wsspi.webcontainer.metadata.WebModuleMetaData; import com.ibm.wsspi.webcontainer.servlet.IServletContext; +import com.ibm.wsspi.anno.info.InfoStore; public class JaxWsExtensionFactory implements ExtensionFactory { @@ -108,10 +110,12 @@ public ExtensionProcessor createExtensionProcessor(IServletContext servletContex WebApp webApp = (WebApp) servletContext; publisherContext.setAttribute(JaxWsWebContainerConstants.NAMESPACE_COLLABORATOR, webApp.getCollaboratorHelper().getWebAppNameSpaceCollaborator()); - publisherContext.setAttribute(JaxWsConstants.ENDPOINT_INFO_BUILDER_CONTEXT, new EndpointInfoBuilderContext( - servletContext.getModuleContainer().adapt(WebAnnotations.class).getInfoStore(), - servletContext.getModuleContainer() - )); + WebAnnotations webAnnotations = AnnotationsBetaHelper.getWebAnnotations(servletContext.getModuleContainer()); + InfoStore infoStore = webAnnotations.getInfoStore(); + + publisherContext.setAttribute( + JaxWsConstants.ENDPOINT_INFO_BUILDER_CONTEXT, + new EndpointInfoBuilderContext(infoStore, servletContext.getModuleContainer())); // get endpoint publisher and do publish EndpointPublisher endpointPublisher = endpointPublisherManagerRef.getServiceWithException().getEndpointPublisher(JaxWsConstants.WEB_ENDPOINT_PUBLISHER_TYPE); From 5c10f599ca32ea51b8dd2a4d095793a212af9897 Mon Sep 17 00:00:00 2001 From: Thomas Bitonti Date: Mon, 18 Nov 2019 16:11:03 -0500 Subject: [PATCH 3/3] Correct builder logic. Adjust info usage. Add more details to logging. --- .../web/WebJaxWsModuleInfoBuilder.java | 201 +++++++++++------- .../jaxws/web/WebJaxWsModuleInfoBuilder.java | 201 +++++++++++------- 2 files changed, 254 insertions(+), 148 deletions(-) diff --git a/dev/com.ibm.ws.jaxws.2.3.web/src/com/ibm/ws/jaxws23/web/WebJaxWsModuleInfoBuilder.java b/dev/com.ibm.ws.jaxws.2.3.web/src/com/ibm/ws/jaxws23/web/WebJaxWsModuleInfoBuilder.java index 33203f1511ad..c692a7dcbd23 100644 --- a/dev/com.ibm.ws.jaxws.2.3.web/src/com/ibm/ws/jaxws23/web/WebJaxWsModuleInfoBuilder.java +++ b/dev/com.ibm.ws.jaxws.2.3.web/src/com/ibm/ws/jaxws23/web/WebJaxWsModuleInfoBuilder.java @@ -11,6 +11,7 @@ package com.ibm.ws.jaxws23.web; import java.lang.reflect.Field; +import java.lang.reflect.Modifier; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Collection; @@ -46,6 +47,7 @@ import com.ibm.wsspi.adaptable.module.Container; import com.ibm.wsspi.adaptable.module.UnableToAdaptException; import com.ibm.wsspi.anno.info.InfoStore; +import com.ibm.wsspi.anno.info.ClassInfo; import com.ibm.wsspi.anno.targets.AnnotationTargets_Targets; import com.ibm.wsspi.http.VirtualHost; import com.ibm.wsspi.webcontainer.servlet.IServletConfig; @@ -105,8 +107,12 @@ public ExtendedModuleInfo build(ModuleMetaData moduleMetaData, Container contain JaxWsModuleInfoBuilderContext jaxWsModuleInfoBuilderContext = new JaxWsModuleInfoBuilderContext(moduleMetaData, containerToAdapt, endpointInfoBuilderContext); - Map servletNameClassPairsInWebXML = getServletNameClassPairsInWebXML(containerToAdapt); - jaxWsModuleInfoBuilderContext.addContextEnv(JaxWsConstants.SERVLET_NAME_CLASS_PAIRS_FOR_EJBSINWAR, servletNameClassPairsInWebXML); + Map servletNameClassPairsInWebXML = + getServletNameClassPairsInWebXML(containerToAdapt); + + jaxWsModuleInfoBuilderContext.addContextEnv( + JaxWsConstants.SERVLET_NAME_CLASS_PAIRS_FOR_EJBSINWAR, + servletNameClassPairsInWebXML); // call the extensions to extra pre build the jaxWsModuleInfo, // eg: endpointInfo for EJBs in War @@ -114,74 +120,125 @@ public ExtendedModuleInfo build(ModuleMetaData moduleMetaData, Container contain extension.preBuild(jaxWsModuleInfoBuilderContext, jaxWsModuleInfo); } - webAnnotations.openInfoStore(); // See the TODO, above. This ought to be avoided if possible. + boolean didOpen = false; try { WebAppConfig webAppConfig = containerToAdapt.adapt(WebAppConfig.class); Set presentedServices = jaxWsModuleInfo.getEndpointImplBeanClassNames(); + if ( TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled() ) { + Tr.debug(tc, "Presented service classes: " + presentedServices); + } + setupContextRoot(moduleMetaData, webAppConfig); setupVirtualHostConfig(moduleMetaData, webAppConfig); if ( !webAppConfig.isMetadataComplete() ) { Collection implClassNamesInWebXML = servletNameClassPairsInWebXML.values(); + if ( TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled() ) { + Tr.debug(tc, "Descriptor servlet class names: " + implClassNamesInWebXML); + } // d95160: The prior implementation obtained classes from the SEED location. // That implementation is not changed by d95160. AnnotationTargets_Targets annotationTargets = webAnnotations.getAnnotationTargets(); - Set webServiceClassNames = annotationTargets.getAnnotatedClasses(WebService.class.getName()); + Set serviceImplClassNames = annotationTargets.getAnnotatedClasses(WebService.class.getName()); if ( TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled() ) { - Tr.debug(tc, "WebService classes: " + webServiceClassNames); + Tr.debug(tc, "WebService classes: " + serviceImplClassNames); } - - Set webServiceProviderClassNames = annotationTargets.getAnnotatedClasses(WebServiceProvider.class.getName()); + Set providerImplClassNames = annotationTargets.getAnnotatedClasses(WebServiceProvider.class.getName()); if ( TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled() ) { - Tr.debug(tc, "WebServiceProvider classes: " + webServiceProviderClassNames); + Tr.debug(tc, "WebServiceProvider classes: " + providerImplClassNames); } + Set implClassNames = new HashSet( serviceImplClassNames.size() + providerImplClassNames.size() ); + implClassNames.addAll(serviceImplClassNames); + implClassNames.addAll(providerImplClassNames); - Set serviceClassNames = new HashSet( webServiceClassNames.size() + webServiceProviderClassNames.size() ); - serviceClassNames.addAll(webServiceClassNames); - serviceClassNames.addAll(webServiceProviderClassNames); - - for ( String serviceImplBeanClassName : serviceClassNames ) { + for ( String implClassName : implClassNames ) { String skipReason; - if ( implClassNamesInWebXML.contains(serviceImplBeanClassName ) ) { + if ( implClassNamesInWebXML.contains(implClassName ) ) { skipReason = "Listed in web.xml"; - } else if ( presentedServices.contains(serviceImplBeanClassName) ) { + } else if ( presentedServices.contains(implClassName) ) { skipReason = "Presentation service"; - } else if ( webServiceClassNames.contains(serviceImplBeanClassName) ) { - skipReason = null; - } else if ( !JaxWsUtils.isWebService( infoStore.getDelayableClassInfo(serviceImplBeanClassName)) ) { - skipReason = "Not a web service"; } else { - skipReason = null; + if ( !didOpen ) { + webAnnotations.openInfoStore(); + didOpen = true; + } + // Don't need to call 'validAnnotations': Guaranteed to have + // WebService or WebServiceProvider. + skipReason = validModifiers( infoStore.getDelayableClassInfo(implClassName) ); } + if ( skipReason != null ) { if ( TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled() ) { - Tr.debug(tc, "Skip [ " + serviceImplBeanClassName + " ]: " + skipReason); + Tr.debug(tc, "Skip [ " + implClassName + " ]: " + skipReason); } continue; } else { if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) { - Tr.debug(tc, "Process service [ " + serviceImplBeanClassName + " ]"); + Tr.debug(tc, "Process [ " + implClassName + " ]"); } } jaxWsModuleInfo.addEndpointInfo( - serviceImplBeanClassName, - endpointInfoBuilder.build(endpointInfoBuilderContext, serviceImplBeanClassName, EndpointType.SERVLET)); + implClassName, + endpointInfoBuilder.build(endpointInfoBuilderContext, implClassName, EndpointType.SERVLET)); } } - // now process the serviceImplBeanClassName in web.xml. - // maybe the serviceImplBeanClassName is in sharedLibs which + // now process the implClassName in web.xml. + // maybe the implClassName is in sharedLibs which // can not be read by webAnnotations.getAnnotationTargets(). - processClassesInWebXML(endpointInfoBuilder, endpointInfoBuilderContext, webAppConfig, jaxWsModuleInfo, presentedServices); + + Iterator cfgIter = webAppConfig.getServletInfos(); + while ( cfgIter.hasNext() ) { + IServletConfig servletCfg = cfgIter.next(); + + String servletName = servletCfg.getServletName(); + String servletClassName = servletCfg.getClassName(); + + String skipReason; + if ( servletClassName == null ) { + skipReason = "Null servlet class name"; + } else if ( presentedServices.contains(servletClassName) ) { + skipReason = "Presented Service"; + } else { + if ( !didOpen ) { + webAnnotations.openInfoStore(); + didOpen = true; + } + ClassInfo classInfo = infoStore.getDelayableClassInfo(servletClassName); + if ( (skipReason = validAnnotations(classInfo)) == null ) { + skipReason = validModifiers(classInfo); + } + } + if ( skipReason != null ) { + if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) { + Tr.debug(tc, "Skip servlet [ " + servletName + " : " + servletClassName + " ]: " + skipReason); + } + continue; + } else { + if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) { + Tr.debug(tc, "Process servlet [ " + servletName + " : " + servletClassName + " ]"); + } + } + + // Note that this step is only for servlet classes... + endpointInfoBuilderContext.addContextEnv(JaxWsConstants.ENV_ATTRIBUTE_ENDPOINT_SERVLET_NAME, servletName); + + // ... but this step is performed for both non-servlet and servlet classes. + jaxWsModuleInfo.addEndpointInfo( + servletName, + endpointInfoBuilder.build(endpointInfoBuilderContext, servletClassName, EndpointType.SERVLET) ); + } } finally { - webAnnotations.closeInfoStore(); + if ( didOpen ) { + webAnnotations.closeInfoStore(); + } } // call the extensions to extra post build the jaxWsModuleInfo, eg: security settings @@ -192,6 +249,48 @@ public ExtendedModuleInfo build(ModuleMetaData moduleMetaData, Container contain return null; } + // TODO: These tests use the info store, which does not account for + // metadata complete settings, and does not account for where + // the class lives in the class path. + + private String validAnnotations(ClassInfo classInfo) { + if ( classInfo == null ) { + return "Class not found"; + } else if ( !classInfo.isAnnotationPresent(WebService.class.getName()) && + !classInfo.isAnnotationPresent(WebServiceProvider.class.getName()) ) { + return "No WebService or WebServiceProvider annotation"; + } else { + return null; + } + } + + // TODO: These might be recoded to use the targets table, but then + // they would be subject to target class selection limits. + + private String validModifiers(ClassInfo classInfo) { + if ( classInfo == null ) { + return "Class not found"; + } else { + String skipReason; + int modifiers = classInfo.getModifiers(); + if ( !Modifier.isPublic(modifiers) ) { + skipReason = "Non-public modifier"; + } else if ( Modifier.isFinal(modifiers) ) { + skipReason = "Modifier is final"; + } else if ( Modifier.isAbstract(modifiers) ) { + skipReason = "Modifier is abstract"; + } else { + skipReason = null; + } + if ( skipReason != null ) { + if ( TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled() ) { + skipReason += " [ 0x" + Integer.toHexString(modifiers) + " ]"; + } + } + return skipReason; + } + } + private void setupContextRoot(ModuleMetaData moduleMetaData, WebAppConfig webAppConfig) { JaxWsModuleMetaData jaxWsModuleMetaData = JaxWsMetaDataManager.getJaxWsModuleMetaData(moduleMetaData); String contextRoot = webAppConfig.getContextRoot(); @@ -254,50 +353,4 @@ private Map getServletNameClassPairsInWebXML(Container container return nameClassPairs; } - - /** - * Process the serviceImplBean classes in web.xml file. - */ - private void processClassesInWebXML( - EndpointInfoBuilder endpointInfoBuilder, - EndpointInfoBuilderContext ctx, - WebAppConfig webAppConfig, - JaxWsModuleInfo jaxWsModuleInfo, - Set presentedServices) throws UnableToAdaptException { - - Iterator cfgIter = webAppConfig.getServletInfos(); - while ( cfgIter.hasNext() ) { - IServletConfig servletCfg = cfgIter.next(); - - String servletName = servletCfg.getServletName(); - String servletClassName = servletCfg.getClassName(); - - String skipReason; - if ( servletClassName == null ) { - skipReason = "Null servlet class name"; - } else if ( presentedServices.contains(servletClassName) ) { - skipReason = "Presented Service"; - } else if ( !JaxWsUtils.isWebService( ctx.getInfoStore().getDelayableClassInfo(servletClassName)) ) { - skipReason = "Not a web service"; - } else { - skipReason = null; - } - if ( skipReason != null ) { - if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) { - Tr.debug(tc, "Skip servlet [ " + servletName + " : " + servletClassName + " ]: " + skipReason); - } - continue; - } else { - if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) { - Tr.debug(tc, "Process servlet [ " + servletName + " : " + servletClassName + " ]"); - } - } - - ctx.addContextEnv(JaxWsConstants.ENV_ATTRIBUTE_ENDPOINT_SERVLET_NAME, servletName); - - jaxWsModuleInfo.addEndpointInfo( - servletName, - endpointInfoBuilder.build(ctx, servletClassName, EndpointType.SERVLET) ); - } - } } diff --git a/dev/com.ibm.ws.jaxws.web/src/com/ibm/ws/jaxws/web/WebJaxWsModuleInfoBuilder.java b/dev/com.ibm.ws.jaxws.web/src/com/ibm/ws/jaxws/web/WebJaxWsModuleInfoBuilder.java index 4bd6a46d5461..dd2b27d66c59 100644 --- a/dev/com.ibm.ws.jaxws.web/src/com/ibm/ws/jaxws/web/WebJaxWsModuleInfoBuilder.java +++ b/dev/com.ibm.ws.jaxws.web/src/com/ibm/ws/jaxws/web/WebJaxWsModuleInfoBuilder.java @@ -11,6 +11,7 @@ package com.ibm.ws.jaxws.web; import java.lang.reflect.Field; +import java.lang.reflect.Modifier; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Collection; @@ -46,6 +47,7 @@ import com.ibm.wsspi.adaptable.module.Container; import com.ibm.wsspi.adaptable.module.UnableToAdaptException; import com.ibm.wsspi.anno.info.InfoStore; +import com.ibm.wsspi.anno.info.ClassInfo; import com.ibm.wsspi.anno.targets.AnnotationTargets_Targets; import com.ibm.wsspi.http.VirtualHost; import com.ibm.wsspi.webcontainer.servlet.IServletConfig; @@ -105,8 +107,12 @@ public ExtendedModuleInfo build(ModuleMetaData moduleMetaData, Container contain JaxWsModuleInfoBuilderContext jaxWsModuleInfoBuilderContext = new JaxWsModuleInfoBuilderContext(moduleMetaData, containerToAdapt, endpointInfoBuilderContext); - Map servletNameClassPairsInWebXML = getServletNameClassPairsInWebXML(containerToAdapt); - jaxWsModuleInfoBuilderContext.addContextEnv(JaxWsConstants.SERVLET_NAME_CLASS_PAIRS_FOR_EJBSINWAR, servletNameClassPairsInWebXML); + Map servletNameClassPairsInWebXML = + getServletNameClassPairsInWebXML(containerToAdapt); + + jaxWsModuleInfoBuilderContext.addContextEnv( + JaxWsConstants.SERVLET_NAME_CLASS_PAIRS_FOR_EJBSINWAR, + servletNameClassPairsInWebXML); // call the extensions to extra pre build the jaxWsModuleInfo, // eg: endpointInfo for EJBs in War @@ -114,74 +120,125 @@ public ExtendedModuleInfo build(ModuleMetaData moduleMetaData, Container contain extension.preBuild(jaxWsModuleInfoBuilderContext, jaxWsModuleInfo); } - webAnnotations.openInfoStore(); // See the TODO, above. This ought to be avoided if possible. + boolean didOpen = false; try { WebAppConfig webAppConfig = containerToAdapt.adapt(WebAppConfig.class); Set presentedServices = jaxWsModuleInfo.getEndpointImplBeanClassNames(); + if ( TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled() ) { + Tr.debug(tc, "Presented service classes: " + presentedServices); + } + setupContextRoot(moduleMetaData, webAppConfig); setupVirtualHostConfig(moduleMetaData, webAppConfig); if ( !webAppConfig.isMetadataComplete() ) { Collection implClassNamesInWebXML = servletNameClassPairsInWebXML.values(); + if ( TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled() ) { + Tr.debug(tc, "Descriptor servlet class names: " + implClassNamesInWebXML); + } // d95160: The prior implementation obtained classes from the SEED location. // That implementation is not changed by d95160. AnnotationTargets_Targets annotationTargets = webAnnotations.getAnnotationTargets(); - Set webServiceClassNames = annotationTargets.getAnnotatedClasses(WebService.class.getName()); + Set serviceImplClassNames = annotationTargets.getAnnotatedClasses(WebService.class.getName()); if ( TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled() ) { - Tr.debug(tc, "WebService classes: " + webServiceClassNames); + Tr.debug(tc, "WebService classes: " + serviceImplClassNames); } - - Set webServiceProviderClassNames = annotationTargets.getAnnotatedClasses(WebServiceProvider.class.getName()); + Set providerImplClassNames = annotationTargets.getAnnotatedClasses(WebServiceProvider.class.getName()); if ( TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled() ) { - Tr.debug(tc, "WebServiceProvider classes: " + webServiceProviderClassNames); + Tr.debug(tc, "WebServiceProvider classes: " + providerImplClassNames); } + Set implClassNames = new HashSet( serviceImplClassNames.size() + providerImplClassNames.size() ); + implClassNames.addAll(serviceImplClassNames); + implClassNames.addAll(providerImplClassNames); - Set serviceClassNames = new HashSet( webServiceClassNames.size() + webServiceProviderClassNames.size() ); - serviceClassNames.addAll(webServiceClassNames); - serviceClassNames.addAll(webServiceProviderClassNames); - - for ( String serviceImplBeanClassName : serviceClassNames ) { + for ( String implClassName : implClassNames ) { String skipReason; - if ( implClassNamesInWebXML.contains(serviceImplBeanClassName ) ) { + if ( implClassNamesInWebXML.contains(implClassName ) ) { skipReason = "Listed in web.xml"; - } else if ( presentedServices.contains(serviceImplBeanClassName) ) { + } else if ( presentedServices.contains(implClassName) ) { skipReason = "Presentation service"; - } else if ( webServiceClassNames.contains(serviceImplBeanClassName) ) { - skipReason = null; - } else if ( !JaxWsUtils.isWebService( infoStore.getDelayableClassInfo(serviceImplBeanClassName)) ) { - skipReason = "Not a web service"; } else { - skipReason = null; + if ( !didOpen ) { + webAnnotations.openInfoStore(); + didOpen = true; + } + // Don't need to call 'validAnnotations': Guaranteed to have + // WebService or WebServiceProvider. + skipReason = validModifiers( infoStore.getDelayableClassInfo(implClassName) ); } + if ( skipReason != null ) { if ( TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled() ) { - Tr.debug(tc, "Skip [ " + serviceImplBeanClassName + " ]: " + skipReason); + Tr.debug(tc, "Skip [ " + implClassName + " ]: " + skipReason); } continue; } else { if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) { - Tr.debug(tc, "Process service [ " + serviceImplBeanClassName + " ]"); + Tr.debug(tc, "Process [ " + implClassName + " ]"); } } jaxWsModuleInfo.addEndpointInfo( - serviceImplBeanClassName, - endpointInfoBuilder.build(endpointInfoBuilderContext, serviceImplBeanClassName, EndpointType.SERVLET)); + implClassName, + endpointInfoBuilder.build(endpointInfoBuilderContext, implClassName, EndpointType.SERVLET)); } } - // now process the serviceImplBeanClassName in web.xml. - // maybe the serviceImplBeanClassName is in sharedLibs which + // now process the implClassName in web.xml. + // maybe the implClassName is in sharedLibs which // can not be read by webAnnotations.getAnnotationTargets(). - processClassesInWebXML(endpointInfoBuilder, endpointInfoBuilderContext, webAppConfig, jaxWsModuleInfo, presentedServices); + + Iterator cfgIter = webAppConfig.getServletInfos(); + while ( cfgIter.hasNext() ) { + IServletConfig servletCfg = cfgIter.next(); + + String servletName = servletCfg.getServletName(); + String servletClassName = servletCfg.getClassName(); + + String skipReason; + if ( servletClassName == null ) { + skipReason = "Null servlet class name"; + } else if ( presentedServices.contains(servletClassName) ) { + skipReason = "Presented Service"; + } else { + if ( !didOpen ) { + webAnnotations.openInfoStore(); + didOpen = true; + } + ClassInfo classInfo = infoStore.getDelayableClassInfo(servletClassName); + if ( (skipReason = validAnnotations(classInfo)) == null ) { + skipReason = validModifiers(classInfo); + } + } + if ( skipReason != null ) { + if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) { + Tr.debug(tc, "Skip servlet [ " + servletName + " : " + servletClassName + " ]: " + skipReason); + } + continue; + } else { + if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) { + Tr.debug(tc, "Process servlet [ " + servletName + " : " + servletClassName + " ]"); + } + } + + // Note that this step is only for servlet classes... + endpointInfoBuilderContext.addContextEnv(JaxWsConstants.ENV_ATTRIBUTE_ENDPOINT_SERVLET_NAME, servletName); + + // ... but this step is performed for both non-servlet and servlet classes. + jaxWsModuleInfo.addEndpointInfo( + servletName, + endpointInfoBuilder.build(endpointInfoBuilderContext, servletClassName, EndpointType.SERVLET) ); + } } finally { - webAnnotations.closeInfoStore(); + if ( didOpen ) { + webAnnotations.closeInfoStore(); + } } // call the extensions to extra post build the jaxWsModuleInfo, eg: security settings @@ -192,6 +249,48 @@ public ExtendedModuleInfo build(ModuleMetaData moduleMetaData, Container contain return null; } + // TODO: These tests use the info store, which does not account for + // metadata complete settings, and does not account for where + // the class lives in the class path. + + private String validAnnotations(ClassInfo classInfo) { + if ( classInfo == null ) { + return "Class not found"; + } else if ( !classInfo.isAnnotationPresent(WebService.class.getName()) && + !classInfo.isAnnotationPresent(WebServiceProvider.class.getName()) ) { + return "No WebService or WebServiceProvider annotation"; + } else { + return null; + } + } + + // TODO: These might be recoded to use the targets table, but then + // they would be subject to target class selection limits. + + private String validModifiers(ClassInfo classInfo) { + if ( classInfo == null ) { + return "Class not found"; + } else { + String skipReason; + int modifiers = classInfo.getModifiers(); + if ( !Modifier.isPublic(modifiers) ) { + skipReason = "Non-public modifier"; + } else if ( Modifier.isFinal(modifiers) ) { + skipReason = "Modifier is final"; + } else if ( Modifier.isAbstract(modifiers) ) { + skipReason = "Modifier is abstract"; + } else { + skipReason = null; + } + if ( skipReason != null ) { + if ( TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled() ) { + skipReason += " [ 0x" + Integer.toHexString(modifiers) + " ]"; + } + } + return skipReason; + } + } + private void setupContextRoot(ModuleMetaData moduleMetaData, WebAppConfig webAppConfig) { JaxWsModuleMetaData jaxWsModuleMetaData = JaxWsMetaDataManager.getJaxWsModuleMetaData(moduleMetaData); String contextRoot = webAppConfig.getContextRoot(); @@ -253,50 +352,4 @@ private Map getServletNameClassPairsInWebXML(Container container } return nameClassPairs; } - - /** - * Process the serviceImplBean classes in web.xml file. - */ - private void processClassesInWebXML( - EndpointInfoBuilder endpointInfoBuilder, - EndpointInfoBuilderContext ctx, - WebAppConfig webAppConfig, - JaxWsModuleInfo jaxWsModuleInfo, - Set presentedServices) throws UnableToAdaptException { - - Iterator cfgIter = webAppConfig.getServletInfos(); - while ( cfgIter.hasNext() ) { - IServletConfig servletCfg = cfgIter.next(); - - String servletName = servletCfg.getServletName(); - String servletClassName = servletCfg.getClassName(); - - String skipReason; - if ( servletClassName == null ) { - skipReason = "Null servlet class name"; - } else if ( presentedServices.contains(servletClassName) ) { - skipReason = "Presented Service"; - } else if ( !JaxWsUtils.isWebService( ctx.getInfoStore().getDelayableClassInfo(servletClassName)) ) { - skipReason = "Not a web service"; - } else { - skipReason = null; - } - if ( skipReason != null ) { - if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) { - Tr.debug(tc, "Skip servlet [ " + servletName + " : " + servletClassName + " ]: " + skipReason); - } - continue; - } else { - if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) { - Tr.debug(tc, "Process servlet [ " + servletName + " : " + servletClassName + " ]"); - } - } - - ctx.addContextEnv(JaxWsConstants.ENV_ATTRIBUTE_ENDPOINT_SERVLET_NAME, servletName); - - jaxWsModuleInfo.addEndpointInfo( - servletName, - endpointInfoBuilder.build(ctx, servletClassName, EndpointType.SERVLET) ); - } - } }