From 4a21082642f01b25b2151126ad92aa61913798ef Mon Sep 17 00:00:00 2001 From: Benjamin Confino Date: Mon, 20 Jan 2025 20:38:40 +0000 Subject: [PATCH] add ear libs to annotation scan --- dev/com.ibm.ws.anno_fat/bnd.bnd | 2 +- dev/com.ibm.ws.container.service/bnd.bnd | 4 + .../internal/ModuleAnnotationsImpl.java | 2 +- .../internal/WebAnnotationsImpl.java | 77 +++++++++++++++++++ .../internal/WebFragmentInfoAdapter.java | 54 +++++++++++++ .../config/internal/WebFragmentsInfoImpl.java | 3 +- 6 files changed, 139 insertions(+), 3 deletions(-) create mode 100644 dev/com.ibm.ws.container.service/src/com/ibm/ws/container/service/config/internal/WebFragmentInfoAdapter.java diff --git a/dev/com.ibm.ws.anno_fat/bnd.bnd b/dev/com.ibm.ws.anno_fat/bnd.bnd index bb38359b55eb..d42f67c388dc 100644 --- a/dev/com.ibm.ws.anno_fat/bnd.bnd +++ b/dev/com.ibm.ws.anno_fat/bnd.bnd @@ -31,7 +31,7 @@ src: \ fat.project: true -tested.features: persistencecontainer-3.1, enterprisebeanslite-4.0, cdi-4.0, servlet-6.0 +tested.features: persistencecontainer-3.1, enterprisebeanslite-4.0, cdi-4.0, servlet-6.0, servlet-6.1 -buildpath: \ io.openliberty.org.apache.commons.logging;version=latest,\ diff --git a/dev/com.ibm.ws.container.service/bnd.bnd b/dev/com.ibm.ws.container.service/bnd.bnd index 45469b6a4edd..23ceb8e3eba4 100644 --- a/dev/com.ibm.ws.container.service/bnd.bnd +++ b/dev/com.ibm.ws.container.service/bnd.bnd @@ -125,6 +125,10 @@ Service-Component: \ greedy:=version;\ configuration-policy:=optional; \ properties:="service.vendor=IBM,toType=com.ibm.ws.container.service.config.WebFragmentsInfo", \ + com.ibm.ws.container.service.config.WebFragmentInfoAdapter; \ + implementation:=com.ibm.ws.container.service.config.internal.WebFragmentInfoAdapter; \ + provide:=com.ibm.wsspi.adaptable.module.adapters.ContainerAdapter; \ + properties:="service.vendor=IBM,toType=com.ibm.ws.container.service.config.WebFragmentInfo", \ com.ibm.ws.container.service.metadata.MetaDataService; \ implementation:=com.ibm.ws.container.service.metadata.internal.MetaDataServiceImpl; \ provide:='com.ibm.ws.container.service.metadata.MetaDataService,com.ibm.ws.container.service.metadata.internal.MetaDataServiceImpl,com.ibm.ws.container.service.metadata.extended.MetaDataIdentifierService'; \ diff --git a/dev/com.ibm.ws.container.service/src/com/ibm/ws/container/service/annocache/internal/ModuleAnnotationsImpl.java b/dev/com.ibm.ws.container.service/src/com/ibm/ws/container/service/annocache/internal/ModuleAnnotationsImpl.java index b552a099bd19..25c582562880 100644 --- a/dev/com.ibm.ws.container.service/src/com/ibm/ws/container/service/annocache/internal/ModuleAnnotationsImpl.java +++ b/dev/com.ibm.ws.container.service/src/com/ibm/ws/container/service/annocache/internal/ModuleAnnotationsImpl.java @@ -207,7 +207,7 @@ public ModuleAnnotationsImpl( // - private final ModuleInfo moduleInfo; + protected final ModuleInfo moduleInfo; @Override public ModuleInfo getModuleInfo() { diff --git a/dev/com.ibm.ws.container.service/src/com/ibm/ws/container/service/annocache/internal/WebAnnotationsImpl.java b/dev/com.ibm.ws.container.service/src/com/ibm/ws/container/service/annocache/internal/WebAnnotationsImpl.java index 5284a2ee2a73..b98ee25810ef 100644 --- a/dev/com.ibm.ws.container.service/src/com/ibm/ws/container/service/annocache/internal/WebAnnotationsImpl.java +++ b/dev/com.ibm.ws.container.service/src/com/ibm/ws/container/service/annocache/internal/WebAnnotationsImpl.java @@ -12,21 +12,37 @@ *******************************************************************************/ package com.ibm.ws.container.service.annocache.internal; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; import java.util.HashMap; import java.util.IdentityHashMap; import java.util.List; import java.util.Map; +import com.ibm.ejs.ras.TraceComponent; +import com.ibm.websphere.ras.Tr; +import com.ibm.ws.container.service.annocache.FragmentAnnotations; +import com.ibm.ws.container.service.annocache.WebAnnotations; +import com.ibm.ws.container.service.app.deploy.ApplicationInfo; +import com.ibm.ws.container.service.app.deploy.EARApplicationInfo; +import com.ibm.ws.container.service.app.deploy.WebModuleInfo; +import com.ibm.ws.container.service.config.WebFragmentInfo; +import com.ibm.ws.container.service.config.WebFragmentsInfo; + import com.ibm.wsspi.artifact.ArtifactContainer; import com.ibm.wsspi.artifact.overlay.OverlayContainer; import com.ibm.wsspi.adaptable.module.Container; +import com.ibm.wsspi.adaptable.module.Entry; import com.ibm.wsspi.adaptable.module.UnableToAdaptException; import com.ibm.wsspi.annocache.classsource.ClassSource_Aggregate; import com.ibm.wsspi.annocache.classsource.ClassSource_Aggregate.ScanPolicy; import com.ibm.wsspi.annocache.classsource.ClassSource_Factory; import com.ibm.wsspi.annocache.targets.AnnotationTargets_Targets; +import com.ibm.wsspi.artifact.ArtifactContainer; +import com.ibm.wsspi.artifact.overlay.OverlayContainer; import com.ibm.ws.container.service.app.deploy.WebModuleInfo; import com.ibm.ws.container.service.config.WebFragmentInfo; @@ -82,6 +98,19 @@ */ public class WebAnnotationsImpl extends ModuleAnnotationsImpl implements WebAnnotations { + //TODO discuss this, sysprop / server.xml, name, etc + private final static String SCAN_EAR_LIBS = "com.ibm.ws.anno.ScanEarLibs"; + + @SuppressWarnings("unused") + private static final boolean scanEarLibs = AccessController.doPrivileged(new PrivilegedAction() { + @Override + public Boolean run() { + String propString = System.getProperty(SCAN_EAR_LIBS); + Boolean scanEarLibs = Boolean.valueOf(propString); + return scanEarLibs; + } + }); + public WebAnnotationsImpl( AnnotationsAdapterImpl annotationsAdapter, Container rootContainer, OverlayContainer rootOverlayContainer, @@ -180,6 +209,8 @@ protected void addInternalToClassSource() { if ( classSourceFactory == null ) { return; } + + List earLibs = scanEarLibs ? getEarLibs() : new ArrayList(); // The classes folder is processed as if it were a fragment item. @@ -198,6 +229,9 @@ protected void addInternalToClassSource() { for ( WebFragmentInfo nextFragment : getOrderedItems() ) { String nextUri = nextFragment.getLibraryURI(); Container nextContainer = nextFragment.getFragmentContainer(); + + //Defensive programming to avoid duplicates + earLibs.remove(nextContainer); boolean nextIsMetadataComplete; ScanPolicy nextPolicy; @@ -243,6 +277,21 @@ protected void addInternalToClassSource() { return; // FFDC in 'addContainerClassSource' } } + + //TODO property name, should it be a server.xml property instead, etc. Talk with Tom + if (scanEarLibs) { + try { + for (Container c : earLibs) { + WebFragmentInfo nextFragmentInfo = c.adapt(WebFragmentInfo.class); + String nextPath = putUniquePath(nextFragmentInfo, getContainerPath(c)); + if (!addContainerClassSource(nextPath, c, ClassSource_Aggregate.ScanPolicy.SEED)) { //TODO should this be SEED? + return; // FFDC in 'addContainerClassSource' + } + } + } catch (UnableToAdaptException e) { + //TODO, ask Tom what he wants to happen here + } + } for ( WebFragmentInfo nextFragment : getExcludedItems() ) { String nextUri = nextFragment.getLibraryURI(); @@ -271,6 +320,33 @@ protected void addInternalToClassSource() { } } } + + private List getEarLibs() { + List earLibs = new ArrayList(); + + ApplicationInfo appInfo = this.moduleInfo.getApplicationInfo(); + EARApplicationInfo earAppInfo = null; + + if (appInfo instanceof EARApplicationInfo) { + earAppInfo = (EARApplicationInfo) appInfo; + Container libContainer = earAppInfo.getLibraryDirectoryContainer(); + + for (Entry entry : libContainer) { + if (entry.getName().endsWith(".jar")) { + try { + Container lib = entry.adapt(Container.class); + earLibs.add(lib); + } catch (UnableToAdaptException ex) { + // Not really a jar archive, just a poorly named file + if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) + Tr.debug(tc, "processLibraryJarPersistenceXml: ignoring " + entry.getName(), ex); + } + } + } + } + + return earLibs; + } // @@ -283,3 +359,4 @@ public FragmentAnnotations getFragmentAnnotations(WebFragmentInfo fragment) { return new FragmentAnnotationsImpl( useTargets, getFragmentPath(fragment) ); } } + diff --git a/dev/com.ibm.ws.container.service/src/com/ibm/ws/container/service/config/internal/WebFragmentInfoAdapter.java b/dev/com.ibm.ws.container.service/src/com/ibm/ws/container/service/config/internal/WebFragmentInfoAdapter.java new file mode 100644 index 000000000000..d8b36b5ffc46 --- /dev/null +++ b/dev/com.ibm.ws.container.service/src/com/ibm/ws/container/service/config/internal/WebFragmentInfoAdapter.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2025 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package com.ibm.ws.container.service.config.internal; + +import org.osgi.service.component.annotations.Component; + +import com.ibm.ws.container.service.config.WebFragmentInfo; +import com.ibm.ws.javaee.dd.web.WebFragment; +import com.ibm.wsspi.adaptable.module.Container; +import com.ibm.wsspi.adaptable.module.Entry; +import com.ibm.wsspi.adaptable.module.UnableToAdaptException; +import com.ibm.wsspi.adaptable.module.adapters.ContainerAdapter; +import com.ibm.wsspi.artifact.ArtifactContainer; +import com.ibm.wsspi.artifact.overlay.OverlayContainer; + +@Component +public class WebFragmentInfoAdapter implements ContainerAdapter { + + @Override + public WebFragmentInfo adapt(Container root, OverlayContainer rootOverlay, ArtifactContainer artifactContainer, Container containerToAdapt) throws UnableToAdaptException { + WebFragment fragmment = containerToAdapt.adapt(WebFragment.class); + String path = getPath(containerToAdapt); + WebFragmentsInfoImpl.WebFragmentItemImpl nextFragmentInfo = new WebFragmentsInfoImpl.WebFragmentItemImpl(containerToAdapt, fragmment, path, path, false); + return nextFragmentInfo; + } + + public static String getPath(Container container) throws UnableToAdaptException { + // if ( tc.isDebugEnabled() ) { + // Tr.debug(tc, "getPath Initial [ " + container + " ]"); + // } + StringBuilder pathBuilder = new StringBuilder(); + + Entry entry; + while ((entry = container.adapt(Entry.class)) != null) { // throws UnableToAdaptException + pathBuilder.insert(0, entry.getPath()); + container = entry.getRoot(); + // if ( tc.isDebugEnabled() ) { + // Tr.debug(tc, "getPath Next [ " + container + " ]"); + // } + } + + return pathBuilder.toString(); + } +} diff --git a/dev/com.ibm.ws.container.service/src/com/ibm/ws/container/service/config/internal/WebFragmentsInfoImpl.java b/dev/com.ibm.ws.container.service/src/com/ibm/ws/container/service/config/internal/WebFragmentsInfoImpl.java index 6cd125394115..2fb5e1df572d 100644 --- a/dev/com.ibm.ws.container.service/src/com/ibm/ws/container/service/config/internal/WebFragmentsInfoImpl.java +++ b/dev/com.ibm.ws.container.service/src/com/ibm/ws/container/service/config/internal/WebFragmentsInfoImpl.java @@ -355,7 +355,8 @@ private List absoluteOrderWebFragments(Map