Skip to content

Commit

Permalink
fixed web initializers
Browse files Browse the repository at this point in the history
  • Loading branch information
lprimak committed Feb 14, 2025
1 parent aa27959 commit 7ed90c6
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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);
}
Expand Down Expand Up @@ -166,14 +169,14 @@ private boolean hasFacesEnablingClass(DeploymentContext context) {
Map<Class<? extends ServletContainerInitializer>, Set<Class<?>>> initialiserList =
ServletContainerInitializerUtil.getInitializerList(
facesInitialisers, interestList,
getTypes(context),
jandexIndexer.getAllIndexes(context),
Utility.getClassLoader(), false);

for (Map.Entry<Class<? extends ServletContainerInitializer>, Set<Class<?>>> initialiserEntry : initialiserList.entrySet()) {
if (initialiserEntry.getValue() != null && !initialiserEntry.getValue().isEmpty()) {
if (logger.isLoggable(Level.FINE)) {
List<String> 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()));
Expand All @@ -200,26 +203,4 @@ private List<ServletContainerInitializer> 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;
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -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.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.Index;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
Expand Down Expand Up @@ -230,6 +233,15 @@ public static Map<Class<?>, List<Class<? extends ServletContainerInitializer>>>
return interestList;
}

@Deprecated
public static Map<Class<? extends ServletContainerInitializer>, Set<Class<?>>> getInitializerList(
Iterable<ServletContainerInitializer> initializers,
Map<Class<?>, List<Class<? extends ServletContainerInitializer>>> 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
Expand All @@ -245,7 +257,7 @@ public static Map<Class<?>, List<Class<? extends ServletContainerInitializer>>>
public static Map<Class<? extends ServletContainerInitializer>, Set<Class<?>>> getInitializerList(
Iterable<ServletContainerInitializer> initializers,
Map<Class<?>, List<Class<? extends ServletContainerInitializer>>> interestList,
Types types,
Map<String, Index> indexMap,
ClassLoader cl, boolean isStandalone) {

if (interestList == null) {
Expand Down Expand Up @@ -281,7 +293,7 @@ public static Map<Class<? extends ServletContainerInitializer>, Set<Class<?>>>
* 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;
Expand Down Expand Up @@ -350,7 +362,7 @@ public static Map<Class<? extends ServletContainerInitializer>, Set<Class<?>>>

initializerList = checkAgainstInterestList(classInfo, interestList, initializerList, cl, isStandalone);
} else {
initializerList = checkAgainstInterestList(types, interestList, initializerList, cl, isStandalone);
initializerList = checkAgainstInterestList(indexMap, interestList, initializerList, cl, isStandalone);
}
}

Expand Down Expand Up @@ -440,66 +452,30 @@ private static void scanDirectory(File dir, ClassDependencyBuilder classInfo) {
*
*/
private static Map<Class<? extends ServletContainerInitializer>, Set<Class<?>>> checkAgainstInterestList(
Types classInfo,
Map<String, Index> indexMap,
Map<Class<?>, List<Class<? extends ServletContainerInitializer>>> interestList,
Map<Class<? extends ServletContainerInitializer>, Set<Class<?>>> initializerList,
ClassLoader cl, boolean isStandalone) {

if (classInfo==null) {
if (indexMap==null) {
return initializerList;
}
for (Map.Entry<Class<?>, List<Class<? extends ServletContainerInitializer>>> e:
interestList.entrySet()) {

Class<?> c = e.getKey();
Type type = classInfo.getBy(c.getName());
if (type==null)
continue;

Set<Class<?>> resultSet = new HashSet<Class<?>>();
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<ClassModel> 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.getAllKnownImplementors(e.getKey()).forEach(classInfo -> addClassToResult(classInfo, cl, isStandalone, resultSet));
index.getAllKnownSubclasses(e.getKey()).forEach(classInfo -> addClassToResult(classInfo, cl, isStandalone, resultSet));
index.getAnnotations(e.getKey()).forEach(annotation ->
addClassToResult(mapAnnotationToClassName(annotation), cl, isStandalone, resultSet));
}

List<Class<? extends ServletContainerInitializer>> containerInitializers = e.getValue();
for(Class<? extends ServletContainerInitializer> initializer : containerInitializers) {
Set<Class<?>> classSet = initializerList.get(initializer);
if(classSet == null) {
classSet = new HashSet<Class<?>>();
classSet = new HashSet<>();
}
classSet.addAll(resultSet);
initializerList.put(initializer, classSet);
Expand All @@ -509,6 +485,55 @@ private static Map<Class<? extends ServletContainerInitializer>, Set<Class<?>>>

return initializerList;
}

private static void addClassToResult(ClassInfo classInfo, ClassLoader cl,
boolean isStandalone, Set<Class<?>> resultSet) {
addClassToResult(classInfo.name().toString(), cl, isStandalone, resultSet);
}

private static void addClassToResult(String className, ClassLoader cl,
boolean isStandalone, Set<Class<?>> 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<Class<?>, List<Class<? extends ServletContainerInitializer>>> interestList =
ServletContainerInitializerUtil.getInterestList(
servletContainerInitializers);
Map<Class<? extends ServletContainerInitializer>, Set<Class<?>>> initializerList =
ServletContainerInitializerUtil.getInitializerList(
servletContainerInitializers, interestList,
null,
getClassLoader(), isStandalone());
ServiceLocator locator = org.glassfish.internal.api.Globals.getDefaultHabitat();
var deploymentContext = locator.getService(Deployment.class).getCurrentDeploymentContext();

Map<Class<? extends ServletContainerInitializer>, Set<Class<?>>> initializerList = null;
if (deploymentContext != null && deploymentContext.getPhase() != ExtendedDeploymentContext.Phase.PREPARE) {
// Get the list of ServletContainerInitializers and the classes
// they are interested in
Map<Class<?>, List<Class<? extends ServletContainerInitializer>>> 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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,9 @@ public void initialize(ApplicationInfo appInfo, Collection<? extends Sniffer> sn
if(appInfo == null) {
return;
}
if (currentDeploymentContext.get().peek() != context) {
currentDeploymentContext.get().push(context);
}
appRegistry.removeTransient(appInfo.getName());
final ActionReport report = context.getActionReport();
ProgressTracker tracker = context.getTransientAppMetaData(ExtendedDeploymentContext.TRACKER, ProgressTracker.class);
Expand Down

0 comments on commit 7ed90c6

Please sign in to comment.