diff --git a/appserver/common/annotation-framework/osgi.bundle b/appserver/common/annotation-framework/osgi.bundle
index 8b97d0499e3..96d1caa39c4 100644
--- a/appserver/common/annotation-framework/osgi.bundle
+++ b/appserver/common/annotation-framework/osgi.bundle
@@ -37,10 +37,12 @@
# only if the new code is made subject to such option by the copyright
# holder.
#
+# Portions Copyright [2025] [Payara Foundation and/or its affiliates]
-exportcontents: \
org.glassfish.apf; \
org.glassfish.apf.context; \
org.glassfish.apf.factory; \
+ org.glassfish.apf.jandex; \
org.glassfish.apf.impl; version=${project.osgi.version}
diff --git a/appserver/common/annotation-framework/pom.xml b/appserver/common/annotation-framework/pom.xml
index a8d46a1137f..45e0000e8f6 100755
--- a/appserver/common/annotation-framework/pom.xml
+++ b/appserver/common/annotation-framework/pom.xml
@@ -106,6 +106,16 @@
common-util
${project.version}
+
+ fish.payara.server.internal.deployment
+ deployment-common
+ ${project.version}
+
+
+ fish.payara.server.internal.core
+ kernel
+ ${project.version}
+
fish.payara.server.internal.common
internal-api
diff --git a/appserver/common/annotation-framework/src/main/java/org/glassfish/apf/impl/JavaEEScanner.java b/appserver/common/annotation-framework/src/main/java/org/glassfish/apf/impl/JavaEEScanner.java
index 79596d8c45f..ef7adebd517 100644
--- a/appserver/common/annotation-framework/src/main/java/org/glassfish/apf/impl/JavaEEScanner.java
+++ b/appserver/common/annotation-framework/src/main/java/org/glassfish/apf/impl/JavaEEScanner.java
@@ -37,7 +37,7 @@
* only if the new code is made subject to such option by the copyright
* holder.
*/
-// Portions Copyright [2018] Payara Foundation and/or affiliates
+// Portions Copyright [2018-2025] Payara Foundation and/or affiliates
/*
* JavaEEScanner.java
@@ -47,8 +47,6 @@
package org.glassfish.apf.impl;
import org.glassfish.apf.ComponentInfo;
-import org.glassfish.hk2.classmodel.reflect.Parser;
-import org.glassfish.hk2.classmodel.reflect.ParsingContext;
import org.glassfish.hk2.classmodel.reflect.Types;
import java.io.File;
@@ -64,24 +62,14 @@ public abstract class JavaEEScanner {
Types types;
public ComponentInfo getComponentInfo(Class componentImpl) {
- return new ComponentDefinition(componentImpl);
+ throw new UnsupportedOperationException("No longer supported");
}
protected void initTypes(File file) throws IOException {
- ParsingContext context = new ParsingContext.Builder().build();
- try (Parser cp = new Parser(context)) {
- cp.parse(file, null);
- try {
- cp.awaitTermination();
- } catch (InterruptedException e) {
- throw new IOException(e);
- }
- types = cp.getContext().getTypes();
- }
+ throw new UnsupportedOperationException("No longer supported");
}
public Types getTypes() {
- return types;
+ throw new UnsupportedOperationException("No longer supported");
}
-
}
diff --git a/appserver/common/annotation-framework/src/main/java/org/glassfish/apf/impl/ProcessingContextImpl.java b/appserver/common/annotation-framework/src/main/java/org/glassfish/apf/impl/ProcessingContextImpl.java
index 40ec5fdb54c..37116e98c67 100644
--- a/appserver/common/annotation-framework/src/main/java/org/glassfish/apf/impl/ProcessingContextImpl.java
+++ b/appserver/common/annotation-framework/src/main/java/org/glassfish/apf/impl/ProcessingContextImpl.java
@@ -53,6 +53,7 @@
*
* @author Jerome ochez
*/
+@Deprecated(forRemoval = true)
class ProcessingContextImpl implements ProcessingContext {
protected AnnotationProcessor processor;
diff --git a/appserver/common/annotation-framework/src/main/java/org/glassfish/apf/jandex/JandexIndexReader.java b/appserver/common/annotation-framework/src/main/java/org/glassfish/apf/jandex/JandexIndexReader.java
new file mode 100644
index 00000000000..1deab4d6f60
--- /dev/null
+++ b/appserver/common/annotation-framework/src/main/java/org/glassfish/apf/jandex/JandexIndexReader.java
@@ -0,0 +1,440 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright (c) [2025] Payara Foundation 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://github.com/payara/Payara/blob/main/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 glassfish/legal/LICENSE.txt.
+ *
+ * GPL Classpath Exception:
+ * The Payara Foundation designates this particular file as subject to the "Classpath"
+ * exception as provided by the Payara Foundation 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.
+ */
+package org.glassfish.apf.jandex;
+
+import com.sun.enterprise.deploy.shared.ArchiveFactory;
+import com.sun.enterprise.deployment.deploy.shared.JarArchive;
+import fish.payara.nucleus.executorservice.PayaraExecutorService;
+import jakarta.annotation.PostConstruct;
+import jakarta.inject.Inject;
+import org.glassfish.apf.impl.AnnotationUtils;
+import org.glassfish.api.admin.ServerEnvironment;
+import org.glassfish.api.deployment.DeploymentContext;
+import org.glassfish.api.deployment.archive.ReadableArchive;
+import org.glassfish.api.event.EventListener;
+import org.glassfish.api.event.Events;
+import org.glassfish.deployment.common.DeploymentProperties;
+import org.glassfish.deployment.common.DeploymentUtils;
+import org.glassfish.internal.deployment.DeploymentTracing;
+import org.glassfish.internal.deployment.JandexIndexer;
+import org.glassfish.internal.deployment.analysis.StructuredDeploymentTracing;
+import org.jboss.jandex.IndexReader;
+import org.jboss.jandex.IndexWriter;
+import org.jboss.jandex.Indexer;
+import org.jvnet.hk2.annotations.Service;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Queue;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.ForkJoinPool;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.function.BiPredicate;
+import java.util.logging.Level;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+import static org.glassfish.internal.deployment.Deployment.DEPLOYMENT_SUCCESS;
+
+@Service
+public class JandexIndexReader implements JandexIndexer, EventListener {
+ private static final String JANDEX_INDEX_METADATA_KEY = JandexIndexer.class.getName() + ".index";
+ private static final Pattern ARCHIVE_EXTENSION_PATTERN = Pattern.compile("\\.(?=\\war$)");
+
+ @Inject
+ ArchiveFactory archiveFactory;
+ @Inject
+ ServerEnvironment serverEnvironment;
+ @Inject
+ Events events;
+ @Inject
+ PayaraExecutorService payaraExecutorService;
+
+ private static final Lock errorsLock = new ReentrantLock();
+ private static final Queue delayedCacheAdditions = new ConcurrentLinkedQueue<>();
+
+ @PostConstruct
+ public void init() {
+ events.register(this);
+ }
+
+ @Override
+ @SuppressWarnings("ResultOfMethodCallIgnored")
+ public void index(DeploymentContext deploymentContext) throws IOException {
+ StructuredDeploymentTracing tracing = StructuredDeploymentTracing.load(deploymentContext);
+ try (var span = tracing.startSpan(DeploymentTracing.AppStage.CLASS_SCANNING, deploymentContext.getSource().getName())) {
+ getCachePath(deploymentContext.getSource().getName(), "none").getParent().toFile().mkdirs();
+
+ if (getIndexMap(deploymentContext) == null) {
+ Map indexMap = new ConcurrentHashMap<>();
+ deploymentContext.addTransientAppMetaData(JANDEX_INDEX_METADATA_KEY, indexMap);
+ indexMap.put(deploymentContext.getSource().getURI().toString(),
+ indexRootArchive(deploymentContext, tracing));
+ if (DeploymentUtils.useWarLibraries(deploymentContext)) {
+ DeploymentUtils.getWarLibraryCache().keySet()
+ .forEach(path -> getOrCreateIndex(deploymentContext, Path.of(path).toUri(), tracing));
+ }
+ indexExternalLibraries(deploymentContext, tracing);
+ }
+ }
+ }
+
+ @Override
+ public void reindex(DeploymentContext deploymentContext) throws IOException {
+ deploymentContext.removeTransientAppMetaData(JANDEX_INDEX_METADATA_KEY);
+ index(deploymentContext);
+ }
+
+ @Override
+ public Index getRootIndex(DeploymentContext deploymentContext) {
+ return getIndexMap(deploymentContext).get(deploymentContext.getSource().getURI().toString());
+ }
+
+ @Override
+ public Map getAllIndexes(DeploymentContext deploymentContext) {
+ return getIndexMap(deploymentContext);
+ }
+
+ @Override
+ public Map getIndexesByURI(DeploymentContext deploymentContext, Collection uris) {
+ Map result = new HashMap<>();
+ uris.forEach(uri -> result.put(uri.toString(), getOrCreateIndex(deploymentContext, uri,
+ StructuredDeploymentTracing.createDisabled(uri.toString()))));
+ return result;
+ }
+
+ @Override
+ public boolean isJakartaEEApplication(DeploymentContext deploymentContext) throws IOException {
+ // Check if the application contains any Jakarta EE specific annotations or classes
+ // TODO: doesn't work with EAR quite yet, root deployment for EARs is wrong
+ return getRootIndex(deploymentContext).getIndex().getKnownClasses().stream()
+ .flatMap(clazz -> clazz.annotations().stream())
+ .anyMatch(annotation -> annotation.name().toString().startsWith("jakarta."));
+ }
+
+ @Override
+ public boolean hasAnyAnnotations(DeploymentContext deploymentContext, List uris, String... annotations) {
+ var indexMap = getIndexMap(deploymentContext);
+ if (indexMap == null) {
+ return false;
+ }
+ for (URI uri : uris) {
+ Index index = indexMap.get(uri.toString());
+ if (index != null) {
+ for (String annotation : annotations) {
+ if (!index.getIndex().getAnnotations(annotation).isEmpty()) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static Map getIndexMap(DeploymentContext deploymentContext) {
+ return deploymentContext.getTransientAppMetaData(JANDEX_INDEX_METADATA_KEY, Map.class);
+ }
+
+ Index getIndexFromArchive(ReadableArchive archive) throws IOException {
+ Index index = readIndex(archive, "META-INF/jandex.idx");
+ if (index == null) {
+ index = readIndex(archive, "WEB-INF/classes/META-INF/jandex.idx");
+ }
+ return index;
+ }
+
+ private Index getOrCreateIndex(DeploymentContext deploymentContext, URI uri, StructuredDeploymentTracing tracing) {
+ if (isEndsWithSlash(uri.toString())) {
+ return getRootIndex(deploymentContext);
+ }
+ Map indexMap = getIndexMap(deploymentContext);
+ return indexMap.computeIfAbsent(uri.toString(), key -> {
+ try {
+ DeploymentUtils.WarLibraryDescriptor descriptor = DeploymentUtils.getWarLibraryCache().get(uri.getPath());
+ return descriptor != null ? descriptor.getIndex() : indexOrGetFromCacheWithSpan(archiveFactory.openArchive(uri), tracing);
+ } catch (IOException | ClassNotFoundException e) {
+ return null;
+ }
+ });
+ }
+
+ private Index indexOrGetFromCacheWithSpan(ReadableArchive archive,
+ StructuredDeploymentTracing tracing) throws IOException, ClassNotFoundException {
+ try (var span = tracing.startSpan(DeploymentTracing.AppStage.CLASS_SCANNING, archive.getName())) {
+ return indexOrGetFromCache(archive);
+ }
+ }
+
+ private static boolean isEndsWithSlash(String path) {
+ return path.endsWith(File.separator) || path.endsWith("/");
+ }
+
+ private Index indexRootArchive(DeploymentContext deploymentContext, StructuredDeploymentTracing tracing) throws IOException {
+ Index index = getIndexFromArchive(deploymentContext.getSource());
+ ArrayList subArchives = new ArrayList<>();
+ if (index == null) {
+ index = indexArchive(deploymentContext.getSource(), subArchives);
+ } else {
+ filterEntries(deploymentContext.getSource(), JandexIndexReader::checkIfSubArchive, subArchives);
+ }
+ indexSubArchives(deploymentContext, deploymentContext.getSource(), subArchives, tracing);
+ return index;
+ }
+
+ private void indexSubArchives(DeploymentContext deploymentContext, ReadableArchive rootArchive,
+ List subArchives, StructuredDeploymentTracing tracing) throws IOException {
+ List> innerJarTasks = new ArrayList<>();
+ StringBuilder errors = new StringBuilder();
+ subArchives.forEach(subArchive -> innerJarTasks.add(
+ () -> indexSubArchive(deploymentContext, rootArchive, subArchive, errors, tracing)));
+ ForkJoinPool.commonPool().invokeAll(innerJarTasks);
+ if (errors.length() > 0) {
+ throw new IOException(errors.toString());
+ }
+ }
+
+ private Index indexArchive(ReadableArchive archive, List innerArchives) throws IOException {
+ Indexer indexer = new Indexer();
+ StringBuilder errors = new StringBuilder();
+
+ filterEntries(archive, (entry, performIndex) -> {
+ try {
+ if (performIndex && entry.endsWith(".class")) {
+ try (InputStream stream = archive.getEntry(entry)) {
+ if (stream != null) {
+ indexer.index(stream);
+ }
+ }
+ }
+ } catch (IOException e) {
+ appendError(archive, entry, errors);
+ }
+ return checkIfSubArchive(entry, performIndex);
+ }, innerArchives);
+
+ if (errors.length() > 0) {
+ throw new IOException(errors.toString());
+ }
+ return new Index(indexer.complete());
+ }
+
+ private static void filterEntries(ReadableArchive archive, BiPredicate filter,
+ List entries) {
+ Set explodedEntries = new HashSet<>();
+ archive.entries().asIterator().forEachRemaining(entry -> {
+ String explodedEntry = toExplodedName(entry);
+ if (explodedEntry != null && archive.isDirectory(explodedEntry)) {
+ explodedEntries.add(explodedEntry);
+ }
+ if (filter.test(entry, !startsWithAny(entry, explodedEntries))) {
+ entries.add(entry);
+ }
+ });
+ }
+
+ private static boolean startsWithAny(String entry, Set explodedEntries) {
+ return explodedEntries.stream().anyMatch(entry::startsWith);
+ }
+
+ private static String toExplodedName(String entry) {
+ Matcher matcher = ARCHIVE_EXTENSION_PATTERN.matcher(entry);
+ return matcher.find() ? matcher.replaceAll("_") : null;
+ }
+
+ private static boolean checkIfSubArchive(String entry, boolean doit) {
+ return ARCHIVE_EXTENSION_PATTERN.matcher(entry).find();
+ }
+
+ private Void indexSubArchive(DeploymentContext context, ReadableArchive archive,
+ String entry, StringBuilder errors, StructuredDeploymentTracing tracing) {
+ try (ReadableArchive subArchive = archive.getSubArchive(entry);
+ var span = subArchive != null
+ ? tracing.startSpan(DeploymentTracing.AppStage.CLASS_SCANNING, subArchive.getName()) : null) {
+ if (subArchive != null) {
+ Index index = indexOrGetFromCache(subArchive);
+ getIndexMap(context).put(subArchive.getURI().toString(), index);
+ }
+ } catch (IOException | ClassNotFoundException e) {
+ appendError(archive, entry, errors);
+ }
+ return null;
+ }
+
+ private Index indexOrGetFromCache(ReadableArchive subArchive) throws IOException, ClassNotFoundException {
+ String subArchivePath = subArchive.getURI().getPath();
+ Index index = getIndexFromArchive(subArchive);
+ if (index == null) {
+ index = getCachedIndex(subArchive);
+ }
+ if (index == null) {
+ List innerArchives = new ArrayList<>();
+ index = indexArchive(subArchive, innerArchives);
+ if (!subArchivePath.endsWith("-SNAPSHOT.jar")
+ && !subArchivePath.endsWith("-SNAPSHOT-tests.jar")
+ && !isEndsWithSlash(subArchivePath)) {
+ var finalIndex = index;
+ var archiveName = subArchive.getName();
+ var archiveSize = subArchive.getArchiveSize();
+ var archiveChecksum = getChecksum(subArchive);
+ delayedCacheAdditions.offer(() -> cacheIndex(archiveName, archiveSize, archiveChecksum, finalIndex));
+ }
+ }
+ return index;
+ }
+
+ private static void appendError(ReadableArchive archive, String entry, StringBuilder errors) {
+ errorsLock.lock();
+ try {
+ if (errors.length() == 0) {
+ errors.append(String.format("Unable to index %s from archive %s ", entry, archive.getName()));
+ }
+ } finally {
+ errorsLock.unlock();
+ }
+ }
+
+ private Index getCachedIndex(ReadableArchive archive) throws IOException, ClassNotFoundException {
+ if (!getCachePath(archive.getName(), "idx").toFile().exists()) {
+ return null;
+ }
+ try (var stream = new GZIPInputStream(Files.newInputStream(getCachePath(archive.getName(),"idx")))) {
+ var objectInputStream = new ObjectInputStream(stream);
+ long archiveSize = objectInputStream.readLong();
+ long archiveChecksum = objectInputStream.readLong();
+ if (archiveSize != archive.getArchiveSize() || archiveChecksum != getChecksum(archive)) {
+ return null;
+ }
+ Index index = (Index) objectInputStream.readObject();
+ index.setIndex(new IndexReader(stream).read());
+ return index;
+ }
+ }
+
+ private void cacheIndex(String archiveName, long archiveSize, long archiveChecksum, Index index) {
+ try (var stream = new GZIPOutputStream(Files.newOutputStream(getCachePath(archiveName, "idx")))) {
+ var objectOutputStream = new ObjectOutputStream(stream);
+ objectOutputStream.writeLong(archiveSize);
+ objectOutputStream.writeLong(archiveChecksum);
+ objectOutputStream.writeObject(index);
+ IndexWriter indexWriter = new IndexWriter(stream);
+ indexWriter.write(index.getIndex());
+ } catch (IOException e) {
+ AnnotationUtils.getLogger().log(Level.WARNING, e, () -> "Failed to cache Jandex index for " + archiveName);
+ }
+ }
+
+ private long getChecksum(ReadableArchive archive) {
+ long crc = 0;
+ if (archive instanceof JarArchive) {
+ var jarArchive = (JarArchive) archive;
+ crc = jarArchive.getArchiveCrc();
+ }
+ return crc;
+ }
+
+ private Path getCachePath(String archiveName, String suffix) {
+ return Path.of(serverEnvironment.getInstanceRoot() + "/jandex-cache/" + archiveName + "." + suffix);
+ }
+
+ private Index readIndex(ReadableArchive archive, String path) throws IOException {
+ try (InputStream stream = archive.getEntry(path)) {
+ if (stream != null) {
+ return new Index(new IndexReader(stream).read());
+ }
+ }
+ return null;
+ }
+
+ private void indexExternalLibraries(DeploymentContext deploymentContext,
+ StructuredDeploymentTracing tracing) throws IOException {
+ boolean skipScanExternalLibProp = Boolean.valueOf(deploymentContext.getAppProps()
+ .getProperty(DeploymentProperties.SKIP_SCAN_EXTERNAL_LIB));
+ for (URI externalLib : getExternalLibraries(skipScanExternalLibProp, deploymentContext)) {
+ getOrCreateIndex(deploymentContext, externalLib, tracing);
+ }
+ }
+
+ private List getExternalLibraries(boolean skipScanExternalLibProp,
+ DeploymentContext deploymentContext) {
+ if (skipScanExternalLibProp) {
+ // if we skip scanning external libraries, we should just
+ // return an empty list here
+ return Collections.emptyList();
+ }
+ try {
+ return Stream.concat(DeploymentUtils.getExternalLibraries(deploymentContext.getSource()).stream(),
+ deploymentContext.getAppLibs().stream()).collect(Collectors.toList());
+ } catch (URISyntaxException e) {
+ AnnotationUtils.getLogger().log(Level.WARNING, e, () -> "Failed to get external libraries");
+ return Collections.emptyList();
+ }
+ }
+
+ @Override
+ public void event(Event> event) {
+ if (event.is(DEPLOYMENT_SUCCESS)) {
+ // drain the queue of delayed cache additions
+ while (!delayedCacheAdditions.isEmpty()) {
+ payaraExecutorService.submit(delayedCacheAdditions.poll());
+ }
+ }
+ }
+}
diff --git a/appserver/deployment/dol/pom.xml b/appserver/deployment/dol/pom.xml
index 4a07d0e5488..cc009fae189 100755
--- a/appserver/deployment/dol/pom.xml
+++ b/appserver/deployment/dol/pom.xml
@@ -182,5 +182,10 @@
${project.version}
jar
+
+ fish.payara.server.internal.common
+ internal-api
+ ${project.version}
+
diff --git a/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/annotation/context/EjbBundleContext.java b/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/annotation/context/EjbBundleContext.java
index 98efead7a71..5a9c241a46c 100644
--- a/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/annotation/context/EjbBundleContext.java
+++ b/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/annotation/context/EjbBundleContext.java
@@ -79,8 +79,11 @@ public EjbBundleDescriptor getDescriptor() {
* Return null if corresponding descriptor is not found.
*/
public AnnotatedElementHandler createContextForEjb() {
- Class ejbClass = (Class)this.getProcessingContext().getProcessor(
- ).getLastAnnotatedElement(ElementType.TYPE);
+ Class ejbClass = null;
+ if (getProcessingContext().getProcessor() != null) {
+ ejbClass = (Class) this.getProcessingContext().getProcessor(
+ ).getLastAnnotatedElement(ElementType.TYPE);
+ }
EjbDescriptor[] ejbDescs = null;
String ejbClassName = null;
if (ejbClass != null) {
@@ -137,13 +140,16 @@ public ServiceReferenceContainer[] getServiceRefContainers() {
* Return null if corresponding descriptor is not found.
*/
public AnnotatedElementHandler createContextForEjbInterceptor() {
+ EjbInterceptor ejbInterceptor = null;
+ if (getProcessingContext().getProcessor() != null) {
Class interceptorClass =
(Class)this.getProcessingContext().getProcessor(
).getLastAnnotatedElement(ElementType.TYPE);
- EjbInterceptor ejbInterceptor =
+ ejbInterceptor =
this.getDescriptor().getInterceptorByClassName(
interceptorClass.getName());
-
+ }
+
AnnotatedElementHandler aeHandler = null;
if (ejbInterceptor != null) {
aeHandler = new EjbInterceptorContext(ejbInterceptor);
diff --git a/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/annotation/factory/AnnotationProcessingContext.java b/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/annotation/factory/AnnotationProcessingContext.java
new file mode 100644
index 00000000000..dd7bdb95697
--- /dev/null
+++ b/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/annotation/factory/AnnotationProcessingContext.java
@@ -0,0 +1,76 @@
+package com.sun.enterprise.deployment.annotation.factory;
+
+import org.glassfish.apf.AnnotatedElementHandler;
+import org.glassfish.apf.AnnotationProcessor;
+import org.glassfish.apf.ErrorHandler;
+import org.glassfish.apf.ProcessingContext;
+import org.glassfish.apf.Scanner;
+import org.glassfish.api.deployment.archive.ReadableArchive;
+
+class AnnotationProcessingContext implements ProcessingContext {
+ private final AnnotatedElementHandler handler;
+ private final ReadableArchive archive;
+ private final AnnotationProcessor processor = new JandexAnnotationProcessor();
+
+ AnnotationProcessingContext(AnnotatedElementHandler handler, ReadableArchive archive) {
+ this.handler = handler;
+ this.archive = archive;
+ }
+
+ @Override
+ public AnnotationProcessor getProcessor() {
+ return processor;
+ }
+
+ @Override
+ public Scanner getProcessingInput() {
+ return null;
+ }
+
+ @Override
+ public ReadableArchive getArchive() {
+ return archive;
+ }
+
+ @Override
+ public void setArchive(ReadableArchive archive) {
+ throw new UnsupportedOperationException("Not supported.");
+ }
+
+ @Override
+ public void setProcessingInput(Scanner scanner) {
+ throw new UnsupportedOperationException("Not supported.");
+ }
+
+ @Override
+ @Deprecated(forRemoval = true)
+ public void pushHandler(AnnotatedElementHandler handler) {
+ // no-op
+ }
+
+ @Override
+ public AnnotatedElementHandler getHandler() {
+ return handler;
+ }
+
+ @Override
+ @Deprecated(forRemoval = true)
+ public AnnotatedElementHandler popHandler() {
+ return handler;
+ }
+
+ @Override
+ public U getHandler(Class handlerType) throws ClassCastException {
+ return handlerType.cast(handler);
+ }
+
+ @Override
+ public void setErrorHandler(ErrorHandler errorHandler) {
+ throw new UnsupportedOperationException("Not supported.");
+ }
+
+ @Override
+ public ErrorHandler getErrorHandler() {
+ return null;
+ }
+}
diff --git a/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/annotation/factory/JandexAnnotationProcessor.java b/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/annotation/factory/JandexAnnotationProcessor.java
new file mode 100644
index 00000000000..c1eecd8be4a
--- /dev/null
+++ b/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/annotation/factory/JandexAnnotationProcessor.java
@@ -0,0 +1,62 @@
+package com.sun.enterprise.deployment.annotation.factory;
+
+import org.glassfish.apf.AnnotationHandler;
+import org.glassfish.apf.AnnotationInfo;
+import org.glassfish.apf.AnnotationProcessorException;
+import org.glassfish.apf.ProcessingContext;
+import org.glassfish.apf.ProcessingResult;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.reflect.AnnotatedElement;
+import java.util.logging.Level;
+
+public class JandexAnnotationProcessor implements org.glassfish.apf.AnnotationProcessor {
+ private Class> type;
+
+ @Override
+ public ProcessingContext createContext() {
+ throw new UnsupportedOperationException("Not supported.");
+ }
+
+ @Override
+ public ProcessingResult process(ProcessingContext ctx) throws AnnotationProcessorException {
+ throw new UnsupportedOperationException("Not supported.");
+ }
+
+ @Override
+ public ProcessingResult process(ProcessingContext ctx, Class[] classes) throws AnnotationProcessorException {
+ if (classes.length != 1) {
+ throw new IllegalArgumentException("Only one class is supported.");
+ }
+ this.type = classes[0];
+ return null;
+ }
+
+ @Override
+ public void pushAnnotationHandler(AnnotationHandler handler) {
+ throw new UnsupportedOperationException("Not supported.");
+ }
+
+ @Override
+ public AnnotationHandler getAnnotationHandler(Class extends Annotation> type) {
+ throw new UnsupportedOperationException("Not supported.");
+ }
+
+ @Override
+ public void popAnnotationHandler(Class extends Annotation> type) {
+ throw new UnsupportedOperationException("Not supported.");
+ }
+
+ @Override
+ public AnnotatedElement getLastAnnotatedElement(ElementType type) {
+ if (type != ElementType.TYPE) {
+ throw new IllegalArgumentException("Only ElementType.TYPE is supported.");
+ }
+ return this.type;
+ }
+
+ @Override
+ public void log(Level level, AnnotationInfo locator, String localizedMessage) {
+ throw new UnsupportedOperationException("Not supported.");
+ }
+}
diff --git a/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/annotation/factory/SJSASFactory.java b/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/annotation/factory/SJSASFactory.java
index 086dac290f2..e6a8e006f4f 100644
--- a/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/annotation/factory/SJSASFactory.java
+++ b/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/annotation/factory/SJSASFactory.java
@@ -37,6 +37,7 @@
* only if the new code is made subject to such option by the copyright
* holder.
*/
+// Portions Copyright [2025] [Payara Foundation and/or its affiliates]
package com.sun.enterprise.deployment.annotation.factory;
@@ -45,66 +46,214 @@
import org.glassfish.apf.AnnotationProcessor;
import org.glassfish.apf.AnnotationProcessorException;
import org.glassfish.apf.HandlerProcessingResult;
+import org.glassfish.apf.context.AnnotationContext;
import org.glassfish.apf.factory.Factory;
-import org.glassfish.apf.impl.AnnotationProcessorImpl;
+import org.glassfish.apf.impl.AnnotationUtils;
+import org.glassfish.api.deployment.DeploymentContext;
+import org.glassfish.api.deployment.archive.ReadableArchive;
+import org.glassfish.deployment.common.RootDeploymentDescriptor;
import org.glassfish.hk2.api.ActiveDescriptor;
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.hk2.utilities.BuilderHelper;
+import org.glassfish.internal.deployment.JandexIndexer;
+import org.glassfish.internal.deployment.JandexIndexer.Index;
+import org.jboss.jandex.AnnotationInstance;
import org.jvnet.hk2.annotations.Service;
import jakarta.annotation.PostConstruct;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
+import java.io.File;
+import java.io.IOException;
import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.reflect.AnnotatedElement;
+import java.net.URI;
+import java.nio.file.Files;
+import java.util.Collections;
import java.util.HashSet;
+import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
/**
* This factory is responsible for initializing a ready to use
- * AnnotationProcessor.
+ * JandexAnnotationProcessor.
*
* @author Shing Wai Chan
*/
@Service
@Singleton
public class SJSASFactory extends Factory {
+ private static final Logger logger = AnnotationUtils.getLogger();
@Inject
private ServiceLocator locator;
+ @Inject
+ JandexIndexer jandexIndexer;
- private final Set annotationClassNames = new HashSet<>();
- private final Set annotationClassNamesMetaDataComplete = new HashSet<>();
-
- // we have two system processors to process annotations:
- // one to process all JavaEE annotations when metadata-complete is false,
- // another to process a subset of JavaEE annotations when
- // metadata-complete is true
- private AnnotationProcessorImpl systemProcessor=null;
- private AnnotationProcessorImpl systemProcessorMetaDataComplete=null;
+ private final Map annotationHandlers = new ConcurrentHashMap<>();
+ @Deprecated(forRemoval = true)
public AnnotationProcessor getAnnotationProcessor(boolean isMetaDataComplete) {
- AnnotationProcessorImpl processor =
- Factory.getDefaultAnnotationProcessor();
- if (!isMetaDataComplete) {
- processor.setDelegate(systemProcessor);
- } else {
- processor.setDelegate(systemProcessorMetaDataComplete);
- }
- return processor;
+ throw new UnsupportedOperationException("This method is deprecated and should not be used");
}
- @SuppressWarnings("unchecked")
+ @Deprecated(forRemoval = true)
public Set getAnnotations(boolean isMetaDataComplete) {
- if (!isMetaDataComplete) {
- return (Set)((HashSet)annotationClassNames).clone();
- } else {
- return (Set)((HashSet)annotationClassNamesMetaDataComplete).clone();
+ throw new UnsupportedOperationException("This method is deprecated and should not be used");
+ }
+
+ public void processAnnotations(DeploymentContext deploymentContext, RootDeploymentDescriptor bundleDesc,
+ ReadableArchive archive) throws IOException {
+ if (checkAlreadyProcessed(deploymentContext, bundleDesc)) {
+ return;
+ }
+
+ String archiveURI = bundleDesc.getModuleDescriptor().getArchiveUri();
+ if (archiveURI == null) {
+ archiveURI = bundleDesc.getName();
+ }
+ Index index = jandexIndexer.getAllIndexes(deploymentContext)
+ .get(new File(archiveURI).toURI().toString());
+ if (index == null) {
+ File file = new File(archiveURI);
+ URI uri = file.toURI();
+ if (file.isDirectory()) {
+ // TODO: assuming there is only one file in the directory
+ // exploded WAR support for EAR
+ uri = Files.list(file.toPath()).filter(path -> path.toString().endsWith("ar")).findAny().get().toUri();
+ }
+ index = jandexIndexer.getIndexesByURI(deploymentContext, Collections.singleton(uri)).values().stream().findAny().get();
+ }
+ AnnotationProcessingContext processingContext = new AnnotationProcessingContext(
+ AnnotatedElementHandlerFactory.createAnnotatedElementHandler(bundleDesc), archive);
+ Set annotationInstances = new HashSet<>();
+ for (Map.Entry entry : annotationHandlers.entrySet()) {
+ Class extends Annotation> annotationClass = entry.getValue().getAnnotationType();
+ index.getIndex().getAnnotations(entry.getKey()).forEach(annotationInstance -> {
+ if (annotationInstances.add(annotationInstance)) {
+ try {
+ Class> cls = deploymentContext.getClassLoader().loadClass(mapAnnotationToClassName(annotationInstance));
+ logger.fine("Processing annotation: " + annotationInstance + " on class: " + cls
+ + " bundleDesc: " + bundleDesc.getName() + " of type: " + bundleDesc.getClass()
+ + " with id: " + System.identityHashCode(bundleDesc));
+ processingContext.getProcessor().process(processingContext, new Class>[] { cls });
+ ((AnnotationContext) processingContext.getHandler()).setProcessingContext(processingContext);
+ AnnotatedElement element = mapAnnotationToElement(cls, annotationInstance);
+ AnnotationInfo annotationInfo = new AnnotationInfo(processingContext,
+ element, element.getAnnotation(annotationClass), mapAnnotationToElementType(annotationInstance));
+ entry.getValue().processAnnotation(annotationInfo);
+ } catch (AnnotationProcessorException | ReflectiveOperationException e) {
+ throw new IllegalStateException(e);
+ } finally {
+ try {
+ processingContext.getProcessor().process(processingContext, new Class>[] { null });
+ ((AnnotationContext) processingContext.getHandler()).setProcessingContext(null);
+ } catch (AnnotationProcessorException e) {
+ logger.log(Level.FINE, "Error processing annotation", e);
+ }
+ }
+ }
+ });
}
}
-
+
+ private boolean checkAlreadyProcessed(DeploymentContext deploymentContext, RootDeploymentDescriptor bundleDescriptor) {
+ @SuppressWarnings("unchecked")
+ Set alreadyProcessed =
+ deploymentContext.getTransientAppMetaData("alreadyProcessedAnnotations", Set.class);
+ if (alreadyProcessed == null) {
+ alreadyProcessed = Collections.newSetFromMap(new IdentityHashMap<>());
+ deploymentContext.addTransientAppMetaData("alreadyProcessedAnnotations", alreadyProcessed);
+ }
+ return !alreadyProcessed.add(bundleDescriptor);
+ }
+
+ /**
+ * *** TODO: duplicate from weld-gf-connector
+ * @param annotationInstance
+ * @return
+ */
+ private static String mapAnnotationToClassName(AnnotationInstance annotationInstance) {
+ String className = null;
+ switch (annotationInstance.target().kind()) {
+ case CLASS:
+ className = annotationInstance.target().asClass().name().toString();
+ break;
+ case FIELD:
+ className = annotationInstance.target().asField().declaringClass().name().toString();
+ break;
+ case METHOD:
+ className = annotationInstance.target().asMethod().receiverType().name().toString();
+ break;
+ case METHOD_PARAMETER:
+ className = annotationInstance.target().asMethodParameter().method().receiverType().name().toString();
+ break;
+ case TYPE:
+ className = annotationInstance.target().asType().asClass().toString();
+ break;
+ case RECORD_COMPONENT:
+ className = annotationInstance.target().asRecordComponent().declaringClass().name().toString();
+ break;
+ }
+ return className;
+ }
+
+ private static AnnotatedElement mapAnnotationToElement(Class> cls, AnnotationInstance annotationInstance)
+ throws ReflectiveOperationException {
+ AnnotatedElement element = null;
+ switch (annotationInstance.target().kind()) {
+ case CLASS:
+ case TYPE:
+ element = cls;
+ break;
+ case FIELD:
+ element = cls.getDeclaredField(annotationInstance.target().asField().name());
+ break;
+ case METHOD:
+ int parametersCount = annotationInstance.target().asMethod().parametersCount();
+ if (annotationInstance.target().asMethod().parametersCount() == 0) {
+ element = cls.getDeclaredMethod(annotationInstance.target().asMethod().name());
+ } else {
+ var parameters = new Class[parametersCount];
+ for (int count = 0; count < parametersCount; count++) {
+ parameters[count] = cls.getClassLoader().loadClass(annotationInstance.target()
+ .asMethod().parameterType(count).name().toString());
+ }
+ element = cls.getDeclaredMethod(annotationInstance.target().asMethod().name(), parameters);
+ }
+ break;
+ case RECORD_COMPONENT:
+ element = cls.getDeclaredField(annotationInstance.target().asRecordComponent().name());
+ break;
+ case METHOD_PARAMETER:
+ throw new UnsupportedOperationException("Method parameter not supported");
+ }
+ return element;
+ }
+
+ private static ElementType mapAnnotationToElementType(AnnotationInstance annotationInstance) {
+ switch (annotationInstance.target().kind()) {
+ case CLASS:
+ case TYPE:
+ return ElementType.TYPE;
+ case FIELD:
+ return ElementType.FIELD;
+ case METHOD:
+ return ElementType.METHOD;
+ case METHOD_PARAMETER:
+ return ElementType.PARAMETER;
+ default:
+ throw new IllegalArgumentException("Unsupported target kind: " + annotationInstance.target().kind());
+ }
+ }
+
private static String getAnnotationHandlerForStringValue(ActiveDescriptor onMe) {
Map> metadata = onMe.getMetadata();
List answers = metadata.get(AnnotationHandler.ANNOTATION_HANDLER_METADATA);
@@ -116,31 +265,14 @@ private static String getAnnotationHandlerForStringValue(ActiveDescriptor i : locator.getDescriptors(BuilderHelper.createContractFilter(
AnnotationHandler.class.getName()))) {
ActiveDescriptor descriptor = (ActiveDescriptor) i;
String annotationTypeName = getAnnotationHandlerForStringValue(descriptor);
if (annotationTypeName == null) continue;
-
- systemProcessor.pushAnnotationHandler(annotationTypeName, new LazyAnnotationHandler(descriptor));
- annotationClassNames.add("L" + annotationTypeName.replace('.', '/') + ";");
-
- // In the current set of the annotations processed by the
- // deployment layer, the only annotation that should be
- // processed even when metadata-complete atribute value is true
- // is jakarta.annotation.ManagedBean. If there are more annotations
- // falling in this category in the future, add them to this list
- if (annotationTypeName.equals("jakarta.annotation.ManagedBean")) {
- systemProcessorMetaDataComplete.pushAnnotationHandler(annotationTypeName, new LazyAnnotationHandler(descriptor));
- annotationClassNamesMetaDataComplete.add("L" + annotationTypeName.replace('.', '/') + ";");
- }
+
+ annotationHandlers.put(annotationTypeName, new LazyAnnotationHandler(descriptor));
}
}
@@ -174,6 +306,5 @@ public HandlerProcessingResult processAnnotation(
public Class extends Annotation>[] getTypeDependencies() {
return getHandler().getTypeDependencies();
}
-
}
}
diff --git a/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/annotation/handlers/AbstractHandler.java b/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/annotation/handlers/AbstractHandler.java
index 54a948a91c6..f3a9edaa19d 100644
--- a/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/annotation/handlers/AbstractHandler.java
+++ b/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/annotation/handlers/AbstractHandler.java
@@ -139,21 +139,7 @@ protected HandlerProcessingResult getInvalidAnnotatedElementHandlerResult(
*/
protected void log(Level level, AnnotationInfo ainfo,
String localizedMessage) throws AnnotationProcessorException {
- if (Level.SEVERE.equals(level)) {
- ainfo.getProcessingContext().getErrorHandler().error(
- new AnnotationProcessorException(localizedMessage, ainfo));
- } else if (Level.WARNING.equals(level)) {
- ainfo.getProcessingContext().getErrorHandler().warning(
- new AnnotationProcessorException(localizedMessage, ainfo));
- } else if (Level.FINE.equals(level)) {
- ainfo.getProcessingContext().getErrorHandler().fine(
- new AnnotationProcessorException(localizedMessage, ainfo));
- } else if (ainfo != null) {
- ainfo.getProcessingContext().getProcessor().log(
- level, ainfo, localizedMessage);
- } else {
- logger.log(level, localizedMessage);
- }
+ logger.log(level, localizedMessage);
}
protected String getInjectionMethodPropertyName(Method method,
diff --git a/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/annotation/impl/ModuleScanner.java b/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/annotation/impl/ModuleScanner.java
index c7268b3be16..58cf41a1391 100644
--- a/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/annotation/impl/ModuleScanner.java
+++ b/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/annotation/impl/ModuleScanner.java
@@ -37,7 +37,7 @@
* only if the new code is made subject to such option by the copyright
* holder.
*/
-// Portions Copyright [2016-2021] [Payara Foundation and/or its affiliates.]
+// Portions Copyright [2016-2025] [Payara Foundation and/or its affiliates.]
package com.sun.enterprise.deployment.annotation.impl;
@@ -74,22 +74,10 @@ public abstract class ModuleScanner extends JavaEEScanner implements Scanner<
private static final int DEFAULT_ENTRY_BUFFER_SIZE = 8192;
- @Inject
- DefaultAnnotationScanner defaultScanner;
-
protected File archiveFile = null;
protected ClassLoader classLoader = null;
protected Parser classParser = null;
- private Set scannedURI = new HashSet<>();
-
- private boolean needScanAnnotation = false;
-
- @Inject
- PayaraExecutorService executorService;
-
- private Set entries = new HashSet<>();
-
public static final Logger deplLogger = com.sun.enterprise.deployment.util.DOLUtils.deplLogger;
@LogMessageInfo(message = "Exception caught during annotation scanning.", cause="An exception was caught that indicates that the annotation is incorrect.", action="Correct the annotation.", level="SEVERE")
@@ -121,11 +109,7 @@ public abstract class ModuleScanner extends JavaEEScanner implements Scanner<
public void process(ReadableArchive archiveFile,
T bundleDesc, ClassLoader classLoader, Parser parser) throws IOException {
- File file = new File(archiveFile.getURI());
- setParser(parser);
- process(file, bundleDesc, classLoader);
- completeProcess(bundleDesc, archiveFile);
- calculateResults(bundleDesc);
+ throw new UnsupportedOperationException("No longer supported.");
}
/**
@@ -144,79 +128,7 @@ protected void completeProcess(T bundleDescr, ReadableArchive archive) throws IO
}
protected void calculateResults(T bundleDesc) {
- try {
- classParser.awaitTermination();
- } catch (InterruptedException e) {
- deplLogger.log(Level.SEVERE,
- ANNOTATION_SCANNING_EXCEPTION,
- e);
- return;
- }
- Level logLevel = (System.getProperty("glassfish.deployment.dump.scanning")!=null?Level.INFO:Level.FINE);
- boolean shouldLog = deplLogger.isLoggable(logLevel);
- ParsingContext context = classParser.getContext();
- boolean isFullAttribute = false;
- if (bundleDesc instanceof BundleDescriptor) {
- isFullAttribute = ((BundleDescriptor)bundleDesc).isFullAttribute();
- }
- Set annotationsToProcess = defaultScanner.getAnnotations(isFullAttribute);
- for (String annotation: annotationsToProcess) {
- Type type = context.getTypes().getBy(annotation);
-
- // we never found anyone using that type
- if (type==null) continue;
-
- // is it an annotation
- if (type instanceof AnnotationType) {
- AnnotationType at = (AnnotationType) type;
- for (AnnotatedElement ae : at.allAnnotatedTypes()) {
- // if it is a member (field, method), let's retrieve the declaring type
- // otherwise, use the annotated type directly.
- Type t = (ae instanceof Member?((Member) ae).getDeclaringType():(Type) ae);
- if (t.wasDefinedIn(scannedURI)) {
- if (shouldLog) {
- if (Level.INFO.equals(logLevel)) {
- deplLogger.log(Level.INFO,
- ANNOTATION_ADDED,
- new Object[] { t.getName(),
- ae.getName(),
- at.getName() });
- } else {
- deplLogger.log(Level.FINE, "Adding {0} since {1} is annotated with {2}", new Object[]{t.getName(), ae.getName(), at.getName()});
- }
- }
- entries.add(t.getName());
- }
- }
-
- } else
- // or is it an interface ?
- if (type instanceof InterfaceModel) {
- InterfaceModel im = (InterfaceModel) type;
- for (ClassModel cm : im.allImplementations()) {
- if (shouldLog) {
- if (Level.INFO.equals(logLevel)) {
- deplLogger.log(Level.INFO,
- INTERFACE_ADDED,
- new Object[] { cm.getName(),
- im.getName() });
- } else {
- deplLogger.log(Level.FINE, "Adding {0} since it is implementing {1}", new Object[]{cm.getName(), im.getName()});
- }
- }
- entries.add(cm.getName());
- }
- } else {
- deplLogger.log(Level.SEVERE,
- INCORRECT_ANNOTATION,
- annotation);
- }
- }
- if (deplLogger.isLoggable(Level.FINE)) {
- deplLogger.log(Level.FINE,
- "Done with results");
- }
-
+ throw new UnsupportedOperationException("No longer supported.");
}
/**
@@ -224,8 +136,7 @@ protected void calculateResults(T bundleDesc) {
* @param className
*/
protected void addScanClassName(String className) {
- if (className!=null && className.length()!=0)
- entries.add(className);
+ throw new UnsupportedOperationException("No longer supported.");
}
/**
@@ -233,24 +144,7 @@ protected void addScanClassName(String className) {
* @param jarFile
*/
protected void addScanJar(File jarFile) throws IOException {
- try {
- /*
- * An app might refer to a non-existent JAR in its Class-Path. Java
- * SE accepts that silently, and so will GlassFish.
- */
- if ( ! jarFile.exists()) {
- return;
- }
- scannedURI.add(jarFile.toURI());
- if (needScanAnnotation) {
- classParser.parse(jarFile, null);
- }
- } catch (ZipException ze) {
- deplLogger.log(Level.WARNING,
- JAR_EXCEPTION,
- new Object[] { ze.getMessage(),
- jarFile.getPath() });
- }
+ throw new UnsupportedOperationException("No longer supported.");
}
/**
@@ -266,10 +160,7 @@ protected void addScanURI(final URI jarURI) throws IOException {
* @param directory
*/
protected void addScanDirectory(File directory) throws IOException {
- scannedURI.add(directory.toURI());
- if (needScanAnnotation) {
- classParser.parse(directory, null);
- }
+ throw new UnsupportedOperationException("No longer supported.");
}
@Override
@@ -279,38 +170,12 @@ public ClassLoader getClassLoader() {
@Override
public Set getElements() {
- return getElements(entries);
+ throw new UnsupportedOperationException("No longer supported.");
}
@Override
public Set getElements(Set classNames) {
- Set elements = new HashSet<>();
- if (getClassLoader() == null) {
- deplLogger.log(Level.SEVERE,
- NO_CLASSLOADER);
- return elements;
- }
-
- for (String className : classNames) {
- if (deplLogger.isLoggable(Level.FINE)) {
- deplLogger.log(Level.FINE, "Getting {0}", className);
- }
- try {
- elements.add(classLoader.loadClass(className));
- } catch (NoClassDefFoundError err) {
- deplLogger.log(Level.WARNING,
- ANNOTATION_ERROR,
- err);
- } catch(ClassNotFoundException cnfe) {
- LogRecord lr = new LogRecord(Level.WARNING, CLASSLOADING_ERROR);
- Object args[] = { className,
- cnfe.getMessage() };
- lr.setParameters(args);
- lr.setThrown(cnfe);
- deplLogger.log(lr);
- }
- }
- return elements;
+ throw new UnsupportedOperationException("No longer supported.");
}
/**
@@ -320,43 +185,15 @@ public Set getElements(Set classNames) {
*/
protected void addLibraryJars(T bundleDesc,
ReadableArchive moduleArchive) {
- List libraryURIs = new ArrayList<>();
- try {
- if (bundleDesc instanceof BundleDescriptor) {
- libraryURIs = DOLUtils.getLibraryJarURIs((BundleDescriptor)bundleDesc, moduleArchive);
- }
-
- for (URI uri : libraryURIs) {
- File libFile = new File(uri);
- if (libFile.isFile()) {
- addScanJar(libFile);
- } else if (libFile.isDirectory()) {
- addScanDirectory(libFile);
- }
- }
- } catch (Exception ex) {
- // we log a warning and proceed for any problems in
- // adding library jars to the scan list
- deplLogger.log(Level.WARNING,
- LIBRARY_JAR_ERROR,
- ex.getMessage());
- }
+ throw new UnsupportedOperationException("No longer supported.");
}
@Override
public Types getTypes() {
- return classParser.getContext().getTypes();
+ throw new UnsupportedOperationException("No longer supported.");
}
protected void setParser(Parser parser) {
- if (parser == null) {
- // if the passed in parser is null, it means no annotation scanning
- // has been done yet, we need to construct a new parser
- // and do the annotation scanning here
- ParsingContext pc = new ParsingContext.Builder().logger(deplLogger).executorService(executorService.getUnderlyingExecutorService()).build();
- parser = new Parser(pc);
- needScanAnnotation = true;
- }
- classParser = parser;
+ throw new UnsupportedOperationException("No longer supported.");
}
}
diff --git a/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/Archivist.java b/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/Archivist.java
index e9d7b1c8d7a..fb2eaa17120 100644
--- a/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/Archivist.java
+++ b/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/Archivist.java
@@ -37,13 +37,13 @@
* only if the new code is made subject to such option by the copyright
* holder.
*/
-// Portions Copyright [2020-2024] [Payara Foundation and/or its affiliates.]
+// Portions Copyright [2020-2025] [Payara Foundation and/or its affiliates.]
package com.sun.enterprise.deployment.archivist;
import com.sun.enterprise.deploy.shared.ArchiveFactory;
-import com.sun.enterprise.deployment.*;
-import com.sun.enterprise.deployment.annotation.factory.AnnotatedElementHandlerFactory;
+import com.sun.enterprise.deployment.Application;
+import com.sun.enterprise.deployment.BundleDescriptor;
import com.sun.enterprise.deployment.annotation.factory.SJSASFactory;
import com.sun.enterprise.deployment.annotation.impl.ModuleScanner;
import com.sun.enterprise.deployment.io.DeploymentDescriptorFile;
@@ -51,28 +51,50 @@
import static com.sun.enterprise.deployment.io.DescriptorConstants.PERSISTENCE_DD_ENTRY;
import static com.sun.enterprise.deployment.io.DescriptorConstants.WEB_WEBSERVICES_JAR_ENTRY;
import static com.sun.enterprise.deployment.io.DescriptorConstants.EJB_WEBSERVICES_JAR_ENTRY;
-import com.sun.enterprise.deployment.util.*;
+import com.sun.enterprise.deployment.util.ComponentPostVisitor;
+import com.sun.enterprise.deployment.util.DOLUtils;
+import com.sun.enterprise.deployment.util.TracerVisitor;
import com.sun.enterprise.util.LocalStringManagerImpl;
import com.sun.enterprise.util.io.FileUtils;
import com.sun.enterprise.util.shared.ArchivistUtils;
import fish.payara.nucleus.hotdeploy.ApplicationState;
-import org.glassfish.apf.*;
+import org.glassfish.apf.AnnotationProcessorException;
+import org.glassfish.apf.ErrorHandler;
+import org.glassfish.apf.ProcessingResult;
+import org.glassfish.apf.ResultType;
import org.glassfish.apf.Scanner;
-import org.glassfish.apf.impl.DefaultErrorHandler;
+import org.glassfish.api.deployment.DeploymentContext;
import org.glassfish.api.deployment.archive.ArchiveType;
import org.glassfish.api.deployment.archive.Archive;
import org.glassfish.api.deployment.archive.ReadableArchive;
import org.glassfish.api.deployment.archive.WritableArchive;
-import org.glassfish.deployment.common.*;
+import org.glassfish.deployment.common.DeploymentProperties;
+import org.glassfish.deployment.common.Descriptor;
+import org.glassfish.deployment.common.DescriptorVisitor;
+import org.glassfish.deployment.common.InstalledLibrariesResolver;
+import org.glassfish.deployment.common.ModuleDescriptor;
+import org.glassfish.deployment.common.RootDeploymentDescriptor;
import org.glassfish.hk2.api.MultiException;
import org.glassfish.hk2.api.ServiceLocator;
-import org.glassfish.hk2.classmodel.reflect.*;
import jakarta.inject.Inject;
+import org.glassfish.internal.deployment.Deployment;
import org.jvnet.hk2.annotations.Contract;
import org.xml.sax.SAXParseException;
-import java.io.*;
-import java.util.*;
+import java.io.BufferedOutputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.JarInputStream;
@@ -138,9 +160,6 @@ public abstract class Archivist {
// runtime xml validation error level reporting/recovering
private String runtimeValidationLevel = "parsing";
- // error handler for annotation processing
- private ErrorHandler annotationErrorHandler = null;
-
private static final String WSDL = ".wsdl";
private static final String XML = ".xml";
private static final String XSD = ".xsd";
@@ -166,23 +185,19 @@ public abstract class Archivist {
protected ServiceLocator habitat;
@Inject
- protected ServiceLocator locator;
+ SJSASFactory annotationFactory;
@Inject
- SJSASFactory annotationFactory;
+ Deployment deployment;
+
+ @Deprecated(forRemoval = true)
+ protected ServiceLocator locator = null;
@Inject
ArchiveFactory archiveFactory;
protected List extensionsArchivists;
- /**
- * Creates new Archivist
- */
- public Archivist() {
- annotationErrorHandler = new DefaultErrorHandler();
- }
-
/**
* initializes this instance from another archivist, this is used to
* transfer contextual information between archivists, for example whether
@@ -194,7 +209,6 @@ protected void initializeContext(Archivist other) {
isValidatingXML = other.isValidatingXML;
validationLevel = other.validationLevel;
classLoader = other.classLoader;
- annotationErrorHandler = other.annotationErrorHandler;
}
/**
@@ -590,24 +604,8 @@ protected ProcessingResult processAnnotations(RootDeploymentDescriptor bundleDes
return null;
}
- AnnotatedElementHandler aeHandler =
- AnnotatedElementHandlerFactory.createAnnotatedElementHandler(
- bundleDesc);
-
- if (aeHandler == null) {
- return null;
- }
-
- Parser parser = null;
- if (archive.getParentArchive() != null) {
- parser = archive.getParentArchive().getExtraData(Parser.class);
- } else {
- parser = archive.getExtraData(Parser.class);
- }
-
- scanner.process(archive, bundleDesc, classLoader, parser);
-
- if (!scanner.getElements().isEmpty()) {
+// if (!scanner.getElements().isEmpty()) {
+ if (true) {
if (((BundleDescriptor) bundleDesc).isDDWithNoAnnotationAllowed()) {
// if we come into this block, it means an old version
// of deployment descriptor has annotation which is not correct
@@ -624,64 +622,18 @@ protected ProcessingResult processAnnotations(RootDeploymentDescriptor bundleDes
"{0} in archive {1} is of version {2}, which cannot support annotations in an application. Please upgrade the deployment descriptor to be a version supported by Java EE 5.0 (or later).",
new Object[]{ddName, archiveName, bundleDesc.getSpecVersion()}));
}
- boolean isFullAttribute = false;
- if (bundleDesc instanceof BundleDescriptor) {
- isFullAttribute = ((BundleDescriptor) bundleDesc).isFullAttribute();
- }
-
- AnnotationProcessor ap = annotationFactory.getAnnotationProcessor(isFullAttribute);
- ProcessingContext ctx = getProcessingContext(bundleDesc, archive, ap);
- ctx.setArchive(archive);
- if (annotationErrorHandler != null) {
- ctx.setErrorHandler(annotationErrorHandler);
- }
- ctx.setProcessingInput(scanner);
- ctx.pushHandler(aeHandler);
-
- // Make sure there is a classloader available on the descriptor
- // during annotation processing.
- ClassLoader originalBundleClassLoader = null;
- try {
- originalBundleClassLoader = bundleDesc.getClassLoader();
- } catch (Exception e) {
- // getClassLoader can throw exception if not available
- }
-
- // Only set classloader if it's not already set.
- if (originalBundleClassLoader == null) {
- bundleDesc.setClassLoader(classLoader);
- }
-
- try {
- return ap.process(ctx);
- } finally {
- if (originalBundleClassLoader == null) {
- bundleDesc.setClassLoader(null);
- }
- }
+// boolean isFullAttribute = false;
+// if (bundleDesc instanceof BundleDescriptor) {
+// isFullAttribute = ((BundleDescriptor) bundleDesc).isFullAttribute();
+// }
+
+ DeploymentContext deploymentContext = deployment.getCurrentDeploymentContext();
+ annotationFactory.processAnnotations(deploymentContext, bundleDesc, archive);
+// ProcessingContext ctx = getProcessingContext(bundleDesc, archive, ap);
}
return null;
}
- private ProcessingContext getProcessingContext(
- RootDeploymentDescriptor bundleDesc,
- ReadableArchive archive,
- AnnotationProcessor ap) {
-
- ProcessingContext ctx = null;
- ApplicationState state = archive.getExtraData(ApplicationState.class);
- if (state != null) {
- ctx = state.getProcessingContext(bundleDesc.getClass(), ProcessingContext.class);
- }
- if (ctx == null) {
- ctx = ap.createContext();
- if (state != null) {
- state.addProcessingContext(bundleDesc.getClass(), ctx);
- }
- }
- return ctx;
- }
-
/**
* Read the standard deployment descriptors (can contained in one or many
* file) and return the corresponding initialized descriptor instance. By
@@ -1222,14 +1174,14 @@ public boolean isAnnotationProcessingRequested() {
* @param annotationErrorHandler
*/
public void setAnnotationErrorHandler(ErrorHandler annotationErrorHandler) {
- this.annotationErrorHandler = annotationErrorHandler;
+ throw new UnsupportedOperationException("No longer supported.");
}
/**
* @return annotation ErrorHandler of this archivist
*/
public ErrorHandler getAnnotationErrorHandler() {
- return annotationErrorHandler;
+ throw new UnsupportedOperationException("No longer supported.");
}
/**
diff --git a/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/util/DOLUtils.java b/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/util/DOLUtils.java
index 67cdc4fbd78..9ed067ffe46 100644
--- a/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/util/DOLUtils.java
+++ b/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/util/DOLUtils.java
@@ -75,10 +75,10 @@
import org.glassfish.hk2.api.ActiveDescriptor;
import org.glassfish.hk2.api.ServiceHandle;
import org.glassfish.hk2.api.ServiceLocator;
-import org.glassfish.hk2.classmodel.reflect.Types;
import org.glassfish.internal.api.Globals;
import org.glassfish.internal.data.ApplicationInfo;
import org.glassfish.internal.data.ApplicationRegistry;
+import org.glassfish.internal.deployment.Deployment;
import org.glassfish.internal.deployment.ExtendedDeploymentContext;
import org.glassfish.internal.deployment.SnifferManager;
import org.glassfish.loader.util.ASClassLoaderUtil;
@@ -648,16 +648,18 @@ private static Collection getSniffersForModule(ServiceLocator habitat,
SnifferManager snifferManager = habitat.getService(SnifferManager.class);
List classPathURIs = handler.getClassPathURIs(archive);
classPathURIs.addAll(getLibraryJarURIs(app, archive));
- Types types = archive.getParentArchive().getExtraData(Types.class);
DeployCommandParameters parameters = archive.getParentArchive().getArchiveMetaData(DeploymentProperties.COMMAND_PARAMS, DeployCommandParameters.class);
Properties appProps = archive.getParentArchive().getArchiveMetaData(DeploymentProperties.APP_PROPS, Properties.class);
ExtendedDeploymentContext context = new DeploymentContextImpl(null, archive, parameters, habitat.getService(ServerEnvironment.class));
+ context.setParentContext(habitat.getService(Deployment.class).getCurrentDeploymentContext());
+ for (var entry : habitat.getService(Deployment.class).getCurrentDeploymentContext().getTransientAppMetadata().entrySet()) {
+ context.addTransientAppMetaData(entry.getKey(), entry.getValue());
+ }
if (appProps != null) {
context.getAppProps().putAll(appProps);
}
context.setArchiveHandler(handler);
- context.addTransientAppMetaData(Types.class.getName(), types);
- Collection sniffers = snifferManager.getSniffers(context, classPathURIs, types);
+ Collection sniffers = snifferManager.getSniffers(context, classPathURIs, null);
context.postDeployClean(true);
String type = getTypeFromModuleType(md.getModuleType());
Sniffer mainSniffer = null;
diff --git a/appserver/deployment/javaee-core/src/main/java/org/glassfish/javaee/core/deployment/DolProvider.java b/appserver/deployment/javaee-core/src/main/java/org/glassfish/javaee/core/deployment/DolProvider.java
index fb0088874e2..9348e65db30 100644
--- a/appserver/deployment/javaee-core/src/main/java/org/glassfish/javaee/core/deployment/DolProvider.java
+++ b/appserver/deployment/javaee-core/src/main/java/org/glassfish/javaee/core/deployment/DolProvider.java
@@ -145,9 +145,6 @@ public MetaData getMetaData() {
private Application processDOL(DeploymentContext dc) throws IOException {
ReadableArchive sourceArchive = dc.getSource();
- sourceArchive.setExtraData(Types.class, dc.getTransientAppMetaData(Types.class.getName(), Types.class));
- sourceArchive.setExtraData(Parser.class, dc.getTransientAppMetaData(Parser.class.getName(), Parser.class));
-
Optional appState = hotDeployService.getApplicationState(dc);
appState.ifPresent(state -> sourceArchive.setExtraData(ApplicationState.class, state));
diff --git a/appserver/packager/appserver-core/pom.xml b/appserver/packager/appserver-core/pom.xml
index 0245fc21cd3..518d4fce7f4 100644
--- a/appserver/packager/appserver-core/pom.xml
+++ b/appserver/packager/appserver-core/pom.xml
@@ -294,5 +294,10 @@
com.fasterxml.jackson.dataformat
jackson-dataformat-toml
+
+ io.smallrye
+ jandex
+ ${jandex.version}
+
diff --git a/appserver/payara-appserver-modules/microprofile/config/pom.xml b/appserver/payara-appserver-modules/microprofile/config/pom.xml
index a5dff27d266..a1101154381 100644
--- a/appserver/payara-appserver-modules/microprofile/config/pom.xml
+++ b/appserver/payara-appserver-modules/microprofile/config/pom.xml
@@ -83,6 +83,11 @@
weld-integration
${project.version}
+
+ io.smallrye
+ jandex
+ 3.2.3
+
jakarta.annotation
jakarta.annotation-api
diff --git a/appserver/payara-appserver-modules/microprofile/config/src/main/java/fish/payara/microprofile/config/activation/ConfigDeployer.java b/appserver/payara-appserver-modules/microprofile/config/src/main/java/fish/payara/microprofile/config/activation/ConfigDeployer.java
index eee474b1efd..9c615dcb787 100644
--- a/appserver/payara-appserver-modules/microprofile/config/src/main/java/fish/payara/microprofile/config/activation/ConfigDeployer.java
+++ b/appserver/payara-appserver-modules/microprofile/config/src/main/java/fish/payara/microprofile/config/activation/ConfigDeployer.java
@@ -1,7 +1,7 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
- * Copyright (c) [2020-2021] Payara Foundation and/or its affiliates. All rights reserved.
+ * Copyright (c) [2020-2025] Payara Foundation 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
@@ -44,13 +44,14 @@
import jakarta.enterprise.inject.spi.Extension;
+import jakarta.inject.Inject;
import org.eclipse.microprofile.config.Config;
import org.eclipse.microprofile.config.inject.ConfigProperties;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.glassfish.api.deployment.DeploymentContext;
import org.glassfish.hk2.api.PerLookup;
-import org.glassfish.hk2.classmodel.reflect.Type;
-import org.glassfish.hk2.classmodel.reflect.Types;
+import org.glassfish.internal.deployment.JandexIndexer;
+import org.glassfish.internal.deployment.JandexIndexer.Index;
import org.glassfish.weld.WeldDeployer;
import org.jvnet.hk2.annotations.Service;
@@ -60,6 +61,8 @@
@Service
@PerLookup
public class ConfigDeployer extends MicroProfileDeployer {
+ @Inject
+ JandexIndexer jandexIndexer;
@Override
@SuppressWarnings("unchecked")
@@ -68,19 +71,13 @@ public ConfigApplicationContainer load(ConfigContainer container,
// Perform annotation scanning to see if CDI extension is required here
// This is performed here so that the ApplicationContainer executes regardless of CDI extension state
- final Types types = deploymentContext.getTransientAppMetaData(Types.class.getName(), Types.class);
-
-
- if (types != null) {
- // The annotations that denote a Config API enabled application
- final Type annotationType = types.getBy(ConfigProperty.class.getName());
- final Type annotation2Type = types.getBy(ConfigProperties.class.getName());
- final Type classType = types.getBy(Config.class.getName());
- final boolean annotationFound = annotationType != null;
- final boolean annotation2Found = annotation2Type != null;
- final boolean classFound = classType != null;
-
- if (annotationFound || annotation2Found || classFound) {
+ Index index = jandexIndexer.getRootIndex(deploymentContext);
+ if (index != null) {
+ boolean found = false;
+ found |= !index.getIndex().getAnnotations(ConfigProperty.class).isEmpty();
+ found |= !index.getIndex().getAnnotations(ConfigProperties.class).isEmpty();
+ found |= !index.getIndex().getAnnotations(Config.class).isEmpty();
+ if (found) {
// Register the CDI extension
final Collection> snifferExtensions = deploymentContext.getTransientAppMetaData(WeldDeployer.SNIFFER_EXTENSIONS, Collection.class);
if (snifferExtensions != null) {
diff --git a/appserver/payara-appserver-modules/microprofile/metrics/pom.xml b/appserver/payara-appserver-modules/microprofile/metrics/pom.xml
index a6354c4f94f..f2a0025a1bb 100644
--- a/appserver/payara-appserver-modules/microprofile/metrics/pom.xml
+++ b/appserver/payara-appserver-modules/microprofile/metrics/pom.xml
@@ -127,6 +127,11 @@
fish.payara.monitoring-console
monitoring-console-api
+
+ io.smallrye
+ jandex
+ 3.2.3
+
org.mockito
mockito-core
diff --git a/appserver/payara-appserver-modules/microprofile/metrics/src/main/java/fish/payara/microprofile/metrics/activation/MetricsSniffer.java b/appserver/payara-appserver-modules/microprofile/metrics/src/main/java/fish/payara/microprofile/metrics/activation/MetricsSniffer.java
index dfd43e02085..0cdc8a21f43 100644
--- a/appserver/payara-appserver-modules/microprofile/metrics/src/main/java/fish/payara/microprofile/metrics/activation/MetricsSniffer.java
+++ b/appserver/payara-appserver-modules/microprofile/metrics/src/main/java/fish/payara/microprofile/metrics/activation/MetricsSniffer.java
@@ -1,7 +1,7 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
- * Copyright (c) [2020-2023] Payara Foundation and/or its affiliates. All rights reserved.
+ * Copyright (c) [2020-2025] Payara Foundation 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
@@ -53,7 +53,8 @@
import org.glassfish.api.deployment.DeploymentContext;
import org.glassfish.api.deployment.archive.ReadableArchive;
import org.glassfish.hk2.api.PerLookup;
-import org.glassfish.hk2.classmodel.reflect.Types;
+import org.glassfish.internal.deployment.JandexIndexer;
+import org.glassfish.internal.deployment.JandexIndexer.Index;
import org.jvnet.hk2.annotations.Service;
import fish.payara.microprofile.connector.MicroProfileSniffer;
@@ -66,6 +67,8 @@ public class MetricsSniffer extends MicroProfileSniffer {
@Inject
private ServerEnvironment serverEnv;
+ @Inject
+ JandexIndexer jandexIndexer;
@Override
@SuppressWarnings("unchecked")
@@ -85,14 +88,12 @@ public Class extends Annotation>[] getAnnotationTypes() {
@Override
public boolean handles(DeploymentContext context) {
- final Types types = context.getTransientAppMetaData(Types.class.getName(), Types.class);
-
- if (types != null) {
- if (types.getBy(MetricRegistry.class.getName()) != null) {
+ Index index = jandexIndexer.getRootIndex(context);
+ if (index != null) {
+ if (!index.getIndex().getAnnotations(MetricRegistry.class).isEmpty()) {
return true;
}
-
- if (types.getBy(Metric.class.getName()) != null) {
+ if (!index.getIndex().getAnnotations(Metric.class).isEmpty()) {
return true;
}
}
diff --git a/appserver/web/gf-weld-connector/pom.xml b/appserver/web/gf-weld-connector/pom.xml
index 5f2ec667e65..aa9648f04b4 100644
--- a/appserver/web/gf-weld-connector/pom.xml
+++ b/appserver/web/gf-weld-connector/pom.xml
@@ -80,5 +80,10 @@
jakarta.faces
true
+
+ io.smallrye
+ jandex
+ ${jandex.version}
+
diff --git a/appserver/web/gf-weld-connector/src/main/java/org/glassfish/weld/connector/WeldSniffer.java b/appserver/web/gf-weld-connector/src/main/java/org/glassfish/weld/connector/WeldSniffer.java
index 273eaf77e97..a09e9a656ae 100644
--- a/appserver/web/gf-weld-connector/src/main/java/org/glassfish/weld/connector/WeldSniffer.java
+++ b/appserver/web/gf-weld-connector/src/main/java/org/glassfish/weld/connector/WeldSniffer.java
@@ -245,7 +245,7 @@ public String[] getAnnotationNames(DeploymentContext context) {
}
// make sure it's not an extension
- if ( ! WeldUtils.isValidBdaBasedOnExtensionAndBeansXml( context.getSource() )) {
+ if ( ! WeldUtils.isValidBdaBasedOnExtensionAndBeansXml(context, context.getSource() )) {
return null;
}
diff --git a/appserver/web/gf-weld-connector/src/main/java/org/glassfish/weld/connector/WeldUtils.java b/appserver/web/gf-weld-connector/src/main/java/org/glassfish/weld/connector/WeldUtils.java
index f5f8050012c..de6e9134148 100644
--- a/appserver/web/gf-weld-connector/src/main/java/org/glassfish/weld/connector/WeldUtils.java
+++ b/appserver/web/gf-weld-connector/src/main/java/org/glassfish/weld/connector/WeldUtils.java
@@ -37,7 +37,7 @@
* only if the new code is made subject to such option by the copyright
* holder.
*/
-// Portions Copyright [2016-2024] [Payara Foundation and/or its affiliates]
+// Portions Copyright [2016-2025] [Payara Foundation and/or its affiliates]
package org.glassfish.weld.connector;
@@ -48,12 +48,10 @@
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.net.URI;
-import java.nio.file.Path;
-import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
-import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
@@ -65,6 +63,7 @@
import jakarta.enterprise.inject.Model;
import jakarta.enterprise.inject.Stereotype;
import jakarta.faces.flow.FlowScoped;
+import jakarta.faces.view.ViewScoped;
import jakarta.inject.Inject;
import jakarta.inject.Scope;
import jakarta.inject.Singleton;
@@ -73,17 +72,11 @@
import org.glassfish.api.admin.ServerEnvironment;
import org.glassfish.api.deployment.DeploymentContext;
import org.glassfish.api.deployment.archive.ReadableArchive;
-import org.glassfish.deployment.common.DeploymentUtils;
-import org.glassfish.hk2.api.ServiceLocator;
-import org.glassfish.hk2.classmodel.reflect.AnnotationModel;
-import org.glassfish.hk2.classmodel.reflect.AnnotationType;
-import org.glassfish.hk2.classmodel.reflect.ClassModel;
-import org.glassfish.hk2.classmodel.reflect.FieldModel;
-import org.glassfish.hk2.classmodel.reflect.MethodModel;
-import org.glassfish.hk2.classmodel.reflect.Type;
-import org.glassfish.hk2.classmodel.reflect.Types;
import org.glassfish.internal.api.Globals;
-import org.glassfish.internal.deployment.ExtendedDeploymentContext;
+import org.glassfish.hk2.api.ServiceLocator;
+import org.glassfish.internal.deployment.JandexIndexer;
+import org.glassfish.internal.deployment.JandexIndexer.Index;
+import org.jboss.jandex.AnnotationInstance;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
@@ -113,6 +106,9 @@ public class WeldUtils {
// which does not have CDI implementation. So, we use the class name as a string.
private static final String SERVICES_CLASSNAME = "jakarta.enterprise.inject.spi.Extension";
private static final String BCE_SERVICES_CLASSNAME = "jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension";
+ private static final String CDI_ENABLING_ANNOTATIONS_CACHE_METADATA = "fish.payara.cdi.enabling.annotations.cache.metadata";
+ private static final String CDI_ANNOTATED_CLASS_NAMES_METADATA = "fish.payara.cdi.annotated.class.names.metadata";
+
public static final String META_INF_SERVICES_EXTENSION = "META-INF" + SEPARATOR_CHAR + SERVICES_DIR +
SEPARATOR_CHAR + SERVICES_CLASSNAME;
public static final String META_INF_BCE_SERVICES_EXTENSION = "META-INF" + SEPARATOR_CHAR + SERVICES_DIR +
@@ -134,42 +130,45 @@ public class WeldUtils {
*/
public enum BDAType { WAR, JAR, RAR, UNKNOWN };
+ static final Set> cdiScopeAnnotationClasses;
protected static final Set cdiScopeAnnotations;
static {
- final HashSet cdi = new HashSet<>();
- cdi.add(Scope.class.getName());
- cdi.add(NormalScope.class.getName());
- cdi.add("jakarta.faces.view.ViewScoped");
- cdi.add("jakarta.faces.flow.FlowScoped");
- cdi.add(ConversationScoped.class.getName());
- cdi.add(FlowScoped.class.getName());
- cdi.add(ApplicationScoped.class.getName());
- cdi.add(SessionScoped.class.getName());
- cdi.add(RequestScoped.class.getName());
- cdi.add(Dependent.class.getName());
- cdi.add(Singleton.class.getName());
- cdi.add(Model.class.getName());
-
- cdiScopeAnnotations = Collections.unmodifiableSet(cdi);
- }
-
- protected static final Set cdiEnablingAnnotations;
+ final HashSet> cdi = new HashSet<>();
+ cdi.add(Scope.class);
+ cdi.add(NormalScope.class);
+ cdi.add(ConversationScoped.class);
+ cdi.add(ViewScoped.class);
+ cdi.add(FlowScoped.class);
+ cdi.add(ApplicationScoped.class);
+ cdi.add(SessionScoped.class);
+ cdi.add(RequestScoped.class);
+ cdi.add(Dependent.class);
+ cdi.add(Singleton.class);
+ cdi.add(Model.class);
+
+ cdiScopeAnnotationClasses = Collections.unmodifiableSet(cdi);
+ cdiScopeAnnotations = cdiScopeAnnotationClasses.stream().map(Class::getName).collect(Collectors.toSet());
+ }
+
+ static final Set cdiEnablingAnnotations;
+ static final Set> cdiEnablingAnnotationClasses;
static {
// CDI scopes
- final HashSet cdi = new HashSet<>(cdiScopeAnnotations);
+ final HashSet> cdi = new HashSet<>(cdiScopeAnnotationClasses);
// 1.2 updates
- cdi.add(Decorator.class.getName());
- cdi.add(Interceptor.class.getName());
- cdi.add(Stereotype.class.getName());
+ cdi.add(Decorator.class);
+ cdi.add(Interceptor.class);
+ cdi.add(Stereotype.class);
// EJB annotations
- cdi.add(MessageDriven.class.getName());
- cdi.add(Stateful.class.getName());
- cdi.add(Stateless.class.getName());
- cdi.add(jakarta.ejb.Singleton.class.getName());
+ cdi.add(MessageDriven.class);
+ cdi.add(Stateful.class);
+ cdi.add(Stateless.class);
+ cdi.add(jakarta.ejb.Singleton.class);
- cdiEnablingAnnotations = Collections.unmodifiableSet(cdi);
+ cdiEnablingAnnotationClasses = Collections.unmodifiableSet(cdi);
+ cdiEnablingAnnotations = cdiEnablingAnnotationClasses.stream().map(Class::getName).collect(Collectors.toSet());
}
@@ -183,10 +182,15 @@ public enum BDAType { WAR, JAR, RAR, UNKNOWN };
*/
public static boolean isImplicitBeanArchive(DeploymentContext context, ReadableArchive archive)
throws IOException {
- if(!isValidBdaBasedOnExtensionAndBeansXml(archive)) {
- return false;
- }
- return isImplicitBeanArchive(context, archive.getURI());
+ var index = Globals.getDefaultHabitat().getService(JandexIndexer.class)
+ .getIndexesByURI(context, Collections.singleton(archive.getURI()))
+ .values().stream().findAny().get();
+ return index.implicitBeanArchive(() -> {
+ if(!isValidBdaBasedOnExtensionAndBeansXml(context, archive)) {
+ return false;
+ }
+ return isImplicitBeanArchive(context, archive.getURI());
+ });
}
/**
@@ -198,10 +202,12 @@ public static boolean isImplicitBeanArchive(DeploymentContext context, ReadableA
* @return true, if it is an implicit bean deployment archive; otherwise, false.
*/
public static boolean isImplicitBeanArchive(DeploymentContext context, URI archivePath) {
- return (isImplicitBeanDiscoveryEnabled(context) && hasCDIEnablingAnnotations(context, archivePath));
+ var index = Globals.getDefaultHabitat().getService(JandexIndexer.class)
+ .getIndexesByURI(context, Collections.singleton(archivePath))
+ .values().stream().findAny().get();
+ return index.implicitBeanArchive(() -> isImplicitBeanDiscoveryEnabled(context) && hasCDIEnablingAnnotations(context, archivePath));
}
-
/**
* Determine whether there are any beans annotated with annotations that should enable CDI
* processing even in the absence of a beans.xml descriptor.
@@ -212,7 +218,10 @@ public static boolean isImplicitBeanArchive(DeploymentContext context, URI archi
* @return true, if there is at least one bean annotated with a qualified annotation in the specified path
*/
public static boolean hasCDIEnablingAnnotations(DeploymentContext context, URI path) {
- return hasCDIEnablingAnnotations(context, Collections.singleton(path));
+ var index = Globals.getDefaultHabitat().getService(JandexIndexer.class)
+ .getIndexesByURI(context, Collections.singleton(path))
+ .values().stream().findAny().get();
+ return index.hasCDIEnablingAnnotations(() -> hasCDIEnablingAnnotations(context, Collections.singleton(path)));
}
@@ -226,19 +235,12 @@ public static boolean hasCDIEnablingAnnotations(DeploymentContext context, URI p
* @return true, if there is at least one bean annotated with a qualified annotation in the specified paths
*/
public static boolean hasCDIEnablingAnnotations(DeploymentContext context, Collection paths) {
- final Set exclusions = new HashSet<>();
- for (final Type type : getAllTypes(context, paths)) {
- if (!(type instanceof AnnotationType) && type.wasDefinedIn(paths)) {
- for (final AnnotationModel am : type.getAnnotations()) {
- final AnnotationType at = am.getType();
- if (isCDIEnablingAnnotation(at, exclusions)) {
- return true;
- }
- }
- }
- }
-
- return false;
+ Map indexes = Globals.getDefaultHabitat().getService(JandexIndexer.class)
+ .getIndexesByURI(context, paths);
+ boolean result = Arrays.stream(getCDIEnablingAnnotations(context))
+ .anyMatch(annotation -> indexes.values().stream()
+ .anyMatch(index -> !index.getIndex().getAnnotations(annotation).isEmpty()));
+ return result;
}
/**
@@ -250,24 +252,42 @@ public static boolean hasCDIEnablingAnnotations(DeploymentContext context, Colle
* @return An array of annotation type names; The array could be empty if none are found.
*/
public static String[] getCDIEnablingAnnotations(DeploymentContext context) {
- final Set result = new HashSet<>();
-
- final Set exclusions = new HashSet<>();
- for (final Type type : getAllTypes(context, List.of())) {
- if (!(type instanceof AnnotationType)) {
- for (final AnnotationModel am : type.getAnnotations()) {
- final AnnotationType at = am.getType();
- if (isCDIEnablingAnnotation(at, exclusions)) {
- result.add(at.getName());
+ String[] annotations = context.getTransientAppMetaData(CDI_ENABLING_ANNOTATIONS_CACHE_METADATA, String[].class);
+ if (annotations != null) {
+ return annotations;
+ }
+ var indexes = Globals.getDefaultHabitat().getService(JandexIndexer.class).getAllIndexes(context);
+ Set appCdiEnablingAnnotations = indexes.values().stream()
+ .flatMap(index -> index.getIndex().getKnownClasses().stream())
+ .flatMap(classInfo -> classInfo.annotations().stream())
+ .map(annotationClass -> annotationClass.name().toString())
+ .collect(Collectors.toSet());
+
+ Set additionalAnnotations = new HashSet<>();
+ appCdiEnablingAnnotations.stream()
+ .filter(annotation -> !cdiEnablingAnnotations.contains(annotation))
+ .forEach(annotation -> {
+ try {
+ @SuppressWarnings("unchecked")
+ Class extends Annotation> cls = (Class extends Annotation>) context.getClassLoader()
+ .loadClass(annotation);
+ for (var annotationClass : cdiEnablingAnnotationClasses) {
+ if (cls.isAnnotationPresent(annotationClass)) {
+ additionalAnnotations.add(annotation);
+ break;
}
}
+ } catch (ClassNotFoundException | NullPointerException e) {
}
- }
-
- return result.toArray(new String[0]);
+ });
+ annotations = appCdiEnablingAnnotations.stream()
+ .filter(annotation -> cdiEnablingAnnotations.contains(annotation)
+ || additionalAnnotations.contains(annotation))
+ .toArray(String[]::new);
+ context.addTransientAppMetaData(CDI_ENABLING_ANNOTATIONS_CACHE_METADATA, annotations);
+ return annotations;
}
-
/**
* Get the names of any classes that are annotated with bean-defining annotations, which should
* enable CDI processing even in the absence of a beans.xml descriptor.
@@ -277,22 +297,23 @@ public static String[] getCDIEnablingAnnotations(DeploymentContext context) {
* @return A collection of class names; The collection could be empty if none are found.
*/
public static Collection getCDIAnnotatedClassNames(DeploymentContext context) {
- final Set result = new HashSet<>();
- final Set cdiEnablingAnnotations = new HashSet<>();
- Collections.addAll(cdiEnablingAnnotations, getCDIEnablingAnnotations(context));
-
- for (final Type type : getAllTypes(context, List.of())) {
- if (!(type instanceof AnnotationType)) {
- for (final AnnotationModel am : type.getAnnotations()) {
- final AnnotationType at = am.getType();
- if (cdiEnablingAnnotations.contains(at.getName())) {
- result.add(type.getName());
- break;
- }
- }
- }
+ @SuppressWarnings("unchecked")
+ Set result = context.getTransientAppMetaData(CDI_ANNOTATED_CLASS_NAMES_METADATA, Set.class);
+ if (result != null) {
+ return result;
}
+ final Set cdiEnablingAnnotations = new HashSet<>();
+ Collections.addAll(cdiEnablingAnnotations, getCDIEnablingAnnotations(context));
+ var indexes = Globals.getDefaultHabitat().getService(JandexIndexer.class).getAllIndexes(context);
+ result = new HashSet<>();
+ var finalResult = result;
+ indexes.values().forEach(index -> cdiEnablingAnnotations
+ .forEach(annotation -> finalResult.addAll(index.getIndex().getAnnotations(annotation).stream()
+ .map(WeldUtils::mapAnnotationToClassName)
+ .filter(Objects::nonNull)
+ .collect(Collectors.toSet()))));
+ context.addTransientAppMetaData(CDI_ANNOTATED_CLASS_NAMES_METADATA, result);
return result;
}
@@ -300,61 +321,25 @@ public static Collection getCDIAnnotatedClassNames(DeploymentContext con
* Searches through the known class names of a {@link BeanDeploymentArchive} to determine which have fields or
* methods with the {@link Inject} annotation.
*
- * @param types The Types obtained from a {@link DeploymentContext}'s transient metadata
+ * @param deploymentContext The deployment context
* @param knownClassNames The known class names of a {@link BeanDeploymentArchive}
* @return The class names from the given list which have fields or methods annotated with {@link Inject}
*/
- public static Collection getInjectionTargetClassNames(Types types, Collection knownClassNames) {
- final Set result = new HashSet<>();
-
- if (types != null) {
- for (String knownClassName : knownClassNames) {
- Type type = types.getBy(knownClassName);
-
- if (type != null && type instanceof ClassModel) {
- boolean injectionTarget = false;
-
- Collection fieldModels = ((ClassModel) type).getFields();
- for (FieldModel fieldModel : fieldModels) {
- injectionTarget = annotatedWithInject(fieldModel.getAnnotations());
- if (injectionTarget) {
- break;
- }
- }
-
- if (!injectionTarget) {
- Collection methodModels = type.getMethods();
- for (MethodModel methodModel : methodModels) {
- injectionTarget = annotatedWithInject(methodModel.getAnnotations());
- if (injectionTarget) {
- break;
- }
- }
- }
-
- if (injectionTarget) {
- result.add(type.getName());
- }
+ public static Collection getInjectionTargetClassNames(DeploymentContext deploymentContext,
+ Collection knownClassNames) {
+ var indexes = Globals.getDefaultHabitat().getService(JandexIndexer.class).getAllIndexes(deploymentContext);
+ Set result = new HashSet<>();
+ indexes.values().forEach(index -> {
+ for (AnnotationInstance annotationInstance : index.getIndex().getAnnotations(Inject.class)) {
+ String className = mapAnnotationToClassName(annotationInstance);
+ if (className != null && knownClassNames.contains(className)) {
+ result.add(className);
}
}
- }
-
+ });
return result;
}
- private static boolean annotatedWithInject(Collection annotationModels) {
- boolean injectionTarget = false;
- for (AnnotationModel annotationModel : annotationModels) {
- if (annotationModel.getType().getName().equals(Inject.class.getName())) {
- injectionTarget = true;
- break;
- }
- }
-
- return injectionTarget;
- }
-
-
/**
* Determine whether the specified class is annotated with a CDI scope annotation.
*
@@ -378,47 +363,6 @@ public static boolean hasCDIEnablingAnnotation(Class clazz) {
return hasValidAnnotation(clazz, cdiEnablingAnnotations, null);
}
-
- /**
- * Determine if the specified annotation type is a CDI-enabling annotation
- *
- * @param annotationType The annotation type to check
- *
- * @return true, if the specified annotation type qualifies as a CDI enabler; Otherwise, false
- */
- private static boolean isCDIEnablingAnnotation(AnnotationType annotationType) {
- return isCDIEnablingAnnotation(annotationType, new HashSet<>());
- }
-
-
- /**
- * Determine if the specified annotation type is a CDI-enabling annotation
- *
- * @param annotationType The annotation type to check
- * @param exclusions The Set of annotation type names that should be excluded from the analysis
- *
- * @return true, if the specified annotation type qualifies as a CDI enabler; Otherwise, false
- */
- private static boolean isCDIEnablingAnnotation(AnnotationType annotationType,
- Set exclusions) {
-
- final String annotationTypeName = annotationType.getName();
- if (cdiEnablingAnnotations.contains(annotationTypeName)) {
- return true;
- } else if (exclusions.add(annotationTypeName)) {
- // If the annotation type itself is not an excluded type, then check its annotation
- // types, exclude itself to avoid infinite recursion
- for (AnnotationModel parent : annotationType.getAnnotations()) {
- if (isCDIEnablingAnnotation(parent.getType(), exclusions)) {
- return true;
- }
- }
- }
-
- return false;
- }
-
-
/**
* Determine whether the specified class is annotated with one of the annotations in the specified
* validScopes collection, but not with any of the annotations in the specified exclusion set.
@@ -481,7 +425,7 @@ private static boolean isValidAnnotation(Class extends Annotation> annotationT
final String annotationTypeName = annotationType.getName();
if (validTypeNames.contains(annotationTypeName) && !excludedTypeNames.contains(annotationTypeName)) {
return true;
- } else if (excludedTypeNames.add(annotationTypeName)){
+ } else if (excludedTypeNames.add(annotationTypeName)) {
// If the annotation type itself is not an excluded type, then check its annotation
// types, exclude itself (to avoid infinite recursion)
for (Annotation parent : annotationType.getAnnotations()) {
@@ -494,23 +438,6 @@ private static boolean isValidAnnotation(Class extends Annotation> annotationT
return false;
}
-
- private static Types getTypes(DeploymentContext context) {
- String metadataKey = Types.class.getName();
-
- Types types = (Types) context.getTransientAppMetadata().get(metadataKey);
- while (types == null) {
- context = ((ExtendedDeploymentContext) context).getParentContext();
- if (context != null) {
- types = (Types) context.getTransientAppMetadata().get(metadataKey);
- } else {
- break;
- }
- }
-
- return types;
- }
-
public static int getPreLoaderThreads() {
int result = 0;
// Check the "global" configuration
@@ -606,15 +533,20 @@ public static InputStream getBeansXmlInputStream(DeploymentContext context) {
* @return false if there is an extension and no beans.xml
* true otherwise
*/
- public static boolean isValidBdaBasedOnExtensionAndBeansXml(ReadableArchive archive) {
- try {
- if (hasExtension(archive) && !hasBeansXML(archive)) {
- // Extensions and no beans.xml: not a bda
- return false;
+ public static boolean isValidBdaBasedOnExtensionAndBeansXml(DeploymentContext context, ReadableArchive archive) {
+ var index = Globals.getDefaultHabitat().getService(JandexIndexer.class)
+ .getIndexesByURI(context, Collections.singleton(archive.getURI()))
+ .values().stream().findAny().get();
+ return index.isValidBdaBasedOnExtensionAndBeansXml(() -> {
+ try {
+ if (hasExtension(archive) && !hasBeansXML(archive)) {
+ // Extensions and no beans.xml: not a bda
+ return false;
+ }
+ } catch (IOException ignore) {
}
- } catch (IOException ignore) {
- }
- return true;
+ return true;
+ });
}
public static boolean hasExtension(ReadableArchive archive) {
@@ -702,24 +634,6 @@ public static String getBeanDiscoveryMode(InputStream beansXmlInputStream) {
return beanDiscoveryMode;
}
- private static List getAllTypes(DeploymentContext context, Collection paths) {
- final Types types = getTypes(context);
- if (types == null) {
- return List.of();
- }
-
- List allTypes = new ArrayList<>(types.getAllTypes());
- Map cache = DeploymentUtils.getWarLibraryCache();
- for (URI path : paths.isEmpty() ? cache.keySet().stream().map(Path::of).map(Path::toUri)
- .collect(Collectors.toList()) : paths) {
- var descriptor = cache.get(path.getRawPath());
- if (descriptor != null) {
- allTypes.addAll(descriptor.getTypes());
- }
- }
- return allTypes;
- }
-
private static class LocalDefaultHandler extends DefaultHandler {
String beanDiscoveryMode = null;
@@ -741,4 +655,29 @@ private SAXStoppedIntentionallyException() {
super();
}
}
+
+ private static String mapAnnotationToClassName(AnnotationInstance annotationInstance) {
+ String className = null;
+ switch (annotationInstance.target().kind()) {
+ case CLASS:
+ className = annotationInstance.target().asClass().name().toString();
+ break;
+ case FIELD:
+ className = annotationInstance.target().asField().declaringClass().name().toString();
+ break;
+ case METHOD:
+ className = annotationInstance.target().asMethod().receiverType().name().toString();
+ break;
+ case METHOD_PARAMETER:
+ className = annotationInstance.target().asMethodParameter().method().receiverType().name().toString();
+ break;
+ case TYPE:
+ className = annotationInstance.target().asType().asClass().toString();
+ break;
+ case RECORD_COMPONENT:
+ className = annotationInstance.target().asRecordComponent().declaringClass().name().toString();
+ break;
+ }
+ return className;
+ }
}
diff --git a/appserver/web/jsf-connector/src/main/java/fish/payara/faces/integration/MojarraSniffer.java b/appserver/web/jsf-connector/src/main/java/fish/payara/faces/integration/MojarraSniffer.java
index d6fa83f9725..8f93e6477d1 100644
--- a/appserver/web/jsf-connector/src/main/java/fish/payara/faces/integration/MojarraSniffer.java
+++ b/appserver/web/jsf-connector/src/main/java/fish/payara/faces/integration/MojarraSniffer.java
@@ -42,14 +42,14 @@
import com.sun.enterprise.util.Utility;
import com.sun.faces.config.FacesInitializer;
import com.sun.faces.config.FacesInitializer2;
+import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import jakarta.servlet.ServletContainerInitializer;
import org.glassfish.api.deployment.DeploymentContext;
import org.glassfish.api.deployment.archive.ArchiveType;
import org.glassfish.api.deployment.archive.ReadableArchive;
-import org.glassfish.hk2.classmodel.reflect.Types;
-import org.glassfish.internal.deployment.ExtendedDeploymentContext;
import org.glassfish.internal.deployment.GenericSniffer;
+import org.glassfish.internal.deployment.JandexIndexer;
import org.glassfish.web.loader.ServletContainerInitializerUtil;
import org.jvnet.hk2.annotations.Service;
@@ -75,6 +75,9 @@ public class MojarraSniffer extends GenericSniffer {
private static final String[] containers = { "org.glassfish.weld.WeldContainer" };
private static final Logger logger = Logger.getLogger(MojarraSniffer.class.getName());
+ @Inject
+ JandexIndexer jandexIndexer;
+
public MojarraSniffer() {
super("cdi", null, null);
}
@@ -166,14 +169,14 @@ private boolean hasFacesEnablingClass(DeploymentContext context) {
Map, Set>> initialiserList =
ServletContainerInitializerUtil.getInitializerList(
facesInitialisers, interestList,
- getTypes(context),
+ jandexIndexer.getAllIndexes(context),
Utility.getClassLoader(), false);
for (Map.Entry, Set>> initialiserEntry : initialiserList.entrySet()) {
if (initialiserEntry.getValue() != null && !initialiserEntry.getValue().isEmpty()) {
if (logger.isLoggable(Level.FINE)) {
List classNames = new ArrayList<>();
- initialiserEntry.getValue().stream().forEach(clazz -> classNames.add(clazz.getName()));
+ initialiserEntry.getValue().forEach(clazz -> classNames.add(clazz.getName()));
logger.fine(initialiserEntry.getKey().getName()
+ " container initialiser has an interest in the following classes detected within the application: "
+ Arrays.toString(classNames.toArray()));
@@ -200,26 +203,4 @@ private List getMojarraServletContextInitialisers(D
return facesInitialisers;
}
-
- private Types getTypes(DeploymentContext context) {
- String metadataKey = Types.class.getName();
-
- Types types = (Types) context.getTransientAppMetadata().get(metadataKey);
- while (types == null) {
- context = ((ExtendedDeploymentContext) context).getParentContext();
- if (context != null) {
- types = (Types) context.getTransientAppMetadata().get(metadataKey);
- } else {
- break;
- }
- }
-
- if (types == null) {
- logger.fine("No types found!");
- }
-
- return types;
- }
-
-
}
diff --git a/appserver/web/war-util/src/main/java/org/glassfish/web/loader/ServletContainerInitializerUtil.java b/appserver/web/war-util/src/main/java/org/glassfish/web/loader/ServletContainerInitializerUtil.java
index 1a7be433272..4b9b15ec62b 100644
--- a/appserver/web/war-util/src/main/java/org/glassfish/web/loader/ServletContainerInitializerUtil.java
+++ b/appserver/web/war-util/src/main/java/org/glassfish/web/loader/ServletContainerInitializerUtil.java
@@ -43,10 +43,13 @@
import fish.payara.web.loader.ServletContainerInitializerBlacklist;
import org.glassfish.deployment.common.ClassDependencyBuilder;
-import org.glassfish.hk2.classmodel.reflect.*;
import jakarta.servlet.ServletContainerInitializer;
import jakarta.servlet.annotation.HandlesTypes;
+import org.glassfish.hk2.classmodel.reflect.Types;
+import org.glassfish.internal.deployment.JandexIndexer.Index;
+import org.jboss.jandex.AnnotationInstance;
+import org.jboss.jandex.ClassInfo;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
@@ -230,6 +233,15 @@ public static Map, List>>
return interestList;
}
+ @Deprecated
+ public static Map, Set>> getInitializerList(
+ Iterable initializers,
+ Map, List>> interestList,
+ Types types,
+ ClassLoader cl, boolean isStandalone) {
+ throw new IllegalStateException("Method is deprecated");
+ }
+
/**
* Given an interestlist that was built above, and a class loader, scan the entire web app's classes and libraries
* looking for classes that extend/implement/use the annotations of a class present in the interest list
@@ -245,7 +257,7 @@ public static Map, List>>
public static Map, Set>> getInitializerList(
Iterable initializers,
Map, List>> interestList,
- Types types,
+ Map indexMap,
ClassLoader cl, boolean isStandalone) {
if (interestList == null) {
@@ -281,7 +293,7 @@ public static Map, Set>>
* the information for every class in this app
*
*/
- if (types==null || Boolean.getBoolean("org.glassfish.web.parsing")) {
+ if (indexMap==null || Boolean.getBoolean("org.glassfish.web.parsing")) {
ClassDependencyBuilder classInfo = new ClassDependencyBuilder();
if (cl instanceof URLClassLoader) {
URLClassLoader ucl = (URLClassLoader) cl;
@@ -350,7 +362,7 @@ public static Map, Set>>
initializerList = checkAgainstInterestList(classInfo, interestList, initializerList, cl, isStandalone);
} else {
- initializerList = checkAgainstInterestList(types, interestList, initializerList, cl, isStandalone);
+ initializerList = checkAgainstInterestList(indexMap, interestList, initializerList, cl, isStandalone);
}
}
@@ -440,66 +452,32 @@ private static void scanDirectory(File dir, ClassDependencyBuilder classInfo) {
*
*/
private static Map, Set>> checkAgainstInterestList(
- Types classInfo,
+ Map indexMap,
Map, List>> interestList,
Map, Set>> initializerList,
ClassLoader cl, boolean isStandalone) {
- if (classInfo==null) {
+ if (indexMap==null) {
return initializerList;
}
for (Map.Entry, List>> e:
interestList.entrySet()) {
- Class> c = e.getKey();
- Type type = classInfo.getBy(c.getName());
- if (type==null)
- continue;
-
Set> resultSet = new HashSet>();
- if (type instanceof AnnotationType) {
- for (AnnotatedElement ae : ((AnnotationType) type).allAnnotatedTypes()) {
- if (ae instanceof Member) {
- ae = ((Member) ae).getDeclaringType();
- } else if (ae instanceof Parameter) {
- ae = ((Parameter) ae).getMethod().getDeclaringType();
- }
- if (ae instanceof Type) {
- try {
- resultSet.add(cl.loadClass(ae.getName()));
- } catch (Throwable t) {
- if (log.isLoggable(getStandaloneWarningLevel(isStandalone))) {
- log.log(getStandaloneWarningLevel(isStandalone),
- LogFacade.CLASS_LOADING_ERROR,
- new Object[] {ae.getName(), t.toString()});
- }
- }
- }
- }
- } else {
- Collection classes;
- if (type instanceof InterfaceModel) {
- classes = ((InterfaceModel) type).allImplementations();
- } else {
- classes = ((ClassModel) type).allSubTypes();
- }
- for (ClassModel classModel : classes) {
- try {
- resultSet.add(cl.loadClass(classModel.getName()));
- } catch (Throwable t) {
- if (log.isLoggable(getStandaloneWarningLevel(isStandalone))) {
- log.log(getStandaloneWarningLevel(isStandalone),
- LogFacade.CLASS_LOADING_ERROR,
- new Object[] {classModel.getName(), t.toString()});
- }
- }
- }
+ for (Index index : indexMap.values()) {
+ index.getIndex().getAllKnownImplementors(e.getKey())
+ .forEach(classInfo -> addClassToResult(classInfo, cl, isStandalone, resultSet));
+ index.getIndex().getAllKnownSubclasses(e.getKey())
+ .forEach(classInfo -> addClassToResult(classInfo, cl, isStandalone, resultSet));
+ index.getIndex().getAnnotations(e.getKey()).forEach(annotation ->
+ addClassToResult(mapAnnotationToClassName(annotation), cl, isStandalone, resultSet));
}
+
List> containerInitializers = e.getValue();
for(Class extends ServletContainerInitializer> initializer : containerInitializers) {
Set> classSet = initializerList.get(initializer);
if(classSet == null) {
- classSet = new HashSet>();
+ classSet = new HashSet<>();
}
classSet.addAll(resultSet);
initializerList.put(initializer, classSet);
@@ -509,6 +487,55 @@ private static Map, Set>>
return initializerList;
}
+
+ private static void addClassToResult(ClassInfo classInfo, ClassLoader cl,
+ boolean isStandalone, Set> resultSet) {
+ addClassToResult(classInfo.name().toString(), cl, isStandalone, resultSet);
+ }
+
+ private static void addClassToResult(String className, ClassLoader cl,
+ boolean isStandalone, Set> resultSet) {
+ try {
+ resultSet.add(cl.loadClass(className));
+ } catch (Exception t) {
+ if (log.isLoggable(getStandaloneWarningLevel(isStandalone))) {
+ log.log(getStandaloneWarningLevel(isStandalone),
+ LogFacade.CLASS_LOADING_ERROR,
+ new Object[]{className, t.toString()});
+ }
+ }
+ }
+
+ /**
+ * *** TODO: duplicate from weld-gf-connector
+ * @param annotationInstance
+ * @return
+ */
+ private static String mapAnnotationToClassName(AnnotationInstance annotationInstance) {
+ String className = null;
+ switch (annotationInstance.target().kind()) {
+ case CLASS:
+ className = annotationInstance.target().asClass().name().toString();
+ break;
+ case FIELD:
+ className = annotationInstance.target().asField().declaringClass().name().toString();
+ break;
+ case METHOD:
+ className = annotationInstance.target().asMethod().receiverType().name().toString();
+ break;
+ case METHOD_PARAMETER:
+ className = annotationInstance.target().asMethodParameter().method().receiverType().name().toString();
+ break;
+ case TYPE:
+ className = annotationInstance.target().asType().asClass().toString();
+ break;
+ case RECORD_COMPONENT:
+ className = annotationInstance.target().asRecordComponent().declaringClass().name().toString();
+ break;
+ }
+ return className;
+ }
+
/**
* Given the interestList, checks if a given class uses any of the
* annotations; If so, builds the initializer list
diff --git a/appserver/web/web-core/src/main/java/org/apache/catalina/core/StandardContext.java b/appserver/web/web-core/src/main/java/org/apache/catalina/core/StandardContext.java
index 42758ba328c..c1a167b8c45 100644
--- a/appserver/web/web-core/src/main/java/org/apache/catalina/core/StandardContext.java
+++ b/appserver/web/web-core/src/main/java/org/apache/catalina/core/StandardContext.java
@@ -193,7 +193,11 @@
import org.glassfish.grizzly.http.server.util.MappingData;
import org.glassfish.grizzly.http.util.CharChunk;
import org.glassfish.grizzly.http.util.MessageBytes;
+import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.hk2.classmodel.reflect.Types;
+import org.glassfish.internal.deployment.Deployment;
+import org.glassfish.internal.deployment.ExtendedDeploymentContext;
+import org.glassfish.internal.deployment.JandexIndexer;
import org.glassfish.web.loader.ServletContainerInitializerUtil;
import org.glassfish.web.loader.WebappClassLoader;
import org.glassfish.web.valve.GlassFishValve;
@@ -5816,20 +5820,23 @@ protected boolean isStandalone() {
protected void callServletContainerInitializers()
throws LifecycleException {
- // Get the list of ServletContainerInitializers and the classes
- // they are interested in
- Map, List>> interestList =
- ServletContainerInitializerUtil.getInterestList(
- servletContainerInitializers);
- Map, Set>> initializerList =
- ServletContainerInitializerUtil.getInitializerList(
- servletContainerInitializers, interestList,
- getTypes(),
- getClassLoader(), isStandalone());
+ ServiceLocator locator = org.glassfish.internal.api.Globals.getDefaultHabitat();
+ var deploymentContext = locator.getService(Deployment.class).getCurrentDeploymentContext();
+
+ Map, Set>> initializerList = null;
+ if (deploymentContext != null && deploymentContext.getPhase() != ExtendedDeploymentContext.Phase.PREPARE) {
+ // Get the list of ServletContainerInitializers and the classes
+ // they are interested in
+ Map, List>> interestList =
+ ServletContainerInitializerUtil.getInterestList(
+ servletContainerInitializers);
+ initializerList = ServletContainerInitializerUtil.getInitializerList(servletContainerInitializers, interestList,
+ locator.getService(JandexIndexer.class).getAllIndexes(deploymentContext), getClassLoader(), isStandalone());
+ }
+
if (initializerList == null) {
return;
}
-
// Allow programmatic registration of ServletContextListeners, but
// only within the scope of ServletContainerInitializer#onStartup
isProgrammaticServletContextListenerRegistrationAllowed = true;
diff --git a/appserver/web/web-glue/src/main/java/com/sun/enterprise/web/WebModule.java b/appserver/web/web-glue/src/main/java/com/sun/enterprise/web/WebModule.java
index 7e11a781b85..ad8af5fc444 100644
--- a/appserver/web/web-glue/src/main/java/com/sun/enterprise/web/WebModule.java
+++ b/appserver/web/web-glue/src/main/java/com/sun/enterprise/web/WebModule.java
@@ -721,7 +721,7 @@ private JaccConfigurationFactory getJaccConfigurationFactory() {
@Override
protected Types getTypes() {
if (wmInfo.getDeploymentContext()!=null) {
- return wmInfo.getDeploymentContext().getTransientAppMetaData(Types.class.getName(), Types.class);
+ throw new IllegalStateException("getTypes() should not be called on a WebModule");
} else {
return null;
}
diff --git a/appserver/web/web-glue/src/main/java/org/glassfish/web/deployment/annotation/impl/WarScanner.java b/appserver/web/web-glue/src/main/java/org/glassfish/web/deployment/annotation/impl/WarScanner.java
index fb8e0536f3b..d5801541ca4 100644
--- a/appserver/web/web-glue/src/main/java/org/glassfish/web/deployment/annotation/impl/WarScanner.java
+++ b/appserver/web/web-glue/src/main/java/org/glassfish/web/deployment/annotation/impl/WarScanner.java
@@ -37,30 +37,21 @@
* only if the new code is made subject to such option by the copyright
* holder.
*/
-// Portions Copyright [2016-2024] [Payara Foundation and/or its affiliates]
+// Portions Copyright [2016-2025] [Payara Foundation and/or its affiliates]
package org.glassfish.web.deployment.annotation.impl;
import com.sun.enterprise.deployment.WebBundleDescriptor;
-import com.sun.enterprise.deployment.WebComponentDescriptor;
import com.sun.enterprise.deployment.annotation.impl.ModuleScanner;
-import com.sun.enterprise.deployment.web.AppListenerDescriptor;
-import com.sun.enterprise.deployment.web.ServletFilter;
-import org.glassfish.apf.impl.AnnotationUtils;
import org.glassfish.api.deployment.archive.ReadableArchive;
import org.glassfish.hk2.api.PerLookup;
import org.glassfish.hk2.classmodel.reflect.Parser;
import org.glassfish.internal.api.ClassLoaderHierarchy;
-import org.glassfish.web.deployment.descriptor.*;
import jakarta.inject.Inject;
import org.jvnet.hk2.annotations.Service;
import java.io.File;
import java.io.IOException;
-import java.util.Iterator;
-import java.util.Vector;
-import java.util.logging.Level;
-
/**
* Implementation of the Scanner interface for war.
@@ -85,7 +76,7 @@ public boolean isScanOtherLibraries() {
@Override
public void process(File archiveFile, WebBundleDescriptor webBundleDesc,
ClassLoader classLoader) throws IOException {
- throw new UnsupportedOperationException("Not supported.");
+ throw new UnsupportedOperationException("No longer supported.");
}
/**
@@ -97,116 +88,6 @@ public void process(File archiveFile, WebBundleDescriptor webBundleDesc,
@Override
public void process(ReadableArchive readableArchive, WebBundleDescriptor webBundleDesc,
ClassLoader classLoader, Parser parser) throws IOException {
-
- WebFragmentDescriptor webFragmentDesc = new WebFragmentDescriptor();
- if (webBundleDesc instanceof WebFragmentDescriptor) {
- webFragmentDesc = (WebFragmentDescriptor) webBundleDesc;
- }
- if (webFragmentDesc.isWarLibrary()) {
- this.archiveFile = new File(webFragmentDesc.getWarLibraryPath());
- } else {
- this.archiveFile = new File(readableArchive.getURI());
- }
- this.classLoader = classLoader;
- setParser(parser);
-
- if (AnnotationUtils.getLogger().isLoggable(Level.FINE)) {
- AnnotationUtils.getLogger().log(Level.FINE, "archiveFile is {0}", archiveFile);
- AnnotationUtils.getLogger().log(Level.FINE, "webBundle is {0}", webBundleDesc);
- AnnotationUtils.getLogger().log(Level.FINE, "classLoader is {0}", classLoader);
- }
-
- if (!webFragmentDesc.isWarLibrary() && !archiveFile.isDirectory()) {
- // on client side
- return;
- }
-
- if (isScanOtherLibraries()) {
- addLibraryJars(webBundleDesc, readableArchive);
- calculateResults(webBundleDesc);
- return;
- }
-
- File webinf = new File(archiveFile, "WEB-INF");
-
- if (webBundleDesc instanceof WebFragmentDescriptor) {
- if (webFragmentDesc.isWarLibrary()) {
- addScanJar(archiveFile);
- } else {
- File lib = new File(webinf, "lib");
- if (lib.exists()) {
- File jarFile = new File(lib, webFragmentDesc.getJarName());
- if (jarFile.exists()) {
- // support exploded jar file
- if (jarFile.isDirectory()) {
- addScanDirectory(jarFile);
- } else {
- addScanJar(jarFile);
- }
- }
- }
- }
- } else {
- File classes = new File(webinf, "classes");
- if (classes.exists()) {
- addScanDirectory(classes);
- }
- }
- scanXmlDefinedClassesIfNecessary(webBundleDesc);
- calculateResults(webBundleDesc);
- }
-
- // This is not mandated by the spec. It is for WSIT.
- // We will also scan any servlets/filters/listeners classes specified
- // in web.xml additionally if those classes are not resided in the wars.
- private void scanXmlDefinedClassesIfNecessary(
- WebBundleDescriptor webBundleDesc)
- throws IOException {
-
- ClassLoader commonCL = clh.getCommonClassLoader();
-
- for (Iterator webComponents =
- webBundleDesc.getWebComponentDescriptors().iterator();
- webComponents.hasNext();) {
- WebComponentDescriptor webCompDesc =
- (WebComponentDescriptor)webComponents.next();
- if (webCompDesc.isServlet()) {
- String servletName = webCompDesc.getWebComponentImplementation();
- if (isScan(servletName, commonCL)) {
- addScanClassName(servletName);
- }
- }
- }
-
- Vector servletFilters = webBundleDesc.getServletFilters();
- for (int i = 0; i < servletFilters.size(); i++) {
- ServletFilter filter = (ServletFilter)servletFilters.elementAt(i);
- String filterName = filter.getClassName();
- if (isScan(filterName, commonCL)) {
- addScanClassName(filter.getClassName());
- }
- }
-
- Vector listeners = webBundleDesc.getAppListenerDescriptors();
- for (int j = 0; j < listeners.size(); j++) {
- AppListenerDescriptor listenerDesc =
- (AppListenerDescriptor) listeners.elementAt(j);
- String listenerName = listenerDesc.getListener();
- if (isScan(listenerName, commonCL)) {
- addScanClassName(listenerDesc.getListener());
- }
- }
- }
-
- /**
- * Returns true if the class is accessible from the classloader
- * @param className
- * @param commonCL
- * @return
- * @throws IOException
- */
- private boolean isScan(String className, ClassLoader commonCL) throws IOException {
- return commonCL.getResource(className.replace(".", "/") + ".class") != null;
+ throw new UnsupportedOperationException("No longer supported.");
}
}
-
diff --git a/appserver/web/web-glue/src/main/java/org/glassfish/web/deployment/archivist/WebArchivist.java b/appserver/web/web-glue/src/main/java/org/glassfish/web/deployment/archivist/WebArchivist.java
index eca18f0b6f6..49e7df3ddac 100644
--- a/appserver/web/web-glue/src/main/java/org/glassfish/web/deployment/archivist/WebArchivist.java
+++ b/appserver/web/web-glue/src/main/java/org/glassfish/web/deployment/archivist/WebArchivist.java
@@ -37,7 +37,7 @@
* only if the new code is made subject to such option by the copyright
* holder.
*/
-// Portions Copyright [2014-2024] [Payara Foundation and/or its affiliates]
+// Portions Copyright [2014-2025] [Payara Foundation and/or its affiliates]
package org.glassfish.web.deployment.archivist;
@@ -50,10 +50,8 @@
import com.sun.enterprise.deployment.EjbDescriptor;
import com.sun.enterprise.deployment.WebComponentDescriptor;
import com.sun.enterprise.deployment.annotation.impl.ModuleScanner;
-import org.glassfish.hk2.classmodel.reflect.Parser;
-import org.glassfish.hk2.classmodel.reflect.Type;
-import org.glassfish.hk2.classmodel.reflect.Types;
import org.glassfish.internal.deployment.Deployment;
+import org.glassfish.internal.deployment.JandexIndexer;
import org.glassfish.web.deployment.annotation.impl.WarScanner;
import com.sun.enterprise.deployment.archivist.Archivist;
import com.sun.enterprise.deployment.archivist.ArchivistFor;
@@ -81,6 +79,7 @@
import java.io.File;
import java.nio.file.Path;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.LinkedHashSet;
@@ -90,7 +89,6 @@
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
-import java.util.stream.Collectors;
/**
@@ -117,6 +115,8 @@ public class WebArchivist extends Archivist {
private ArchiveFactory archiveFactory;
@Inject
private Deployment deployment;
+ @Inject
+ JandexIndexer jandexIndexer;
/**
* @return the module type handled by this archivist
@@ -368,7 +368,6 @@ protected void postAnnotationProcess(WebBundleDescriptorImpl descriptor,
ReadableArchive warArchive = null;
try {
warArchive = archiveFactory.openArchive(new File(wfDesc.getWarLibraryPath()));
- warArchive.setExtraData(Parser.class, archive.getExtraData(Parser.class));
super.readAnnotations(warArchive, wfDesc, localExtensions);
} finally {
if (warArchive != null) {
@@ -376,7 +375,10 @@ protected void postAnnotationProcess(WebBundleDescriptorImpl descriptor,
}
}
DeploymentUtils.getWarLibraryCache().putIfAbsent(wfDesc.getWarLibraryPath(),
- new DeploymentUtils.WarLibraryDescriptor(wfDesc, filterTypesByWarLibrary(wfDesc)));
+ new DeploymentUtils.WarLibraryDescriptor(wfDesc,
+ jandexIndexer.getIndexesByURI(deployment.getCurrentDeploymentContext(),
+ Collections.singleton(Path.of(wfDesc.getWarLibraryPath()).toUri()))
+ .values().stream().findAny().orElse(null)));
}
} else {
super.readAnnotations(archive, wfDesc, localExtensions);
@@ -418,15 +420,6 @@ protected void postAnnotationProcess(WebBundleDescriptorImpl descriptor,
descriptor.addDefaultWebBundleDescriptor(defaultWebBundleDescriptor);
}
- private List filterTypesByWarLibrary(WebFragmentDescriptor wfDesc) {
- Types types = deployment.getCurrentDeploymentContext().getTransientAppMetaData(Types.class.getName(), Types.class);
- if (types == null) {
- return List.of();
- }
- return types.getAllTypes().stream().filter(key -> key.wasDefinedIn(
- List.of(Path.of(wfDesc.getWarLibraryPath()).toUri()))).collect(Collectors.toList());
- }
-
/**
* This method will return the list of web fragment in the desired order.
*/
@@ -475,6 +468,9 @@ private List readStandardFragments(WebBundleDescriptorImp
}
}
wfDesc.setJarName(lib.substring(lib.lastIndexOf('/') + 1));
+ if (embeddedArchive != null) {
+ wfDesc.setName(embeddedArchive.getURI().getPath());
+ }
if (isWarLibrary) {
if (wfDesc.getClassLoader() != null) {
wfDesc.setClassLoader(wfDesc.getClassLoader().getParent());
diff --git a/appserver/web/weld-integration/src/main/java/org/glassfish/weld/BeanDeploymentArchiveImpl.java b/appserver/web/weld-integration/src/main/java/org/glassfish/weld/BeanDeploymentArchiveImpl.java
index 235ed40151a..0f1431fc7eb 100644
--- a/appserver/web/weld-integration/src/main/java/org/glassfish/weld/BeanDeploymentArchiveImpl.java
+++ b/appserver/web/weld-integration/src/main/java/org/glassfish/weld/BeanDeploymentArchiveImpl.java
@@ -47,6 +47,8 @@
import org.glassfish.api.deployment.DeploymentContext;
import org.glassfish.api.deployment.archive.ReadableArchive;
import org.glassfish.cdi.CDILoggerInfo;
+import org.glassfish.internal.api.Globals;
+import org.glassfish.internal.deployment.JandexIndexer;
import org.glassfish.weld.connector.WeldUtils;
import org.glassfish.weld.ejb.EjbDescriptorImpl;
import org.jboss.weld.bootstrap.WeldBootstrap;
@@ -66,19 +68,15 @@
import java.io.ObjectOutputStream;
import java.io.ObjectStreamException;
import java.io.Serializable;
-import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
-import java.net.URLClassLoader;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.logging.Level;
import java.util.logging.Logger;
import static java.util.logging.Level.FINE;
import static java.util.logging.Level.FINER;
import static java.util.logging.Level.SEVERE;
-import static org.glassfish.web.loader.NonCachedJarStreamHandler.forceNonCachedJarURL;
import static org.glassfish.weld.WeldDeployer.WELD_BOOTSTRAP;
import static org.glassfish.weld.connector.WeldUtils.*;
@@ -502,33 +500,7 @@ private void populate(Collection ej
if (webinfbda) {
bdaType = BDAType.WAR;
- Enumeration entries = archive.entries();
- while (entries.hasMoreElements()) {
- String entry = entries.nextElement();
- if (legalClassName(entry)) {
- if (entry.contains(WEB_INF_CLASSES)) {
- //Workaround for incorrect WARs that bundle classes above WEB-INF/classes
- //[See. GLASSFISH-16706]
- entry = entry.substring(WEB_INF_CLASSES.length() + 1);
- }
- String className = filenameToClassname(entry);
- try {
- if (hasBeansXml || isCDIAnnotatedClass(className)) {
- beanClassNames.add(className);
- beanClasses.add(getClassLoader().loadClass(className));
- }
- moduleClassNames.add(className);
- } catch (Throwable t) {
- if (logger.isLoggable(Level.WARNING)) {
- logger.log(Level.WARNING, CDILoggerInfo.ERROR_LOADING_BEAN_CLASS,
- new Object[]{className, t.toString()});
- }
- }
- } else if (entry.endsWith(BEANS_XML_FILENAME)) {
- addBeansXMLURL(archive, entry);
- }
- }
- archive.close();
+ addClassNamesFromIndex(archive, hasBeansXml);
}
// If this archive has WEB-INF/lib entry..
@@ -699,94 +671,42 @@ private void ensureWebLibJarVisibility(List webLibBDA
private void collectJarInfo(ReadableArchive archive, boolean isBeanArchive, boolean hasBeansXml)
throws IOException, ClassNotFoundException {
- if (archive != null) {
+ if (archive != null && isBeanArchive) {
if (logger.isLoggable(FINE)) {
logger.log(FINE, CDILoggerInfo.COLLECTING_JAR_INFO, new Object[]{archive.getURI()});
}
- Enumeration entries = archive.entries();
- while (entries.hasMoreElements()) {
- String entry = entries.nextElement();
- handleEntry(archive, entry, isBeanArchive, hasBeansXml);
- }
+ addClassNamesFromIndex(archive, hasBeansXml);
}
}
- private void handleEntry(ReadableArchive archive,
- String entry,
- boolean isBeanArchive,
- boolean hasBeansXml) throws ClassNotFoundException {
- if (legalClassName(entry)) {
- String className = filenameToClassname(entry);
- try {
- if (isBeanArchive) {
- // If the jar is a bean archive, or the individual class should be managed,
- // based on its annotation(s)
+ private void addClassNamesFromIndex(ReadableArchive archive, boolean hasBeansXml) {
+ Globals.getDefaultHabitat().getService(JandexIndexer.class)
+ .getIndexesByURI(context, Collections.singleton(archive.getURI()))
+ .values().stream().findAny().get().getIndex()
+ .getKnownClasses().forEach(classInfo -> {
+ String className = classInfo.name().toString();
if (hasBeansXml || isCDIAnnotatedClass(className)) {
- beanClasses.add(getClassLoader().loadClass(className));
beanClassNames.add(className);
}
- }
- // Add the class as a module class
- moduleClassNames.add(className);
- } catch (Throwable t) {
- if (logger.isLoggable(Level.WARNING)) {
- logger.log(Level.WARNING,
- CDILoggerInfo.ERROR_LOADING_BEAN_CLASS,
- new Object[]{className, t.toString()});
- }
- }
- } else if (entry.endsWith("/beans.xml")) {
- try {
- // use a throwaway classloader to load the application's beans.xml
- ClassLoader throwAwayClassLoader =
- new URLClassLoader(new URL[]{archive.getURI().toURL()}, null);
- URL beansXmlUrl = forceNonCachedJarURL(throwAwayClassLoader.getResource(entry));
- if (beansXmlUrl != null && !beansXmlURLs.contains(beansXmlUrl)) { // http://java.net/jira/browse/GLASSFISH-17157
- beansXmlURLs.add(beansXmlUrl);
- }
- } catch (MalformedURLException e) {
- if (logger.isLoggable(Level.SEVERE)) {
- logger.log(Level.SEVERE,
- CDILoggerInfo.SEVERE_ERROR_READING_ARCHIVE,
- new Object[]{e.getMessage()});
- }
- }
- }
- }
-
-
- private boolean legalClassName(String className) {
- return className.endsWith(CLASS_SUFFIX) && !className.startsWith(WEB_INF_LIB);
+ moduleClassNames.add(className);
+ });
}
-
private void collectRarInfo(ReadableArchive archive) throws IOException, ClassNotFoundException {
if (logger.isLoggable(FINE)) {
logger.log(FINE, CDILoggerInfo.COLLECTING_RAR_INFO, new Object[]{archive.getURI()});
}
Enumeration entries = archive.entries();
+ addClassNamesFromIndex(archive, false);
while (entries.hasMoreElements()) {
String entry = entries.nextElement();
if (entry.endsWith(JAR_SUFFIX)) {
ReadableArchive jarArchive = archive.getSubArchive(entry);
collectJarInfo(jarArchive, true, true);
- } else {
- handleEntry(archive, entry, true, true);
}
}
}
- private static String filenameToClassname(String filename) {
- String className = null;
- if (filename.indexOf(File.separatorChar) >= 0) {
- className = filename.replace(File.separatorChar, '.');
- } else {
- className = filename.replace(SEPARATOR_CHAR, '.');
- }
- className = className.substring(0, className.length() - 6);
- return className;
- }
-
private ClassLoader getClassLoader() {
ClassLoader cl;
if (this.context.getClassLoader() != null) {
diff --git a/appserver/web/weld-integration/src/main/java/org/glassfish/weld/WeldDeployer.java b/appserver/web/weld-integration/src/main/java/org/glassfish/weld/WeldDeployer.java
index 2bae45ddd6a..557eec86d44 100644
--- a/appserver/web/weld-integration/src/main/java/org/glassfish/weld/WeldDeployer.java
+++ b/appserver/web/weld-integration/src/main/java/org/glassfish/weld/WeldDeployer.java
@@ -888,7 +888,7 @@ private void fireProcessInjectionTargetEvents(WeldBootstrap bootstrap, Applicati
// From the spec: "The container must also fire an event for every Jakarta EE component class supporting
// injection that may be instantiated by the container at runtime". Stress on the "may".
Collection injectionTargetClassNames = WeldUtils.getInjectionTargetClassNames(
- deploymentImpl.getTypes(), beanDeploymentArchive.getKnownClasses());
+ deploymentImpl.context, beanDeploymentArchive.getKnownClasses());
for (String injectionTargetClassName : injectionTargetClassNames) {
// Don't fire twice
if (beanDeploymentArchive.getBeanClasses().contains(injectionTargetClassName)) {
diff --git a/nucleus/common/glassfish-api/src/main/java/org/glassfish/api/deployment/archive/Archive.java b/nucleus/common/glassfish-api/src/main/java/org/glassfish/api/deployment/archive/Archive.java
index 26b0007ad74..22d78c659ce 100644
--- a/nucleus/common/glassfish-api/src/main/java/org/glassfish/api/deployment/archive/Archive.java
+++ b/nucleus/common/glassfish-api/src/main/java/org/glassfish/api/deployment/archive/Archive.java
@@ -55,7 +55,7 @@
*
* @author Jerome Dochez
*/
-public interface Archive {
+public interface Archive extends AutoCloseable {
/**
* closes this archive and releases all resources
diff --git a/nucleus/common/internal-api/pom.xml b/nucleus/common/internal-api/pom.xml
index 60536d64bd4..dc418615f55 100644
--- a/nucleus/common/internal-api/pom.xml
+++ b/nucleus/common/internal-api/pom.xml
@@ -140,6 +140,11 @@
+
+ io.smallrye
+ jandex
+ ${jandex.version}
+
org.glassfish.annotations
logging-annotation-processor
diff --git a/nucleus/common/internal-api/src/main/java/org/glassfish/internal/deployment/Deployment.java b/nucleus/common/internal-api/src/main/java/org/glassfish/internal/deployment/Deployment.java
index 5d29afd4fd9..e49c05ae459 100644
--- a/nucleus/common/internal-api/src/main/java/org/glassfish/internal/deployment/Deployment.java
+++ b/nucleus/common/internal-api/src/main/java/org/glassfish/internal/deployment/Deployment.java
@@ -316,7 +316,9 @@ DeploymentContext enable(String target, Application app, ApplicationRef appRef,
* @param context deployment context
* @return the types information from the deployment artifacts
* @throws IOException if the scanning fails due to an I/O exception
+ * @deprecated replaced with Jandex indexer
*/
+ @Deprecated(forRemoval = true, since = "7.0.0")
Types getDeployableTypes(DeploymentContext context) throws IOException;
List getSniffersFromApp(Application app);
diff --git a/nucleus/common/internal-api/src/main/java/org/glassfish/internal/deployment/JandexIndexer.java b/nucleus/common/internal-api/src/main/java/org/glassfish/internal/deployment/JandexIndexer.java
new file mode 100644
index 00000000000..101c2d520ed
--- /dev/null
+++ b/nucleus/common/internal-api/src/main/java/org/glassfish/internal/deployment/JandexIndexer.java
@@ -0,0 +1,122 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright (c) [2025] Payara Foundation 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://github.com/payara/Payara/blob/main/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 glassfish/legal/LICENSE.txt.
+ *
+ * GPL Classpath Exception:
+ * The Payara Foundation designates this particular file as subject to the "Classpath"
+ * exception as provided by the Payara Foundation 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.
+ */
+package org.glassfish.internal.deployment;
+
+import org.glassfish.api.deployment.DeploymentContext;
+import org.jvnet.hk2.annotations.Contract;
+import java.io.IOException;
+import java.io.Serializable;
+import java.net.URI;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.function.BooleanSupplier;
+
+@Contract
+public interface JandexIndexer {
+ enum SettingType {
+ UNSET,
+ TRUE,
+ FALSE,
+ ;
+
+ public boolean isSet() {
+ return this != UNSET;
+ }
+
+ public boolean isTrue() {
+ return this == TRUE;
+ }
+
+ static SettingType of(BooleanSupplier supplier) {
+ return supplier.getAsBoolean() ? TRUE : FALSE;
+ }
+ }
+
+ class Index implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ private transient org.jboss.jandex.Index jandexIndex;
+ private SettingType implicitBeanArchive = SettingType.UNSET;
+ private SettingType hasCDIEnablingAnnotations = SettingType.UNSET;
+ private SettingType isValidBdaBasedOnExtensionAndBeansXml = SettingType.UNSET;
+
+ public Index(org.jboss.jandex.Index index) {
+ this.jandexIndex = index;
+ }
+
+ public org.jboss.jandex.Index getIndex() {
+ return jandexIndex;
+ }
+
+ public void setIndex(org.jboss.jandex.Index index) {
+ this.jandexIndex = index;
+ }
+
+ public boolean implicitBeanArchive(BooleanSupplier settingTypeSupplier) {
+ if (!implicitBeanArchive.isSet()) {
+ implicitBeanArchive = SettingType.of(settingTypeSupplier);
+ }
+ return implicitBeanArchive.isTrue();
+ }
+
+ public boolean hasCDIEnablingAnnotations(BooleanSupplier settingTypeSupplier) {
+ if (!hasCDIEnablingAnnotations.isSet()) {
+ hasCDIEnablingAnnotations = SettingType.of(settingTypeSupplier);
+ }
+ return hasCDIEnablingAnnotations.isTrue();
+ }
+
+ public boolean isValidBdaBasedOnExtensionAndBeansXml(BooleanSupplier settingTypeSupplier) {
+ if (!isValidBdaBasedOnExtensionAndBeansXml.isSet()) {
+ isValidBdaBasedOnExtensionAndBeansXml = SettingType.of(settingTypeSupplier);
+ }
+ return isValidBdaBasedOnExtensionAndBeansXml.isTrue();
+ }
+ }
+
+ void index(DeploymentContext deploymentContext) throws IOException;
+ void reindex(DeploymentContext deploymentContext) throws IOException;
+ boolean isJakartaEEApplication(DeploymentContext deploymentContext) throws IOException;
+ Index getRootIndex(DeploymentContext deploymentContext);
+ Map getAllIndexes(DeploymentContext deploymentContext);
+ Map getIndexesByURI(DeploymentContext deploymentContext, Collection uris);
+ boolean hasAnyAnnotations(DeploymentContext deploymentContext, List uris, String... annotations);
+}
diff --git a/nucleus/core/kernel/pom.xml b/nucleus/core/kernel/pom.xml
index bc64e629576..0bd905ad787 100755
--- a/nucleus/core/kernel/pom.xml
+++ b/nucleus/core/kernel/pom.xml
@@ -272,6 +272,11 @@
fish.payara.deployment.transformer
deployment-transformer-api
+
+ io.smallrye
+ jandex
+ ${jandex.version}
+
diff --git a/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/ApplicationLifecycle.java b/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/ApplicationLifecycle.java
index c5894174385..ee6704a111b 100644
--- a/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/ApplicationLifecycle.java
+++ b/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/ApplicationLifecycle.java
@@ -38,7 +38,7 @@
* holder.
*/
-// Portions Copyright 2016-2023 Payara Foundation and/or its affiliates.
+// Portions Copyright 2016-2025 Payara Foundation and/or its affiliates.
package com.sun.enterprise.v3.server;
@@ -51,7 +51,6 @@
import com.sun.enterprise.util.LocalStringManagerImpl;
import com.sun.enterprise.util.io.FileUtils;
import fish.payara.enterprise.config.serverbeans.DeploymentGroup;
-import fish.payara.nucleus.executorservice.PayaraExecutorService;
import org.glassfish.api.ActionReport;
import org.glassfish.api.admin.ParameterMap;
import org.glassfish.api.admin.ServerEnvironment;
@@ -90,8 +89,7 @@
import org.glassfish.hk2.classmodel.reflect.Parser;
import org.glassfish.hk2.classmodel.reflect.ParsingContext;
import org.glassfish.hk2.classmodel.reflect.Types;
-import org.glassfish.hk2.classmodel.reflect.util.CommonModelRegistry;
-import org.glassfish.hk2.classmodel.reflect.util.ResourceLocator;
+import org.glassfish.hk2.utilities.BuilderHelper;
import org.glassfish.internal.api.ClassLoaderHierarchy;
import org.glassfish.internal.data.ApplicationInfo;
import org.glassfish.internal.data.ApplicationRegistry;
@@ -104,6 +102,7 @@
import org.glassfish.internal.deployment.Deployment;
import org.glassfish.internal.deployment.DeploymentTracing;
import org.glassfish.internal.deployment.ExtendedDeploymentContext;
+import org.glassfish.internal.deployment.JandexIndexer;
import org.glassfish.internal.deployment.analysis.DeploymentSpan;
import org.glassfish.internal.deployment.analysis.SpanSequence;
import org.glassfish.internal.deployment.analysis.StructuredDeploymentTracing;
@@ -149,9 +148,6 @@
import static java.util.stream.Collectors.toMap;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
-import java.net.URISyntaxException;
-import org.glassfish.hk2.classmodel.reflect.util.ParsingConfig;
-import org.glassfish.hk2.utilities.BuilderHelper;
/**
* Application Loader is providing useful methods to load applications
@@ -198,16 +194,10 @@ public class ApplicationLifecycle implements Deployment, PostConstruct {
Events events;
@Inject
- ConfigSupport configSupport;
-
- @Inject
- CommonClassLoaderServiceImpl commonClassLoaderService;
+ private HotDeployService hotDeployService;
@Inject
- PayaraExecutorService executorService;
-
- @Inject
- private HotDeployService hotDeployService;
+ JandexIndexer jandexIndexer;
protected Logger logger = KernelLoggerInfo.getLogger();
final private static LocalStringManagerImpl localStrings = new LocalStringManagerImpl(ApplicationLifecycle.class);
@@ -397,14 +387,13 @@ public void actOn(Logger logger) {
span.start(DeploymentTracing.AppStage.CLASS_SCANNING);
- Types types = null;
if (handler.requiresAnnotationScanning(context.getSource())) {
- types = getDeployableTypes(context);
+ jandexIndexer.index(context);
}
span.finish();
- transformApplication(context, types, tracing, span);
+ transformApplication(context, tracing, span);
// containers that are started are not stopped even if
// the deployment fail, the main reason
@@ -663,132 +652,13 @@ public ApplicationInfo deploy(Collection extends Sniffer> sniffers, final Exte
}
@Override
+ @Deprecated(forRemoval = true)
@SuppressWarnings("squid:S2095")
public Types getDeployableTypes(DeploymentContext context) throws IOException {
- synchronized (context) {
- Types types = context.getTransientAppMetaData(Types.class.getName(), Types.class);
- if (types != null) {
- return types;
- }
- StructuredDeploymentTracing tracing = StructuredDeploymentTracing.load(context);
- Boolean skipScanExternalLibProp = Boolean.valueOf(context.getAppProps().getProperty(DeploymentProperties.SKIP_SCAN_EXTERNAL_LIB));
-
- Parser parser = getDeployableParser(context.getSource(), skipScanExternalLibProp, false, tracing,
- context.getLogger(), context);
- ParsingContext parsingContext = parser.getContext();
- context.addTransientAppMetaData(Types.class.getName(), parsingContext.getTypes());
- context.addTransientAppMetaData(Parser.class.getName(), parser);
- return parsingContext.getTypes();
- }
- }
-
- public Parser getDeployableParser(ReadableArchive source, boolean skipScanExternalLibProp,
- boolean modelUnAnnotatedMembers, StructuredDeploymentTracing tracing,
- Logger logger, DeploymentContext deploymentContext) throws IOException {
- Parser parser = new Parser(createBuilder(modelUnAnnotatedMembers, logger).build());
- try(ReadableArchiveScannerAdapter scannerAdapter = new ReadableArchiveScannerAdapter(parser, source)) {
- DeploymentSpan mainScanSpan = tracing.startSpan(DeploymentTracing.AppStage.CLASS_SCANNING, source.getName());
- return processParsing(skipScanExternalLibProp, tracing, parser, scannerAdapter, mainScanSpan, deploymentContext);
- }
+ throw new IllegalStateException("This method is not supported anymore");
}
- public Parser getDeployableParser(ReadableArchive source, boolean skipScanExternalLibProp,
- boolean modelUnAnnotatedMembers, StructuredDeploymentTracing tracing, Logger logger)
- throws java.io.IOException {
- Parser parser = new Parser(createBuilder(modelUnAnnotatedMembers, logger).build());
- ReadableArchiveScannerAdapter scannerAdapter = new ReadableArchiveScannerAdapter(parser, source);
- DeploymentSpan mainScanSpan = tracing.startSpan(DeploymentTracing.AppStage.CLASS_SCANNING, source.getName());
- return processParsing(source, skipScanExternalLibProp, tracing, parser, scannerAdapter, mainScanSpan);
- }
-
- public Parser processParsing(ReadableArchive source, boolean skipScanExternalLibProp,
- StructuredDeploymentTracing tracing, Parser parser,
- ReadableArchiveScannerAdapter scannerAdapter, DeploymentSpan mainScanSpan)
- throws IOException {
- try {
- parser.parse(scannerAdapter, () -> mainScanSpan.close());
- for (ReadableArchive externalLibArchive : getExternalLibraries(source, skipScanExternalLibProp)) {
- ReadableArchiveScannerAdapter libAdapter = null;
- try {
- DeploymentSpan span = tracing.startSpan(DeploymentTracing.AppStage.CLASS_SCANNING, externalLibArchive.getName());
- libAdapter = new ReadableArchiveScannerAdapter(parser, externalLibArchive);
- parser.parse(libAdapter, () -> span.close());
- } finally {
- if (libAdapter != null) {
- libAdapter.close();
- }
- }
- }
- parser.awaitTermination();
- scannerAdapter.close();
- return parser;
- } catch (InterruptedException e) {
- throw new IOException(e);
- }
- }
-
- public Parser processParsing(boolean skipScanExternalLibProp,
- StructuredDeploymentTracing tracing, Parser parser,
- ReadableArchiveScannerAdapter scannerAdapter, DeploymentSpan mainScanSpan,
- DeploymentContext deploymentContext)
- throws IOException {
- try {
- parser.parse(scannerAdapter, () -> mainScanSpan.close());
- List externalLibraries = getExternalLibraries(skipScanExternalLibProp, deploymentContext);
- for (ReadableArchive externalLibArchive : externalLibraries) {
- DeploymentSpan span = tracing.startSpan(DeploymentTracing.AppStage.CLASS_SCANNING, externalLibArchive.getName());
- try (ReadableArchiveScannerAdapter libAdapter = new ReadableArchiveScannerAdapter(parser, externalLibArchive)) {
- parser.parse(libAdapter, () -> span.close());
- }
- }
- parser.awaitTermination();
- for(ReadableArchive externalLibArchive: externalLibraries) {
- externalLibArchive.close();
- }
- return parser;
- } catch (InterruptedException | java.net.URISyntaxException e) {
- throw new IOException(e);
- }
- }
-
- public ParsingContext.Builder createBuilder(boolean modelUnAnnotatedMembers, Logger logger) {
- ResourceLocator locator = determineLocator();
- // scan the jar and store the result in the deployment context.
- ParsingContext.Builder parsingContextBuilder = new ParsingContext.Builder()
- .logger(logger)
- .executorService(executorService.getUnderlyingExecutorService())
- .config(new ParsingConfig() {
- @Override
- public Set getAnnotationsOfInterest() {
- return Collections.emptySet();
- }
-
- @Override
- public Set getTypesOfInterest() {
- return Collections.emptySet();
- }
-
- @Override
- public boolean modelUnAnnotatedMembers() {
- return modelUnAnnotatedMembers;
- }
- });
- // workaround bug in Builder
- parsingContextBuilder.locator(locator);
- return parsingContextBuilder;
- }
-
-
-
- private ResourceLocator determineLocator() {
- if (CommonModelRegistry.getInstance().canLoadResources()) {
- // common model registry will handle our external class dependencies
- return null;
- }
- return new ClassloaderResourceLocatorAdapter(commonClassLoaderService.getCommonClassLoader());
- }
-
- private void transformApplication(ExtendedDeploymentContext context, Types types,
+ private void transformApplication(ExtendedDeploymentContext context,
StructuredDeploymentTracing tracing, SpanSequence span) throws IOException {
String transformNS = System.getProperty("fish.payara.deployment.transform.namespace");
@@ -817,11 +687,9 @@ private void transformApplication(ExtendedDeploymentContext context, Types types
JakartaNamespaceDeploymentTransformer jakartaNamespaceDeploymentTransformerService =
jakartaNamespaceDeploymentTransformerOptional.get();
- if (types == null) {
- types = getDeployableTypes(context);
- }
+ jandexIndexer.index(context);
- if (!jakartaNamespaceDeploymentTransformerService.isJakartaEEApplication(types)) {
+ if (!jandexIndexer.isJakartaEEApplication(context)) {
context.getSource().close();
// DeploymentException will be thrown here if this fails
@@ -830,14 +698,10 @@ private void transformApplication(ExtendedDeploymentContext context, Types types
context.getAppProps().setProperty(ServerTags.EMPTY_BEANS_XML_MODE_ALL_PROP, Boolean.TRUE.toString());
context.setSource((FileArchive) archiveFactory.createArchive(output));
- // reset transient and module data of original deployed archive
- context.removeTransientAppMetaData(Types.class.getName());
- context.removeTransientAppMetaData(Parser.class.getName());
context.resetModuleMetaData();
tracing.register(context);
- // Rescan for the data we just removed
- getDeployableTypes(context);
+ jandexIndexer.reindex(context);
}
span.finish();
}
@@ -857,45 +721,6 @@ private void notifyLifecycleInterceptorsAfter(final ExtendedDeploymentContext.Ph
}
}
- private List getExternalLibraries(ReadableArchive source, Boolean skipScanExternalLibProp) throws IOException {
- List externalLibArchives = new ArrayList<>();
-
- if (skipScanExternalLibProp) {
- // if we skip scanning external libraries, we should just
- // return an empty list here
- return Collections.emptyList();
- }
-
- List externalLibs = DeploymentUtils.getExternalLibraries(source);
- for (URI externalLib : externalLibs) {
- externalLibArchives.add(archiveFactory.openArchive(new File(externalLib.getPath())));
- }
-
- return externalLibArchives;
- }
-
- private List getExternalLibraries(Boolean skipScanExternalLibProp,
- DeploymentContext deploymentContext)
- throws IOException, URISyntaxException {
- List externalLibArchives = new ArrayList<>();
-
- if (skipScanExternalLibProp) {
- // if we skip scanning external libraries, we should just
- // return an empty list here
- return Collections.emptyList();
- }
-
- for(URI externalLib : DeploymentUtils.getExternalLibraries(deploymentContext.getSource())) {
- externalLibArchives.add(archiveFactory.openArchive(new File(externalLib.getPath())));
- }
-
- for (URI externalLib : deploymentContext.getAppLibs()) {
- externalLibArchives.add(archiveFactory.openArchive(new File(externalLib.getPath())));
- }
-
- return externalLibArchives;
- }
-
/**
* Suspends this application.
*
@@ -2712,4 +2537,40 @@ public Thread newThread(Runnable r) {
public ExtendedDeploymentContext getCurrentDeploymentContext() {
return DeploymentUtils.getCurrentDeploymentContext();
}
+
+ @Deprecated(forRemoval = true)
+ public ParsingContext.Builder createBuilder(boolean modelUnAnnotatedMembers, Logger logger) {
+ throw new UnsupportedOperationException("Deprecated");
+ }
+
+ @Deprecated(forRemoval = true)
+ public Parser getDeployableParser(ReadableArchive source, boolean skipScanExternalLibProp,
+ boolean modelUnAnnotatedMembers, StructuredDeploymentTracing tracing,
+ Logger logger, DeploymentContext deploymentContext) throws IOException {
+ throw new UnsupportedOperationException("Deprecated");
+ }
+
+ @Deprecated(forRemoval = true)
+ public Parser getDeployableParser(ReadableArchive source, boolean skipScanExternalLibProp,
+ boolean modelUnAnnotatedMembers, StructuredDeploymentTracing tracing, Logger logger)
+ throws IOException {
+ throw new UnsupportedOperationException("Deprecated");
+ }
+
+ @Deprecated(forRemoval = true)
+ public Parser processParsing(ReadableArchive source, boolean skipScanExternalLibProp,
+ StructuredDeploymentTracing tracing, Parser parser,
+ ReadableArchiveScannerAdapter scannerAdapter, DeploymentSpan mainScanSpan)
+ throws IOException {
+ throw new UnsupportedOperationException("Deprecated");
+ }
+
+ @Deprecated(forRemoval = true)
+ public Parser processParsing(boolean skipScanExternalLibProp,
+ StructuredDeploymentTracing tracing, Parser parser,
+ ReadableArchiveScannerAdapter scannerAdapter, DeploymentSpan mainScanSpan,
+ DeploymentContext deploymentContext)
+ throws IOException {
+ throw new UnsupportedOperationException("Deprecated");
+ }
}
diff --git a/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/ClassloaderResourceLocatorAdapter.java b/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/ClassloaderResourceLocatorAdapter.java
deleted file mode 100644
index 1c268f32125..00000000000
--- a/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/ClassloaderResourceLocatorAdapter.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright (c) [2019] Payara Foundation 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://github.com/payara/Payara/blob/main/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 glassfish/legal/LICENSE.txt.
- *
- * GPL Classpath Exception:
- * The Payara Foundation designates this particular file as subject to the "Classpath"
- * exception as provided by the Payara Foundation 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.
- */
-
-package com.sun.enterprise.v3.server;
-
-import org.glassfish.hk2.classmodel.reflect.util.ResourceLocator;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.stream.Stream;
-
-class ClassloaderResourceLocatorAdapter implements ResourceLocator {
- private static String[] BLACKLIST = {"java/","com/sun"};
-
- private ClassLoader delegate;
-
- ClassloaderResourceLocatorAdapter(ClassLoader delegate) {
- this.delegate = delegate;
- }
-
- @Override
- public InputStream openResourceStream(String name) throws IOException {
- return isAllowed(name) ? delegate.getResourceAsStream(name) : null;
- }
-
- @Override
- public URL getResource(String name) {
- return isAllowed(name) ? delegate.getResource(name) : null;
- }
-
- private static boolean isAllowed(String name) {
- return Stream.of(BLACKLIST).noneMatch(p -> name.startsWith(p));
- }
-}
diff --git a/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/SnifferManagerImpl.java b/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/SnifferManagerImpl.java
index 1889421068f..4449b2e2688 100644
--- a/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/SnifferManagerImpl.java
+++ b/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/SnifferManagerImpl.java
@@ -42,8 +42,9 @@
package com.sun.enterprise.v3.server;
import org.glassfish.hk2.api.ServiceLocator;
-import org.glassfish.hk2.classmodel.reflect.*;
import jakarta.inject.Inject;
+import org.glassfish.hk2.classmodel.reflect.Types;
+import org.glassfish.internal.deployment.JandexIndexer;
import org.jvnet.hk2.annotations.Service;
import org.glassfish.api.deployment.DeploymentContext;
import org.glassfish.api.container.Sniffer;
@@ -75,6 +76,8 @@ public class SnifferManagerImpl implements SnifferManager {
@Inject
protected ServiceLocator habitat;
+ @Inject
+ JandexIndexer jandexIndexer;
/**
* Returns all the presently registered sniffers
@@ -132,17 +135,16 @@ public Collection getSniffers(DeploymentContext context) {
ReadableArchive archive = context.getSource();
ArchiveHandler handler = context.getArchiveHandler();
List uris = handler.getClassPathURIs(archive);
- Types types = context.getTransientAppMetaData(Types.class.getName(), Types.class);
- return getSniffers(context, uris, types);
+ return getSniffers(context, uris, null);
}
- public Collection getSniffers(DeploymentContext context, List uris, Types types) {
+ public Collection getSniffers(DeploymentContext context, List uris, @Deprecated Types types) {
// it is important to keep an ordered sequence here to keep sniffers
Collection regularSniffers = getSniffers();
// in their natural order.
// scan for registered annotations and retrieve applicable sniffers
- List appSniffers = this.getApplicableSniffers(context, uris, types, regularSniffers, true);
+ List appSniffers = this.getApplicableSniffers(context, uris, regularSniffers);
// call handles method of the sniffers
for (Sniffer sniffer : regularSniffers) {
@@ -153,7 +155,7 @@ public Collection getSniffers(DeploymentContext context, List uris
return appSniffers;
}
- private List getApplicableSniffers(DeploymentContext context, List uris, Types types, Collection sniffers, boolean checkPath) {
+ private List getApplicableSniffers(DeploymentContext context, List uris, Collection sniffers) {
ArchiveType archiveType = habitat.getService(ArchiveType.class, context.getArchiveHandler().getArchiveType());
if (sniffers == null || sniffers.isEmpty()) {
@@ -166,37 +168,8 @@ private List getApplicableSniffers(DeploymentContext cont
continue;
}
String[] annotationNames = sniffer.getAnnotationNames(context);
- if (annotationNames == null || types == null) {
- continue;
- }
- for (String annotationName : annotationNames) {
- types.getAllTypes().stream()
- .filter(type -> type instanceof AnnotationType && type.getName().equals(annotationName))
- .findFirst().ifPresent(type -> {
- Collection elements = ((AnnotationType) type).allAnnotatedTypes();
- for (AnnotatedElement element : elements) {
- if (checkPath) {
- Type t;
- if (element instanceof Member) {
- t = ((Member) element).getDeclaringType();
- } else if (element instanceof Type) {
- t = (Type) element;
- } else if (element instanceof ParameterizedType) {
- t = ((ParameterizedType) element).getType();
- } else {
- LOGGER.log(Level.WARNING, "Unrecognised type: {0}.", element);
- continue;
- }
- if (t.wasDefinedIn(uris)) {
- result.add(sniffer);
- break;
- }
- } else {
- result.add(sniffer);
- break;
- }
- }
- });
+ if (annotationNames != null && jandexIndexer.hasAnyAnnotations(context, uris, annotationNames)) {
+ result.add(sniffer);
}
}
return result;
diff --git a/nucleus/deployment/common/src/main/java/com/sun/enterprise/deployment/deploy/shared/InputJarArchive.java b/nucleus/deployment/common/src/main/java/com/sun/enterprise/deployment/deploy/shared/InputJarArchive.java
index dde28643747..e4e628490d0 100644
--- a/nucleus/deployment/common/src/main/java/com/sun/enterprise/deployment/deploy/shared/InputJarArchive.java
+++ b/nucleus/deployment/common/src/main/java/com/sun/enterprise/deployment/deploy/shared/InputJarArchive.java
@@ -37,7 +37,7 @@
* only if the new code is made subject to such option by the copyright
* holder.
*/
-// Portions Copyright [2022] Payara Foundation and/or affiliates
+// Portions Copyright [2022-2025] Payara Foundation and/or affiliates
package com.sun.enterprise.deployment.deploy.shared;
@@ -51,6 +51,7 @@
import java.io.*;
import org.glassfish.hk2.utilities.CleanerFactory;
import java.util.*;
+import java.util.concurrent.atomic.LongAccumulator;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarInputStream;
@@ -780,5 +781,11 @@ private void populateEntries() {
e = null;
}
}
-}
+ @Override
+ public long getArchiveCrc() {
+ LongAccumulator checksum = new LongAccumulator(Long::sum, 0);
+ jarFile.entries().asIterator().forEachRemaining(entry -> checksum.accumulate(entry.getCrc()));
+ return checksum.get();
+ }
+}
diff --git a/nucleus/deployment/common/src/main/java/com/sun/enterprise/deployment/deploy/shared/JarArchive.java b/nucleus/deployment/common/src/main/java/com/sun/enterprise/deployment/deploy/shared/JarArchive.java
index a7635c71f2d..483b6609e50 100644
--- a/nucleus/deployment/common/src/main/java/com/sun/enterprise/deployment/deploy/shared/JarArchive.java
+++ b/nucleus/deployment/common/src/main/java/com/sun/enterprise/deployment/deploy/shared/JarArchive.java
@@ -37,6 +37,7 @@
* only if the new code is made subject to such option by the copyright
* holder.
*/
+// Portions Copyright [2025] Payara Foundation and/or affiliates
package com.sun.enterprise.deployment.deploy.shared;
@@ -44,11 +45,12 @@
import java.net.URI;
import org.glassfish.api.deployment.archive.Archive;
import org.glassfish.api.deployment.archive.ReadableArchive;
+import org.glassfish.hk2.classmodel.reflect.Parser;
+import org.glassfish.hk2.classmodel.reflect.Types;
import java.util.Enumeration;
import java.util.Vector;
import java.util.Map;
import java.util.HashMap;
-import java.util.zip.ZipEntry;
import java.util.jar.JarEntry;
import java.io.IOException;
@@ -166,14 +168,23 @@ public ReadableArchive getParentArchive() {
* type dataType registered.
*/
public synchronized U getExtraData(Class dataType) {
+ if (dataType == Types.class || dataType == Parser.class) {
+ throw new IllegalArgumentException("Cannot set Types or Parser as extra data - Deprecated");
+ }
return dataType.cast(extraData.get(dataType));
}
public synchronized void setExtraData(Class dataType, U instance) {
+ if (dataType == Types.class || dataType == Parser.class) {
+ throw new IllegalArgumentException("Cannot set Types or Parser as extra data - Deprecated");
+ }
extraData.put(dataType, instance);
}
public synchronized void removeExtraData(Class dataType) {
+ if (dataType == Types.class || dataType == Parser.class) {
+ throw new IllegalArgumentException("Cannot set Types or Parser as extra data - Deprecated");
+ }
extraData.remove(dataType);
}
@@ -194,4 +205,8 @@ public T getArchiveMetaData(String metaDataKey, Class metadataType) {
public void removeArchiveMetaData(String metaDataKey) {
archiveMetaData.remove(metaDataKey);
}
+
+ public long getArchiveCrc() {
+ throw new UnsupportedOperationException("Not Supported");
+ }
}
diff --git a/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/DeploymentContextImpl.java b/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/DeploymentContextImpl.java
index 573f185fa7a..8b6b4e8cda6 100644
--- a/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/DeploymentContextImpl.java
+++ b/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/DeploymentContextImpl.java
@@ -37,7 +37,7 @@
* only if the new code is made subject to such option by the copyright
* holder.
*/
-// Portions Copyright [2019-2024] Payara Foundation and/or affiliates
+// Portions Copyright [2019-2025] Payara Foundation and/or affiliates
package org.glassfish.deployment.common;
@@ -51,12 +51,16 @@
import org.glassfish.api.deployment.archive.ReadableArchive;
import org.glassfish.api.deployment.archive.ArchiveHandler;
import org.glassfish.api.admin.ServerEnvironment;
+import org.glassfish.hk2.classmodel.reflect.Parser;
+import org.glassfish.hk2.classmodel.reflect.Types;
import org.glassfish.internal.api.ClassLoaderHierarchy;
import org.glassfish.internal.deployment.*;
import org.glassfish.loader.util.ASClassLoaderUtil;
import java.lang.ref.WeakReference;
import java.util.*;
+import java.util.function.BiFunction;
+import java.util.function.Function;
import java.util.logging.Logger;
import java.io.File;
import java.io.IOException;
@@ -76,8 +80,6 @@
import static java.util.logging.Level.FINEST;
import org.glassfish.api.deployment.DeployCommandParameters;
import org.glassfish.hk2.api.ServiceLocator;
-import org.glassfish.hk2.classmodel.reflect.Parser;
-import org.glassfish.hk2.classmodel.reflect.Types;
import org.glassfish.internal.api.Globals;
import org.glassfish.logging.annotation.LoggerInfo;
@@ -118,7 +120,49 @@ public class DeploymentContextImpl implements ExtendedDeploymentContext, PreDest
Phase phase = Phase.UNKNOWN;
WeakReference sharableTemp = null;
Map modulePropsMap = new HashMap();
- Map transientAppMetaData = new HashMap();
+ Map transientAppMetaData = new HashMap<>() {
+ @Override
+ public Object get(Object key) {
+ check(key);
+ return super.get(key);
+ }
+
+ @Override
+ public Object put(String key, Object value) {
+ check(key);
+ return super.put(key, value);
+ }
+
+ @Override
+ public Object putIfAbsent(String key, Object value) {
+ check(key);
+ return super.putIfAbsent(key, value);
+ }
+
+ @Override
+ public Object compute(String key, BiFunction super String, ? super Object, ?> remappingFunction) {
+ check(key);
+ return super.compute(key, remappingFunction);
+ }
+
+ @Override
+ public Object computeIfAbsent(String key, Function super String, ?> mappingFunction) {
+ check(key);
+ return super.computeIfAbsent(key, mappingFunction);
+ }
+
+ @Override
+ public Object computeIfPresent(String key, BiFunction super String, ? super Object, ?> remappingFunction) {
+ check(key);
+ return super.computeIfPresent(key, remappingFunction);
+ }
+
+ private void check(Object key) {
+ if (key.equals(Types.class.getName()) || key.equals(Parser.class.getName())) {
+ throw new IllegalArgumentException("Cannot access " + key + " in transient metadata");
+ }
+ }
+ };
Map moduleArchiveHandlers = new HashMap();
Map moduleDeploymentContexts = new HashMap();
ExtendedDeploymentContext parentContext = null;
@@ -724,11 +768,6 @@ public void postDeployClean(boolean isFinalClean) {
if (isFinalClean) {
transientAppMetaData.clear();
} else {
- final String [] classNamesToClean = {Types.class.getName(), Parser.class.getName()};
-
- for (String className : classNamesToClean) {
- transientAppMetaData.remove(className);
- }
com.sun.enterprise.deploy.shared.FileArchive.clearCache();
}
}
diff --git a/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/DeploymentUtils.java b/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/DeploymentUtils.java
index ae86f5d23fd..c510ad228d6 100644
--- a/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/DeploymentUtils.java
+++ b/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/DeploymentUtils.java
@@ -37,7 +37,7 @@
* only if the new code is made subject to such option by the copyright
* holder.
*/
-// Portions Copyright [2018-2024] Payara Foundation and/or affiliates
+// Portions Copyright [2018-2025] Payara Foundation and/or affiliates
package org.glassfish.deployment.common;
@@ -54,7 +54,6 @@
import fish.payara.enterprise.config.serverbeans.DeploymentGroup;
import org.glassfish.api.deployment.DeploymentContext;
import org.glassfish.hk2.api.ServiceLocator;
-import org.glassfish.hk2.classmodel.reflect.Type;
import org.glassfish.internal.deployment.ExtendedDeploymentContext;
import org.glassfish.loader.util.ASClassLoaderUtil;
@@ -85,6 +84,7 @@
import org.glassfish.logging.annotation.LogMessageInfo;
+import static org.glassfish.internal.deployment.JandexIndexer.Index;
/**
* Utility methods for deployment.
@@ -117,19 +117,19 @@ public class DeploymentUtils {
public static class WarLibraryDescriptor {
private final Descriptor descriptor;
- private final List types;
+ private final Index index;
- public WarLibraryDescriptor(Descriptor descriptor, List types) {
+ public WarLibraryDescriptor(Descriptor descriptor, Index index) {
this.descriptor = descriptor;
- this.types = types;
+ this.index = index;
}
public Descriptor getDescriptor() {
return descriptor;
}
- public List getTypes() {
- return types;
+ public Index getIndex() {
+ return index;
}
}
diff --git a/pom.xml b/pom.xml
index 8e543487d17..ed4b5b6a1bc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -287,6 +287,7 @@
2.19.0
3.1.10.payara-p1
3.0.2
+ 3.3.1
8.0.1.Final.payara-p1
8.0.1.Final
4.0.2