#23628 Fixed TCK tests - issues with the SecurityManager

- now ClassGenerator is responsible for everything around this.
diff --git a/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/codegen/ClassGenerator.java b/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/codegen/ClassGenerator.java
index 14289c3..fef5136 100644
--- a/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/codegen/ClassGenerator.java
+++ b/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/codegen/ClassGenerator.java
@@ -16,22 +16,29 @@
 
 package com.sun.ejb.codegen;
 
+import com.sun.enterprise.loader.ASURLClassLoader;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
 import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.security.PrivilegedExceptionAction;
 import java.security.ProtectionDomain;
+import java.util.Objects;
 import java.util.logging.Logger;
 
 import static java.util.logging.Level.CONFIG;
 
 /**
- * This class serves to generate classes, which cannot be generated by the
- * {@link java.lang.invoke.MethodHandles.Lookup} class, because it restricts
+ * This class serves to generate classes, because ...
+ * <p>
+ * {@link java.lang.invoke.MethodHandles.Lookup} class restricts
  * the generated class to use an already existing class as a source of the package
  * and {@link ProtectionDomain}.
  * <p>
- * Also {@link Proxy#newProxyInstance(ClassLoader, Class[], java.lang.reflect.InvocationHandler)}
+ * {@link Proxy#newProxyInstance(ClassLoader, Class[], java.lang.reflect.InvocationHandler)}
  * has another requirements, ie. all referred classes must be loadable by used classloader.
  *
  * @author David Matejcek
@@ -68,6 +75,56 @@
 
 
     /**
+     * Decides which method is suitable to define the new class and then uses it.
+     *
+     * @param loader the classloader instance used to generate the class
+     * @param anchorClass the class used as an "orientation" class. See the {@link Lookup} class for
+     *            more info.
+     * @param targetPackageName the name is used in decision logic; if the anchor class is from
+     *            a different package, the {@link Lookup}'s method is not usable.
+     * @param className expected binary name or null
+     * @param classData the valid bytes that make up the class data.
+     * @return the new generated class
+     * @throws ClassDefinitionException invalid data, missing dependency, or another error related
+     *             to the class generation
+     */
+    public static Class<?> defineClass(final ClassLoader loader, final Class<?> anchorClass,
+        final String targetPackageName, final String className,  final byte[] classData) {
+        if (useMethodHandles(loader, anchorClass, targetPackageName)) {
+            return defineClass(anchorClass, className, classData);
+        } else if (System.getSecurityManager() == null) {
+            return defineClass(loader, className, classData, anchorClass.getProtectionDomain());
+        } else {
+            return defineClass(loader, className, classData);
+        }
+    }
+
+
+    /**
+     * Calls the {@link Lookup}'s defineClass method to create a new class
+     *
+     * @param anchorClass the class used as an "orientation" class. See the {@link Lookup} class for more info.
+     * @param className expected binary name or null
+     * @param classData the valid bytes that make up the class data.
+     * @return the new generated class
+     * @throws ClassDefinitionException invalid data, missing dependency, or another error related
+     *             to the class generation
+     */
+    public static Class<?> defineClass(final Class<?> anchorClass, final String className, final byte[] classData) {
+        LOG.log(CONFIG, "Defining class: {0} with anchorClass: {1}", new Object[] {className, anchorClass});
+        final PrivilegedAction<Class<?>> action = () -> {
+            try {
+                final Lookup lookup = MethodHandles.privateLookupIn(anchorClass, MethodHandles.lookup());
+                return lookup.defineClass(classData);
+            } catch (IllegalAccessException e) {
+                throw new ClassDefinitionException(className,anchorClass, e);
+            }
+        };
+        return AccessController.doPrivileged(action);
+    }
+
+
+    /**
      * Calls the {@link ClassLoader}'s protected defineClass method to create a new class
      *
      * @param loader the classloader instance used to generate the class
@@ -95,15 +152,17 @@
      * @throws ClassDefinitionException invalid data, missing dependency, or another error related
      *             to the class generation
      */
