Using Weld 4.0.1.SP1 instead of 4.0.0.Final

- reimplemented ProxyServicesImpl, because Weld changed behavior and added
  methods to the interface and previous implementation caused failure of
  cdi_all tests
diff --git a/appserver/pom.xml b/appserver/pom.xml
index 639e2f8..1e49f3a 100644
--- a/appserver/pom.xml
+++ b/appserver/pom.xml
@@ -158,7 +158,7 @@
 
         <!-- CDI -->
         <cdi-api.version>3.0.0</cdi-api.version>
-        <weld.version>4.0.0.Final</weld.version>
+        <weld.version>4.0.1.SP1</weld.version>
         <jboss.classfilewriter.version>1.2.4.Final</jboss.classfilewriter.version>
 
         <!-- Admin console components -->
diff --git a/appserver/web/weld-integration/src/main/java/org/glassfish/weld/services/ProxyServicesImpl.java b/appserver/web/weld-integration/src/main/java/org/glassfish/weld/services/ProxyServicesImpl.java
index 859eab1..4479088 100644
--- a/appserver/web/weld-integration/src/main/java/org/glassfish/weld/services/ProxyServicesImpl.java
+++ b/appserver/web/weld-integration/src/main/java/org/glassfish/weld/services/ProxyServicesImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2018-2021 Oracle and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v. 2.0, which is available at
@@ -16,124 +16,203 @@
 
 package org.glassfish.weld.services;
 
