Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FISH-10286 Enhancement: Use <domain_dir>/lib/warlibs to enable fast devopment deployments #7097

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,22 +37,27 @@
* 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 com.sun.appserv.connectors.internal.api;

import jakarta.inject.Provider;
import org.glassfish.deployment.common.DeploymentUtils;
import org.glassfish.internal.api.*;
import org.glassfish.internal.deployment.Deployment;
import org.jvnet.hk2.annotations.Service;

import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.UnaryOperator;
import java.util.logging.Logger;
import java.util.logging.Level;

import com.sun.logging.LogDomains;

import jakarta.inject.Inject;
import jakarta.inject.Provider;

/**
* We support two policies:
Expand All @@ -72,13 +77,13 @@ public class ConnectorClassLoaderServiceImpl implements ConnectorClassLoaderServ
* class loader for all applications. In other words, we make every
* standalone RARs available to all applications.
*/
private volatile DelegatingClassLoader globalConnectorCL;
private final AtomicReference<DelegatingClassLoader> globalConnectorCL = new AtomicReference<>();
private final AtomicReference<DelegatingClassLoader> globalConnectorWithWarLibCL = new AtomicReference<>();

@Inject
private AppSpecificConnectorClassLoaderUtil appsSpecificCCLUtil;

@Inject
private Provider<ClassLoaderHierarchy> classLoaderHierarchyProvider;
private Provider<ConnectorsClassLoaderUtil> connectorsClassLoaderUtil;

private Logger logger = LogDomains.getLogger(ConnectorClassLoaderServiceImpl.class, LogDomains.RSR_LOGGER);

