Skip to content

Commit

Permalink
bugfix: fix EAR deployment failure when multiple WARs use multible CD…
Browse files Browse the repository at this point in the history
…I-enabled library JARs

- correctly copy BDA sets for each war in EAR
- Make WAR's CDI beans available in EAR-libs
- read web-fragment.xml from EAR-libs
- processing ear-lib manifest
- de-duplicate BDAs in CDI processing by using LinkedHashSet intead of ArrayList
- made some structures final (cleanup)
- fixed ear and concurrent classloader leaks
  • Loading branch information
lprimak committed Dec 12, 2024
1 parent ba7a20f commit de830ba
Show file tree
Hide file tree
Showing 21 changed files with 942 additions and 527 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
* only if the new code is made subject to such option by the copyright
* holder.
*/
// Portions Copyright [2016-2023] [Payara Foundation and/or its affiliates]
// Portions Copyright [2016-2024] [Payara Foundation and/or its affiliates]

package org.glassfish.concurrent.runtime;

Expand Down Expand Up @@ -378,9 +378,7 @@ public void reset(ContextHandle contextHandle) {
restorer.endContext();
}

if (handle.getContextClassLoader() != null) {
Utility.setContextClassLoader(handle.getContextClassLoader());
}
Utility.setContextClassLoader(handle.getContextClassLoader());
if (handle.getSecurityContext() != null) {
SecurityContext.setCurrent(handle.getSecurityContext());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
* only if the new code is made subject to such option by the copyright
* holder.
*/
// Portions Copyright [2024] [Payara Foundation and/or its affiliates]

package org.glassfish.javaee.full.deployment;

Expand Down Expand Up @@ -101,7 +102,7 @@
@Service
@PerLookup
public class EarDeployer implements Deployer {

public static final String PER_BDA_METADATA_KEY = "[PerBDA]";
// private static final Class GLASSFISH_APPCLIENT_GROUP_FACADE_CLASS =
// org.glassfish.appclient.client.AppClientGroupFacade.class;
// Currently using a string instead of a Class constant to avoid a circular
Expand Down Expand Up @@ -457,15 +458,21 @@ public <U extends OpsParams> U getCommandParameters(Class<U> commandParametersTy
@Override
public void addTransientAppMetaData(String metaDataKey,
Object metaData) {
context.addTransientAppMetaData(metaDataKey,
metaData);
if (metaDataKey.startsWith(PER_BDA_METADATA_KEY)) {
super.addTransientAppMetaData(metaDataKey, metaData);
} else {
context.addTransientAppMetaData(metaDataKey, metaData);
}
}

@Override
public <T> T getTransientAppMetaData(String metaDataKey,
Class<T> metadataType) {
return context.getTransientAppMetaData(metaDataKey,
metadataType);
if (metaDataKey.startsWith(PER_BDA_METADATA_KEY)) {
return super.getTransientAppMetaData(metaDataKey, metadataType);
} else {
return context.getTransientAppMetaData(metaDataKey, metadataType);
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,60 +42,49 @@

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
* @deprecated This class is not used and will be removed in a future release.
* Functionality has been moved to {@link com.sun.enterprise.loader.CachingReflectionUtil}.
*/
@Deprecated(forRemoval = true)
public class CachingReflectionUtil {
private static final Logger logger = LogFacade.getLogger();
private static final Map<String, Class<?>> classCache = new ConcurrentHashMap<>();
private static final Map<String, Method> methodCache = new ConcurrentHashMap<>();
private static final Map<String, Field> fieldCache = new ConcurrentHashMap<>();

/**
* @deprecated This method is not used and will be removed in a future release.
* Functionality has been moved to {@link com.sun.enterprise.loader.CachingReflectionUtil}.
* @param className
* @param classLoader
* @return
*/
@Deprecated(forRemoval = true)
public static Class<?> getClassFromCache(String className, ClassLoader classLoader) {
var cls = classCache.computeIfAbsent(className, k -> {
try {
return classLoader.loadClass(className);
} catch (ClassNotFoundException e) {
logger.log(Level.FINE, "Class not found: " + className, e);
return null;
}
});
return cls;
return com.sun.enterprise.loader.CachingReflectionUtil.getClassFromCache(className, classLoader);
}

/**
* @deprecated This method is not used and will be removed in a future release.
* Functionality has been moved to {@link com.sun.enterprise.loader.CachingReflectionUtil}.
* @param cls
* @param methodName
* @param isPrivate
* @param parameterTypes
* @return
*/
@Deprecated(forRemoval = true)
public static Method getMethodFromCache(Class<?> cls, String methodName, boolean isPrivate, Class<?>... parameterTypes) {
return methodCache.computeIfAbsent(methodName, k -> {
try {
if (isPrivate) {
Method method = cls.getDeclaredMethod(methodName, parameterTypes);
method.setAccessible(true);
return method;
} else {
return cls.getMethod(methodName, parameterTypes);
}
} catch (NoSuchMethodException e) {
logger.log(Level.FINE, "Method not found: " + methodName, e);
return null;
}
});
return com.sun.enterprise.loader.CachingReflectionUtil.getMethodFromCache(cls, methodName, isPrivate, parameterTypes);
}

/**
* @deprecated This method is not used and will be removed in a future release.
* Functionality has been moved to {@link com.sun.enterprise.loader.CachingReflectionUtil}.
* @param cls
* @param fieldName
* @param isPrivate
* @return
*/
@Deprecated(forRemoval = true)
public static Field getFieldFromCache(Class<?> cls, String fieldName, boolean isPrivate) {
return fieldCache.computeIfAbsent(fieldName, k -> {
try {
if (isPrivate) {
Field field = cls.getDeclaredField(fieldName);
field.setAccessible(true);
return field;
} else {
return cls.getField(fieldName);
}
} catch (NoSuchFieldException e) {
logger.log(Level.FINE, "Field not found: " + fieldName, e);
return null;
}
});
return com.sun.enterprise.loader.CachingReflectionUtil.getFieldFromCache(cls, fieldName, isPrivate);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
import com.sun.enterprise.deployment.Application;
import com.sun.enterprise.deployment.util.DOLUtils;
import com.sun.enterprise.glassfish.bootstrap.MainHelper.HotSwapHelper;
import com.sun.enterprise.loader.CacheCleaner;
import com.sun.enterprise.security.integration.DDPermissionsLoader;
import com.sun.enterprise.security.integration.PermsHolder;
import com.sun.enterprise.util.io.FileUtils;
Expand Down Expand Up @@ -2051,7 +2052,7 @@ public void stop() throws Exception {
// START SJSAS 6258619
ClassLoaderUtil.releaseLoader(this);
// END SJSAS 6258619
clearJaxRSCache();
CacheCleaner.clearJaxRSCache(this);

synchronized(jarFilesLock) {
started = false;
Expand Down Expand Up @@ -2658,23 +2659,6 @@ private void clearReferencesRmiTargets() {
}
}

private void clearJaxRSCache() {
try {
Class<?> cdiComponentProvider = CachingReflectionUtil
.getClassFromCache("org.glassfish.jersey.ext.cdi1x.internal.CdiComponentProvider", this);
if (cdiComponentProvider != null) {
Field runtimeSpecificsField = CachingReflectionUtil.getFieldFromCache(cdiComponentProvider,
"runtimeSpecifics", true);
Object runtimeSpecifics = runtimeSpecificsField.get(null);
CachingReflectionUtil.getMethodFromCache(runtimeSpecifics.getClass(),
"clearJaxRsResource", true, ClassLoader.class)
.invoke(runtimeSpecifics, this);
}
} catch (Exception e) {
logger.log(Level.WARNING, "Error clearing Jax-Rs cache", e);
}
}

/**
* Clear the {@link ResourceBundle} cache of any bundles loaded by this
* class loader or any class loader where this loader is a parent class
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,12 @@
* only if the new code is made subject to such option by the copyright
* holder.
*/
// Portions Copyright [2014-2021] [Payara Foundation and/or its affiliates]
// Portions Copyright [2014-2024] [Payara Foundation and/or its affiliates]

package org.glassfish.web.deployment.archivist;

import com.sun.enterprise.deployment.Application;
import com.sun.enterprise.deployment.EarType;
import org.glassfish.deployment.common.RootDeploymentDescriptor;
import com.sun.enterprise.deployment.EjbBundleDescriptor;
import com.sun.enterprise.deployment.EjbDescriptor;
Expand Down Expand Up @@ -75,9 +76,10 @@
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.Set;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
Expand Down Expand Up @@ -296,24 +298,33 @@ protected String getArchiveExtension() {
/**
* @return a list of libraries included in the archivist
*/
public Vector<String> getLibraries(Archive archive) {
public Set<String> getLibraries(ReadableArchive archive) throws IOException {
Set<String> libraries = new LinkedHashSet<>();
// WAR libraries
extractLibraries(archive, true, libraries);
ReadableArchive parentArchive = archive.getParentArchive();
if (parentArchive != null && parentArchive.getExtraData(ArchiveType.class).toString().equals(EarType.ARCHIVE_TYPE)) {
// EAR shared libraries
extractLibraries(parentArchive.getSubArchive("lib"), false, libraries);
}
return libraries;
}

Enumeration<String> entries = archive.entries();
private static void extractLibraries(Archive archive, boolean hasWebInfPrefix, Set<String> libs) {
Enumeration<String> entries = archive != null ? archive.entries() : null;
if (entries==null)
return null;
return;

Vector<String> libs = new Vector<String>();
while (entries.hasMoreElements()) {

String entryName = entries.nextElement();
if (!entryName.startsWith("WEB-INF/lib")) {
continue; // not in WEB-INF...
if (hasWebInfPrefix && !entryName.startsWith("WEB-INF/lib")) {
continue; // not in prefix (i.e. WEB-INF)...
}
if (entryName.endsWith(".jar")) {
libs.add(entryName);
}
}
return libs;
}

@Override
Expand Down Expand Up @@ -381,54 +392,50 @@ private List<WebFragmentDescriptor> readStandardFragments(WebBundleDescriptorImp
ReadableArchive archive) throws IOException {

List<WebFragmentDescriptor> wfList = new ArrayList<WebFragmentDescriptor>();
Vector libs = getLibraries(archive);
if (libs != null && libs.size() > 0) {

for (int i = 0; i < libs.size(); i++) {
String lib = (String)libs.get(i);
Archivist wfArchivist = new WebFragmentArchivist(this, habitat);
wfArchivist.setRuntimeXMLValidation(this.getRuntimeXMLValidation());
wfArchivist.setRuntimeXMLValidationLevel(
this.getRuntimeXMLValidationLevel());
wfArchivist.setAnnotationProcessingRequested(false);

WebFragmentDescriptor wfDesc = null;
ReadableArchive embeddedArchive = archive.getSubArchive(lib);
try {
if (embeddedArchive != null &&
wfArchivist.hasStandardDeploymentDescriptor(embeddedArchive)) {
try {
wfDesc = (WebFragmentDescriptor)wfArchivist.open(embeddedArchive);
} catch(SAXParseException ex) {
IOException ioex = new IOException();
ioex.initCause(ex);
throw ioex;
}
} else {
wfDesc = new WebFragmentDescriptor();
wfDesc.setExists(false);
}
} finally {
if (embeddedArchive != null) {
embeddedArchive.close();
for (String lib : getLibraries(archive)) {
Archivist wfArchivist = new WebFragmentArchivist(this, habitat);
wfArchivist.setRuntimeXMLValidation(this.getRuntimeXMLValidation());
wfArchivist.setRuntimeXMLValidationLevel(
this.getRuntimeXMLValidationLevel());
wfArchivist.setAnnotationProcessingRequested(false);

WebFragmentDescriptor wfDesc = null;
ReadableArchive embeddedArchive = lib.startsWith("WEB-INF")
? archive.getSubArchive(lib) : archive.getParentArchive().getSubArchive("lib").getSubArchive(lib);
try {
if (embeddedArchive != null &&
wfArchivist.hasStandardDeploymentDescriptor(embeddedArchive)) {
try {
wfDesc = (WebFragmentDescriptor)wfArchivist.open(embeddedArchive);
} catch(SAXParseException ex) {
IOException ioex = new IOException();
ioex.initCause(ex);
throw ioex;
}
} else {
wfDesc = new WebFragmentDescriptor();
wfDesc.setExists(false);
}
} finally {
if (embeddedArchive != null) {
embeddedArchive.close();
}
wfDesc.setJarName(lib.substring(lib.lastIndexOf('/') + 1));
wfList.add(wfDesc);
}
wfDesc.setJarName(lib.substring(lib.lastIndexOf('/') + 1));
wfList.add(wfDesc);

descriptor.putJarNameWebFragmentNamePair(wfDesc.getJarName(), wfDesc.getName());
descriptor.putJarNameWebFragmentNamePair(wfDesc.getJarName(), wfDesc.getName());

}
}

if (((WebBundleDescriptorImpl)descriptor).getAbsoluteOrderingDescriptor() != null) {
wfList = ((WebBundleDescriptorImpl)descriptor).getAbsoluteOrderingDescriptor().order(wfList);
} else {
OrderingDescriptor.sort(wfList);
}
if (((WebBundleDescriptorImpl)descriptor).getAbsoluteOrderingDescriptor() != null) {
wfList = ((WebBundleDescriptorImpl)descriptor).getAbsoluteOrderingDescriptor().order(wfList);
} else {
OrderingDescriptor.sort(wfList);
}

for (WebFragmentDescriptor wf : wfList) {
descriptor.addOrderedLib(wf.getJarName());
}
for (WebFragmentDescriptor wf : wfList) {
descriptor.addOrderedLib(wf.getJarName());
}

return wfList;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
* only if the new code is made subject to such option by the copyright
* holder.
*
* Portions Copyright [2017-2019] Payara Foundation and/or affiliates
* Portions Copyright [2017-2024] Payara Foundation and/or affiliates
*/

package org.glassfish.weld;
Expand Down Expand Up @@ -108,11 +108,11 @@ public ClassLoader run()
@Override
public T get( String id )
{
ClassLoader acl = getClassLoader();
T instance = store.get(acl);
T instance = storeById.get(id);
if (instance == null)
{
instance = storeById.get(id);
ClassLoader acl = getClassLoader();
instance = store.get(acl);
if (instance == null) {
throw new IllegalStateException("Singleton not set for " + acl);
}
Expand Down
Loading

0 comments on commit de830ba

Please sign in to comment.