-import static java.lang.System.getSecurityManager;
-import static java.security.AccessController.doPrivileged;
-
+import java.lang.reflect.Method;
+import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.security.PrivilegedExceptionAction;
+import java.security.ProtectionDomain;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.glassfish.hk2.api.ServiceLocator;
 import org.glassfish.internal.api.ClassLoaderHierarchy;
 import org.jboss.weld.serialization.spi.ProxyServices;
 
 /**
- * An implementation of the <code>ProxyServices</code> Service.
- *
- * This implementation uses the thread context classloader (the application classloader) as the classloader for loading
- * the bean proxies. The classloader that loaded the Bean must be used to load and define the bean proxy to handle Beans
- * with package-private constructor as discussed in WELD-737.
- *
- * Weld proxies today have references to some internal weld implementation classes such as javassist and
- * org.jboss.weld.proxy.* packages. These classes are temporarily re-exported through the weld-integration-fragment
- * bundle so that when the bean proxies when loaded using the application classloader will have visibility to these
- * internal implementation classes.
- *
- * As a fix for WELD-737, Weld may use the Bean's classloader rather than asking the ProxyServices service
- * implementation. Weld also plans to remove the dependencies of the bean proxy on internal implementation classes. When
- * that happens we can remove the weld-integration-fragment workaround and the ProxyServices implementation
+ * An implementation of the {@link ProxyServices}.
+ * <p>
+ * This implementation respects the classloader hierarchy used to load original beans.
+ * If it is not an application classloader, uses the current thread classloader.
+ * If it wasn't possible to detect any usable classloader, throws a {@link WeldProxyException}
+ * <p>
+ * Context: Weld generates proxies for beans from an application and for certain API artifacts
+ * such as <code>UserTransaction</code>.
  *
  * @author Sivakumar Thyagarajan
+ * @author David Matějček
  */
 public class ProxyServicesImpl implements ProxyServices {
 
-    ClassLoaderHierarchy classLoaderHierarchy;
+    private static Method defineClassMethod;
+    private static Method defineClassMethodSM;
+    private static final AtomicBoolean CL_METHODS_INITIALIZATION_FINISHED = new AtomicBoolean(false);
 
-    public ProxyServicesImpl(ServiceLocator services) {
+    private final ClassLoaderHierarchy classLoaderHierarchy;
+
+
+    /**
+     * @param services immediately used to find a {@link ClassLoaderHierarchy} service
+     */
+    public ProxyServicesImpl(final ServiceLocator services) {
         classLoaderHierarchy = services.getService(ClassLoaderHierarchy.class);
     }
 
+
+    @Deprecated
+    @Override
+    public boolean supportsClassDefining() {
+        // true is mandatory since Weld 4.0.1.SP1, because default method impl returns false
+        // and cdi_all tests then fail
+        return true;
+    }
+
+
+    @Deprecated
     @Override
     public ClassLoader getClassLoader(final Class<?> proxiedBeanType) {
-        if (getSecurityManager() == null) {
+        if (System.getSecurityManager() == null) {
             return getClassLoaderforBean(proxiedBeanType);
         }
-        return doPrivileged(new PrivilegedAction<ClassLoader>() {
-            @Override
-            public ClassLoader run() {
-                return getClassLoaderforBean(proxiedBeanType);
-            }
-        });
+        final PrivilegedAction<ClassLoader> action = () -> getClassLoaderforBean(proxiedBeanType);
+        return AccessController.doPrivileged(action);
     }
 
-    /**
-     * Gets the ClassLoader associated with the Bean. Weld generates Proxies for Beans from an application/BDA and for
-     * certain API artifacts such as <code>UserTransaction</code>.
-     *
-     * @param proxiedBeanType
-     * @return
-     */
-    private ClassLoader getClassLoaderforBean(Class<?> proxiedBeanType) {
-        // Get the ClassLoader that loaded the Bean. For Beans in an application,
-        // this would be the application/module classloader. For other API
-        // Bean classes, such as UserTransaction, this would be a non-application
-        // classloader
-        ClassLoader proxyClassLoader = proxiedBeanType.getClassLoader();
 
-        //Check if this is an application classloader
-        boolean isAppCL = isApplicationClassLoader(proxyClassLoader);
-        if (!isAppCL) {
-            proxyClassLoader = _getClassLoader();
-            //fall back to the old behaviour of using TCL to get the application
-            //or module classloader. We return this classloader for non-application
-            //Beans, as Weld Proxies requires other Weld support classes (such as
-            //JBoss Reflection API) that is exported through the weld-osgi-bundle.
-        }
-
-        return proxyClassLoader;
-    }
-
-    /**
-     * Check if the ClassLoader of the Bean type being proxied is a GlassFish application ClassLoader. The current logic
-     * checks if the common classloader appears as a parent in the classloader hierarchy of the Bean's classloader.
-     */
-    private boolean isApplicationClassLoader(ClassLoader prxCL) {
-        boolean isAppCL = false;
-        while (prxCL != null) {
-            if (prxCL.equals(classLoaderHierarchy.getCommonClassLoader())) {
-                isAppCL = true;
-                break;
-            }
-            prxCL = prxCL.getParent();
-        }
-        return isAppCL;
-    }
-
-    private ClassLoader _getClassLoader() {
-        return Thread.currentThread().getContextClassLoader();
-    }
-
+    @Deprecated
     @Override
     public Class<?> loadBeanClass(final String className) {
         try {
-            if (getSecurityManager() == null) {
-                return Class.forName(className, true, _getClassLoader());
+            if (System.getSecurityManager() == null) {
+                return loadClassByThreadCL(className);
             }
-
-            return (Class<?>) doPrivileged(new PrivilegedExceptionAction<>() {
-                @Override
-                public Object run() throws Exception {
-                    return Class.forName(className, true, _getClassLoader());
-                }
-            });
-        } catch (Exception ex) {
-            ex.printStackTrace();
-            throw new RuntimeException(ex);
+            final PrivilegedExceptionAction<Class<?>> action = () -> loadClassByThreadCL(className);
+            return AccessController.doPrivileged(action);
+        } catch (final Exception ex) {
+            throw new WeldProxyException("Failed to load the bean class: " + className, ex);
         }
     }
 
+
+    @Override
+    public Class<?> defineClass(final Class<?> originalClass, final String className, final byte[] classBytes,
+        final int off, final int len) throws ClassFormatError {
+        return defineClass(originalClass, className, classBytes, off, len, null);
+    }
+
+
+    @Override
+    public Class<?> defineClass(final Class<?> originalClass, final String className, final byte[] classBytes,
+        final int off, final int len, final ProtectionDomain protectionDomain) throws ClassFormatError {
+        checkClassDefinitionFeature();
+        final ClassLoader loader = getClassLoaderforBean(originalClass);
+        if (protectionDomain == null) {
+            return defineClass(loader, className, classBytes, off, len);
+        }
+        return defineClass(loader, className, classBytes, off, len, protectionDomain);
+    }
+
+
+    @Override
+    public Class<?> loadClass(final Class<?> originalClass, final String classBinaryName)
+        throws ClassNotFoundException {
+        return getClassLoaderforBean(originalClass).loadClass(classBinaryName);
+    }
+
+
     @Override
     public void cleanup() {
         // nothing to cleanup in this implementation.
     }
 
+
+    /**
+     * Initialization of access to protected methods of the {@link ClassLoader} class.
+     */
+    private static void checkClassDefinitionFeature() {
+        if (CL_METHODS_INITIALIZATION_FINISHED.compareAndSet(false, true)) {
+            try {
+                final PrivilegedExceptionAction<Void> action = () -> {
+                    final Class<?> cl = Class.forName("java.lang.ClassLoader");
+                    final String name = "defineClass";
+                    defineClassMethod = cl.getDeclaredMethod(name, String.class, byte[].class, int.class, int.class);
+                    defineClassMethod.setAccessible(true);
+                    defineClassMethodSM = cl.getDeclaredMethod(
+                        name, String.class, byte[].class, int.class, int.class, ProtectionDomain.class);
+                    defineClassMethodSM.setAccessible(true);
+                    return null;
+                };
+                AccessController.doPrivileged(action);
+            } catch (final Exception e) {
+                throw new WeldProxyException("Could not initialize access to ClassLoader.defineClass method.", e);
+            }
+        }
+    }
+
+
+    /**
+     * @param originalClass
+     * @return ClassLoader probably usable with the bean.
+     */
+    private ClassLoader getClassLoaderforBean(final Class<?> originalClass) {
+        // Get the ClassLoader that loaded the Bean. For Beans in an application,
+        // this would be the application/module classloader. For other API
+        // Bean classes, such as UserTransaction, this would be a non-application
+        // classloader
+        final ClassLoader originalClassLoader = originalClass.getClassLoader();
+        if (isApplicationClassLoader(originalClassLoader)) {
+            return originalClassLoader;
+        }
+        // fall back to the old behaviour of using thread class loader to get the application
+        // or module classloader. We return this classloader for non-application
+        // Beans, as Weld Proxies requires other Weld support classes (such as
+        // JBoss Reflection API) that is exported through the weld-osgi-bundle.
+        final ClassLoader threadCL = Thread.currentThread().getContextClassLoader();
+        if (threadCL != null) {
+            return threadCL;
+        }
+        throw new WeldProxyException("Could not determine classloader for " + originalClass);
+    }
+
+
+    /**
+     * Check if the ClassLoader of the Bean type being proxied is a GlassFish application
+     * ClassLoader. The current logic checks if the common classloader appears as a parent in
+     * the classloader hierarchy of the Bean's classloader.
+     */
+    private boolean isApplicationClassLoader(ClassLoader classLoader) {
+        while (classLoader != null) {
+            if (classLoader.equals(classLoaderHierarchy.getCommonClassLoader())) {
+                return true;
+            }
+            classLoader = classLoader.getParent();
+        }
+        return false;
+    }
+
+
+    private Class<?> loadClassByThreadCL(final String className) throws ClassNotFoundException {
+        return Class.forName(className, true, Thread.currentThread().getContextClassLoader());
+    }
+
+
+    private Class<?> defineClass(
+        final ClassLoader loader, final String className,
+        final byte[] b, final int off, final int len,
+        final ProtectionDomain protectionDomain) {
+        try {
+            return (Class<?>) defineClassMethodSM.invoke(loader, className, b, 0, len, protectionDomain);
+        } catch (final Exception e) {
+            throw new WeldProxyException("Could not define class " + className, e);
+        }
+    }
+
+
+    private Class<?> defineClass(
+        final ClassLoader loader, final String className,
+        final byte[] b, final int off, final int len) {
+        try {
+            return (Class<?>) defineClassMethod.invoke(loader, className, b, 0, len);
+        } catch (final Exception e) {
+            throw new WeldProxyException("Could not define class " + className, e);
+        }
+    }
 }
diff --git a/appserver/web/weld-integration/src/main/java/org/glassfish/weld/services/WeldProxyException.java b/appserver/web/weld-integration/src/main/java/org/glassfish/weld/services/WeldProxyException.java
new file mode 100644
index 0000000..d3beaba
--- /dev/null
+++ b/appserver/web/weld-integration/src/main/java/org/glassfish/weld/services/WeldProxyException.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2021 Eclipse Foundation and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.weld.services;
+
+
+/**
+ * Runtime exception meaning that the operation failed to finish the desired operation.
+ *
+ * @author David Matějček
+ */
+public class WeldProxyException extends RuntimeException {
+
+    private static final long serialVersionUID = 1L;
+
+    public WeldProxyException(final String message, final Exception cause) {
+        super(message, cause);
+    }
+
+
+    public WeldProxyException(final String message) {
+        super(message);
+    }
+}