Expand All @@ -92,34 +97,8 @@ public class ConnectorClassLoaderServiceImpl implements ConnectorClassLoaderServ
public DelegatingClassLoader getConnectorClassLoader(String appName) {
DelegatingClassLoader loader = null;

// We do not have dependency on common-class-loader explicitly
// and also cannot initialize globalConnectorCL during postConstruct via ClassLoaderHierarchy
// which will result in circular dependency injection between kernel and connector module
// Hence initializing globalConnectorCL lazily
if (globalConnectorCL == null) {
synchronized (ConnectorClassLoaderServiceImpl.class) {
if (globalConnectorCL == null) {
//[parent is assumed to be common-class-loader in ConnectorClassLoaderUtil.createRARClassLoader() also]
final ClassLoader parent = getCommonClassLoader();
globalConnectorCL = AccessController.doPrivileged(new PrivilegedAction<DelegatingClassLoader>() {
public DelegatingClassLoader run() {
DelegatingClassLoader dcl = new DelegatingClassLoader(parent);
for (DelegatingClassLoader.ClassFinder cf : appsSpecificCCLUtil.getSystemRARClassLoaders()) {
dcl.addDelegate(cf);
}
return dcl;
}
});

for (DelegatingClassLoader.ClassFinder cf : appsSpecificCCLUtil.getSystemRARClassLoaders()) {
globalConnectorCL.addDelegate(cf);
}
}
}
}
if (hasGlobalAccessForRARs(appName)) {
assert (globalConnectorCL != null);
loader = globalConnectorCL;
loader = getGlobalConnectorClassLoader();
} else {
appsSpecificCCLUtil.detectReferredRARs(appName);
loader = createConnectorClassLoaderForApplication(appName);
Expand All @@ -133,14 +112,42 @@ private boolean hasGlobalAccessForRARs(String appName) {
(ConnectorConstants.RAR_VISIBILITY_GLOBAL_ACCESS);
}

private ClassLoader getCommonClassLoader(){
return classLoaderHierarchyProvider.get().getCommonClassLoader();
private DelegatingClassLoader getGlobalConnectorClassLoader() {
// We do not have dependency on common-class-loader explicitly
// and also cannot initialize globalConnectorCL during postConstruct via ClassLoaderHierarchy
// which will result in circular dependency injection between kernel and connector module
// Hence initializing globalConnectorCL lazily
UnaryOperator<DelegatingClassLoader> updateOperator = currentValue -> {
if (currentValue == null) {
//[parent is assumed to be common-class-loader in ConnectorClassLoaderUtil.createRARClassLoader() also]
var newValue = AccessController.doPrivileged(new PrivilegedAction<DelegatingClassLoader>() {
public DelegatingClassLoader run() {
DelegatingClassLoader dcl = new DelegatingClassLoader(connectorsClassLoaderUtil.get().getCommonClassLoader());
for (DelegatingClassLoader.ClassFinder cf : appsSpecificCCLUtil.getSystemRARClassLoaders()) {
dcl.addDelegate(cf);
}
return dcl;
}
});

for (DelegatingClassLoader.ClassFinder cf : appsSpecificCCLUtil.getSystemRARClassLoaders()) {
newValue.addDelegate(cf);
}
return newValue;
}
return currentValue;
};
if (DeploymentUtils.useWarLibraries(DeploymentUtils.getCurrentDeploymentContext())) {
return globalConnectorWithWarLibCL.updateAndGet(updateOperator);
} else {
return globalConnectorCL.updateAndGet(updateOperator);
}
}

private DelegatingClassLoader createConnectorClassLoaderForApplication(String appName){

DelegatingClassLoader appSpecificConnectorClassLoader =
new DelegatingClassLoader(getCommonClassLoader());
new DelegatingClassLoader(connectorsClassLoaderUtil.get().getCommonClassLoader());

//add system ra classloaders
for(DelegatingClassLoader.ClassFinder cf : appsSpecificCCLUtil.getSystemRARClassLoaders()){
Expand Down Expand Up @@ -178,7 +185,7 @@ private void addRarClassLoader(String appName, DelegatingClassLoader appSpecific
}

private DelegatingClassLoader.ClassFinder getClassFinder(String raName) {
List<DelegatingClassLoader.ClassFinder> delegates = globalConnectorCL.getDelegates();
List<DelegatingClassLoader.ClassFinder> delegates = getGlobalConnectorClassLoader().getDelegates();
DelegatingClassLoader.ClassFinder classFinder = null;
for(DelegatingClassLoader.ClassFinder cf : delegates){
if(raName.equals(((ConnectorClassFinder)cf).getResourceAdapterName())){
Expand All @@ -188,5 +195,4 @@ private DelegatingClassLoader.ClassFinder getClassFinder(String raName) {
}
return classFinder;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -37,25 +37,33 @@
* 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 com.sun.appserv.connectors.internal.api;

import com.sun.enterprise.loader.CurrentBeforeParentClassLoader;
import org.glassfish.deployment.common.DeploymentUtils;
import org.glassfish.deployment.common.InstalledLibrariesResolver;
import org.glassfish.internal.api.ClassLoaderHierarchy;
import org.glassfish.internal.api.DelegatingClassLoader;
import org.glassfish.api.admin.*;
import org.glassfish.api.event.Events;
import org.glassfish.api.event.EventListener;
import org.glassfish.api.event.EventTypes;
import org.glassfish.internal.api.Globals;
import org.glassfish.internal.deployment.Deployment;
import org.jvnet.hk2.annotations.Service;

import jakarta.inject.Singleton;

import java.io.*;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedExceptionAction;
import java.security.PrivilegedActionException;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.Collection;
Expand All @@ -81,7 +89,8 @@ public class ConnectorsClassLoaderUtil {
@Inject
private ClassLoaderHierarchy clh;

//private static List<ConnectorClassFinder> systemRARClassLoaders;
// warLibClassLoader is used to load libraries from the war file
private final AtomicReference<CurrentBeforeParentClassLoader> warLibClassLoader = new AtomicReference<>();

private Logger _logger = LogDomains.getLogger(ConnectorRuntime.class, LogDomains.RSR_LOGGER);

Expand Down Expand Up @@ -209,7 +218,7 @@ public Collection<ConnectorClassFinder> getSystemRARClassLoaders() throws Connec
libraries = ConnectorsUtil.getInstalledLibrariesFromManifest(location, env);
}

ConnectorClassFinder ccf = createRARClassLoader(location, null, rarName, libraries);
ConnectorClassFinder ccf = createRARClassLoader(location, getCommonClassLoader(), rarName, libraries);
classLoaders.add(ccf);
}
// systemRARClassLoaders = classLoaders;
Expand All @@ -218,6 +227,29 @@ public Collection<ConnectorClassFinder> getSystemRARClassLoaders() throws Connec
return classLoaders;
}

public ClassLoader getCommonClassLoader() {
if (DeploymentUtils.useWarLibraries(DeploymentUtils.getCurrentDeploymentContext())) {
return warLibClassLoader.updateAndGet(currentValue -> {
if (currentValue == null) {
var newValue = new CurrentBeforeParentClassLoader(InstalledLibrariesResolver.getWarLibraries()
.stream().map(uri -> {
try {
return uri.toUri().toURL();
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
})
.toArray(URL[]::new), clh.getCommonClassLoader());
newValue.enableCurrentBeforeParentUnconditional();
return newValue;
}
return currentValue;
});
} else {
return clh.getCommonClassLoader();
}
}


public ConnectorClassFinder getSystemRARClassLoader(String rarName) throws ConnectorRuntimeException {
if (ConnectorsUtil.belongsToSystemRA(rarName)) {
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
Loading