-    public static Class<?> defineClass(
-        final ClassLoader loader, final String className,
-        final byte[] classData, final int offset, final int length) throws ClassDefinitionException {
+    public static Class<?> defineClass(final ClassLoader loader, final String className, final byte[] classData,
+        final int offset, final int length) throws ClassDefinitionException {
         LOG.log(CONFIG, "Defining class: {0} by loader: {1}", new Object[] {className, loader});
-        try {
-            return (Class<?>) defineClassMethod.invoke(loader, className, classData, 0, length);
-        } catch (final Exception | NoClassDefFoundError | ClassFormatError e) {
-            throw new ClassDefinitionException(className, loader, e);
-        }
+        final PrivilegedAction<Class<?>> action = () -> {
+            try {
+                return (Class<?>) defineClassMethod.invoke(loader, className, classData, 0, length);
+            } catch (final Exception | NoClassDefFoundError | ClassFormatError e) {
+                throw new ClassDefinitionException(className, loader, e);
+            }
+        };
+        return AccessController.doPrivileged(action);
     }
 
 
@@ -142,11 +201,14 @@
         final byte[] classData, final int offset, final int length,
         final ProtectionDomain protectionDomain) throws ClassDefinitionException {
         LOG.log(CONFIG, "Defining class: {0} by loader: {1}", new Object[] {className, loader});
-        try {
-            return (Class<?>) defineClassMethodSM.invoke(loader, className, classData, 0, length, protectionDomain);
-        } catch (final Exception | NoClassDefFoundError | ClassFormatError e) {
-            throw new ClassDefinitionException(className, loader, e);
-        }
+        final PrivilegedAction<Class<?>> action = () -> {
+            try {
+                return (Class<?>) defineClassMethodSM.invoke(loader, className, classData, 0, length, protectionDomain);
+            } catch (final Exception | NoClassDefFoundError | ClassFormatError e) {
+                throw new ClassDefinitionException(className, loader, e);
+            }
+        };
+        return AccessController.doPrivileged(action);
     }
 
 
@@ -159,5 +221,24 @@
         ClassDefinitionException(final String className, final ClassLoader loader, final Throwable cause) {
             super("Could not define class '" + className + "' by the class loader: " + loader, cause);
         }
+
+        ClassDefinitionException(final String className, final Class<?> anchorClass, final Throwable cause) {
+            super("Could not define class '" + className + "' using the anchor " + anchorClass, cause);
+        }
+
+    }
+
+
+    private static boolean useMethodHandles(final ClassLoader loader, final Class<?> anchorClass,
+        final String targetPackageName) {
+        if (loader == null) {
+            return true;
+        }
+        // The bootstrap CL used by embedded glassfish doesn't remember generated classes
+        // Further ClassLoader.findClass calls will fail.
+        if (anchorClass == null || loader.getParent() == null || loader.getClass() == ASURLClassLoader.class) {
+            return false;
+        }
+        return Objects.equals(targetPackageName, anchorClass.getPackageName());
     }
 }
diff --git a/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/codegen/Generator.java b/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/codegen/Generator.java
index 6acfb2f..caf1b43 100644
--- a/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/codegen/Generator.java
+++ b/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/codegen/Generator.java
@@ -17,15 +17,10 @@
 
 package com.sun.ejb.codegen;
 
-import com.sun.enterprise.loader.ASURLClassLoader;
-
 import java.io.ByteArrayOutputStream;
 import java.io.PrintStream;
 import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodHandles.Lookup;
 import java.lang.reflect.Method;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
@@ -37,6 +32,7 @@
 import org.glassfish.pfl.dynamic.codegen.spi.ImportList;
 import org.glassfish.pfl.dynamic.codegen.spi.Wrapper;
 
+import static com.sun.ejb.codegen.ClassGenerator.defineClass;
 import static org.glassfish.pfl.dynamic.codegen.impl.CodeGenerator.generateBytecode;
 import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper.DUMP_AFTER_SETUP_VISITOR;
 import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper.TRACE_BYTE_CODE_GENERATION;
@@ -128,31 +124,7 @@
 
         final ClassGeneratorImpl codeGenerator = (ClassGeneratorImpl) _classGenerator();
         final byte[] bytecode = generateBytecode(codeGenerator, getClassLoader(), imports, props, System.out);
-
-        if (useMethodHandles()) {
-            LOG.log(Level.FINEST, "Using MethodHandles to define {0}, anchorClass: {1}",
-                new Object[] {getGeneratedClassName(), getAnchorClass()});
-            final Lookup lookup = MethodHandles.privateLookupIn(getAnchorClass(), MethodHandles.lookup());
-            return lookup.defineClass(bytecode);
-        }
-
-        if (System.getSecurityManager() == null) {
-            return ClassGenerator.defineClass(getClassLoader(), getGeneratedClassName(), bytecode,
-                getAnchorClass().getProtectionDomain());
-        }
-        final PrivilegedAction<Class<?>> action = () -> ClassGenerator.defineClass(getClassLoader(),
-            getGeneratedClassName(), bytecode);
-        return AccessController.doPrivileged(action);
-    }
-
-
-    private boolean useMethodHandles() {
-        // The bootstrap CL used by embedded glassfish doesn't remember generated classes
-        // Further ClassLoader.findClass calls will fail.
-        if (loader.getParent() == null || loader.getClass() == ASURLClassLoader.class) {
-            return false;
-        }
-        return Objects.equals(getPackageName(), getAnchorClass().getPackageName());
+        return defineClass(getClassLoader(), getAnchorClass(), getPackageName(), getGeneratedClassName(), bytecode);
     }