Fixed #23616 by refactoring
- cleanup around leaky api of generateAndLoad which relied on consistency of
it's parameters
- the anchor class was moved to the generator to keep JDK rules
- removeRedundantMethods was and is slow -> TODO: optimize + test
- ServiceInterfaceGenerator changed output class name and package, because
original addition of jaxws.internal is forbidden in JDK11+
- tests were enhanced to be able to compare loading of cached classes.
diff --git a/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/EJBUtils.java b/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/EJBUtils.java
index ec4daf1..1ba97fa 100644
--- a/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/EJBUtils.java
+++ b/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/EJBUtils.java
@@ -54,6 +54,7 @@
import org.glassfish.pfl.dynamic.codegen.spi.Wrapper;
+import static com.sun.ejb.codegen.GenericHomeGenerator.GENERIC_HOME_CLASSNAME;
import static java.util.logging.Level.FINE;
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;
@@ -177,48 +178,61 @@
private static String getClassPackageName(String intf) {
int dot = intf.lastIndexOf('.');
- return (dot == -1) ? null : intf.substring(0, dot);
+ return dot == -1 ? null : intf.substring(0, dot);
}
+ /** @return the simple name of the class. For included classes returns includes dollar and wrapper class */
private static String getClassSimpleName(String intf) {
int dot = intf.lastIndexOf('.');
- return (dot == -1) ? intf : intf.substring(dot+1);
+ return dot == -1 ? intf : intf.substring(dot + 1);
}
+ /**
+ * Prepends __EJB31_Generated__ and adds _Intf__ to the simple class name.
+ *
+ * @param ejbClassName full class name
+ */
public static String getGeneratedOptionalInterfaceName(String ejbClassName) {
String packageName = getClassPackageName(ejbClassName);
String simpleName = getClassSimpleName(ejbClassName);
String optionalIntfName = "__EJB31_Generated__" + simpleName + "__Intf__";
- return (packageName != null) ?
- packageName + "." + optionalIntfName : optionalIntfName;
+ return packageName == null ? optionalIntfName : packageName + "." + optionalIntfName;
}
+ /**
+ * Adds _Serializable to the original name.
+ *
+ * @param beanClass full class name
+ */
public static String getGeneratedSerializableClassName(String beanClass) {
String packageName = getClassPackageName(beanClass);
String simpleName = getClassSimpleName(beanClass);
String generatedSimpleName = "_" + simpleName + "_Serializable";
- return (packageName != null) ?
- packageName + "." + generatedSimpleName : generatedSimpleName;
+ return packageName == null ? generatedSimpleName : packageName + "." + generatedSimpleName;
}
+ /**
+ * Adds _Remote to the original name.
+ *
+ * @param businessIntf full class name
+ */
public static String getGeneratedRemoteIntfName(String businessIntf) {
String packageName = getClassPackageName(businessIntf);
String simpleName = getClassSimpleName(businessIntf);
String generatedSimpleName = "_" + simpleName + "_Remote";
- return (packageName != null) ?
- packageName + "." + generatedSimpleName : generatedSimpleName;
+ return packageName == null ? generatedSimpleName : packageName + "." + generatedSimpleName;
}
+ /**
+ * Adds _Wrapper to the original name.
+ *
+ * @param businessIntf full class name
+ */
public static String getGeneratedRemoteWrapperName(String businessIntf) {
String packageName = getClassPackageName(businessIntf);
String simpleName = getClassSimpleName(businessIntf);
String generatedSimpleName = "_" + simpleName + "_Wrapper";
- return (packageName != null) ?
- packageName + "." + generatedSimpleName : generatedSimpleName;
- }
-
- public static String getGenericEJBHomeClassName() {
- return "com.sun.ejb.codegen.GenericEJBHome_Generated";
+ return packageName == null ? generatedSimpleName : packageName + "." + generatedSimpleName;
}
/**
@@ -340,100 +354,49 @@
}
- public static Object resolveEjbRefObject(EjbReferenceDescriptor refDesc,
- Object jndiObj)
- throws NamingException {
-
- Object returnObject = jndiObj;
-
- if( refDesc.isLocal() ) {
-
+ public static Object resolveEjbRefObject(EjbReferenceDescriptor refDesc, Object jndiObj) throws NamingException {
+ if (refDesc.isLocal()) {
EjbDescriptor target = refDesc.getEjbDescriptor();
-
BaseContainer container = EjbContainerUtilImpl.getInstance().getContainer(target.getUniqueId());
-
- if( refDesc.isEJB30ClientView() ) {
- GenericEJBLocalHome genericLocalHome =
- container.getEJBLocalBusinessHome(refDesc.getEjbInterface());
- returnObject = genericLocalHome.create(refDesc.getEjbInterface());
- } else {
- returnObject = container.getEJBLocalHome();
+ if (refDesc.isEJB30ClientView()) {
+ GenericEJBLocalHome genericLocalHome = container.getEJBLocalBusinessHome(refDesc.getEjbInterface());
+ return genericLocalHome.create(refDesc.getEjbInterface());
}
-
- } else {
-
- // For the Remote case, the only time we have to do
- // something extra with the given jndiObj is if the lookup
- // is for a Remote 3.0 object and it was made through a
- // corba interoperable name. In that case,
- // the jndiObj refers to the internal Remote 3.0 Home so we
- // still need to create a remote 30 client wrapper object.
-
- if ( refDesc.isEJB30ClientView() &&
- !(jndiObj instanceof RemoteBusinessWrapperBase) ) {
- returnObject = EJBUtils.lookupRemote30BusinessObject
- (jndiObj, refDesc.getEjbInterface());
- }
-
+ return container.getEJBLocalHome();
}
- return returnObject;
-
+ if (refDesc.isEJB30ClientView() && !(jndiObj instanceof RemoteBusinessWrapperBase)) {
+ return EJBUtils.lookupRemote30BusinessObject(jndiObj, refDesc.getEjbInterface());
+ }
+ return jndiObj;
}
- public static Object lookupRemote30BusinessObject(Object jndiObj,
- String businessInterface)
- throws NamingException
- {
- Object returnObject = null;
-
+ public static Object lookupRemote30BusinessObject(Object jndiObj, String businessInterface) throws NamingException {
try {
-
ClassLoader loader = Thread.currentThread().getContextClassLoader();
-
- Class genericEJBHome = loadGeneratedGenericEJBHomeClass
- (loader);
-
- final Object genericHomeObj =
- PortableRemoteObject.narrow(jndiObj, genericEJBHome);
+ Class<?> genericEJBHome = loadGeneratedGenericEJBHomeClass(loader);
+ final Object genericHomeObj = PortableRemoteObject.narrow(jndiObj, genericEJBHome);
// The generated remote business interface and the
// client wrapper for the business interface are produced
- // dynamically. The following call must be made before
+ // dynamically. The following call must be made before
// any EJB 3.0 Remote business interface runtime behavior
// is needed in a given JVM.
loadGeneratedRemoteBusinessClasses(businessInterface);
- String generatedRemoteIntfName = EJBUtils.
- getGeneratedRemoteIntfName(businessInterface);
+ String generatedRemoteIntfName = EJBUtils.getGeneratedRemoteIntfName(businessInterface);
+ Method createMethod = genericEJBHome.getMethod("create", String.class);
+ java.rmi.Remote delegate = (java.rmi.Remote) createMethod.invoke(genericHomeObj, generatedRemoteIntfName);
- Method createMethod = genericEJBHome.getMethod
- ("create", String.class);
-
- java.rmi.Remote delegate = (java.rmi.Remote)
- createMethod.invoke(genericHomeObj,
- generatedRemoteIntfName);
-
-
- returnObject = createRemoteBusinessObject
- (loader, businessInterface, delegate);
-
-
- // TODO Bring over appclient security exception retry logic CR 6620388
-
- } catch(Exception e) {
- NamingException ne = new NamingException
- ("ejb ref resolution error for remote business interface"
- + businessInterface);
-
- ne.initCause(e instanceof InvocationTargetException ?
- e.getCause() : e);
+ // TODO Bring over appclient security exception retry logic CR 6620388
+ return createRemoteBusinessObject(loader, businessInterface, delegate);
+ } catch (Exception e) {
+ NamingException ne = new NamingException(
+ "ejb ref resolution error for remote business interface" + businessInterface);
+ ne.initCause(e instanceof InvocationTargetException ? e.getCause() : e);
throw ne;
}
-
- return returnObject;
-
}
@@ -452,6 +415,10 @@
}
+ /**
+ * @param appClassLoader - used to verify existence of classes and for generating too.
+ * @param businessInterfaceName - this class must exist
+ */
public static void loadGeneratedRemoteBusinessClasses(ClassLoader appClassLoader, String businessInterfaceName)
throws Exception {
String generatedRemoteIntfName = EJBUtils.getGeneratedRemoteIntfName(businessInterfaceName);
@@ -465,17 +432,13 @@
Wrapper._setClassLoader(appClassLoader);
try {
if (generatedRemoteIntf == null) {
- RemoteGenerator gen = new RemoteGenerator(appClassLoader, businessInterfaceName);
- Class<?> developerClass = appClassLoader.loadClass(businessInterfaceName);
- generateAndLoad(gen, generatedRemoteIntfName, appClassLoader, developerClass);
-
+ RemoteGenerator generator = new RemoteGenerator(appClassLoader, businessInterfaceName);
+ generateAndLoad(generator, appClassLoader);
}
if (generatedRemoteWrapper == null) {
- Remote30WrapperGenerator gen = new Remote30WrapperGenerator(appClassLoader, businessInterfaceName,
- generatedRemoteIntfName);
-
- Class<?> developerClass = appClassLoader.loadClass(businessInterfaceName);
- generateAndLoad(gen, wrapperClassName, appClassLoader, developerClass);
+ Remote30WrapperGenerator generator
+ = new Remote30WrapperGenerator(appClassLoader, businessInterfaceName, generatedRemoteIntfName);
+ generateAndLoad(generator, appClassLoader);
}
} finally {
// Make sure no classloader is bound to threadlocal: avoid possible classloader leak.
@@ -484,36 +447,38 @@
}
- public static Class<?> loadGeneratedGenericEJBHomeClass(ClassLoader appClassLoader) throws Exception {
- String className = getGenericEJBHomeClassName();
- Class<?> generatedGenericEJBHomeClass = loadClassIgnoringExceptions(appClassLoader, className);
+ public static Class<?> loadGeneratedGenericEJBHomeClass(final ClassLoader appClassLoader) throws Exception {
+ final Class<?> generatedGenericEJBHomeClass = loadClassIgnoringExceptions(appClassLoader, GENERIC_HOME_CLASSNAME);
if (generatedGenericEJBHomeClass != null) {
return generatedGenericEJBHomeClass;
}
- GenericHomeGenerator gen = new GenericHomeGenerator(appClassLoader);
- return generateAndLoad(gen, className, appClassLoader, GenericHomeGenerator.class);
+ final GenericHomeGenerator generator = new GenericHomeGenerator();
+ return generateAndLoad(generator, appClassLoader);
}
- public static Class generateSEI(ClassGeneratorFactory cgf, ClassLoader loader, Class beanClass) {
- Class<?> clazz = loadClassIgnoringExceptions(loader, cgf.className());
+ public static Class<?> generateSEI(ClassGeneratorFactory cgf, ClassLoader loader) {
+ Class<?> clazz = loadClassIgnoringExceptions(loader, cgf.getGeneratedClassName());
if (clazz != null) {
return clazz;
}
- return generateAndLoad(cgf, cgf.className(), loader, beanClass);
+ return generateAndLoad(cgf, loader);
}
- private synchronized static Class<?> generateAndLoad(
- final ClassGeneratorFactory factory, final String requestedClassName,
- final ClassLoader loader, final Class<?> anchorClass) {
-
- Class<?> clazz = loadClassIgnoringExceptions(loader, requestedClassName);
+ /**
+ * Checks if the class wasn't already generated by another thread and if not, generates it.
+ * The class name is retrieved from {@link ClassGeneratorFactory#getGeneratedClassName()}
+ * and if it wasn't found, generator knows it's definition.
+ */
+ // made package visible just for tests
+ static synchronized Class<?> generateAndLoad(final ClassGeneratorFactory generator, final ClassLoader loader) {
+ Class<?> clazz = loadClassIgnoringExceptions(loader, generator.getGeneratedClassName());
if (clazz != null) {
return clazz;
}
- factory.evaluate();
+ generator.evaluate();
final Properties props = new Properties();
if (_logger.isLoggable(Level.FINEST)) {
@@ -531,9 +496,9 @@
}
if (System.getSecurityManager() == null) {
- return Wrapper._generate(anchorClass, props);
+ return Wrapper._generate(generator.getAnchorClass(), props);
}
- PrivilegedAction<Class<?>> action = () -> Wrapper._generate(anchorClass, props);
+ PrivilegedAction<Class<?>> action = () -> Wrapper._generate(generator.getAnchorClass(), props);
return AccessController.doPrivileged(action);
}
diff --git a/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/codegen/ClassGeneratorFactory.java b/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/codegen/ClassGeneratorFactory.java
index 22eba45..84a1263 100644
--- a/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/codegen/ClassGeneratorFactory.java
+++ b/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/codegen/ClassGeneratorFactory.java
@@ -1,5 +1,6 @@
/*
* Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021 Contributors to the Eclipse Foundation
*
* 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,14 +17,26 @@
package com.sun.ejb.codegen;
+import org.glassfish.pfl.dynamic.codegen.spi.Wrapper;
-/** Convenience interface that defines a factory for ClassGenerator instances.
+/**
+ * Convenience interface that defines a factory for ClassGenerator instances.
* It puts the class name of the generated class in a single place.
- * It must always be the case that evaluate().name().equals( className() ).
*/
-public interface ClassGeneratorFactory
-{
- String className() ;
+public interface ClassGeneratorFactory {
+ /**
+ * @return name of the generated class or interface
+ */
+ String getGeneratedClassName();
+
+ /**
+ * @return loadable class of the same package as {@link #getGeneratedClassName()}
+ */
+ Class<?> getAnchorClass();
+
+ /**
+ * Calls {@link Wrapper} methods to configure the class definition.
+ */
void evaluate();
}
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 7ea2959..84fdca6 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
@@ -1,5 +1,6 @@
/*
* Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021 Contributors to the Eclipse Foundation
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -17,246 +18,102 @@
package com.sun.ejb.codegen;
import java.lang.reflect.Method;
-import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.Set;
-import java.util.Vector;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.sun.enterprise.deployment.MethodDescriptor;
-import com.sun.logging.LogDomains;
-import org.glassfish.api.deployment.DeploymentContext;
-import org.glassfish.ejb.deployment.descriptor.ContainerTransaction;
-import org.glassfish.ejb.deployment.descriptor.EjbDescriptor;
-import org.glassfish.ejb.deployment.descriptor.EjbSessionDescriptor;
+import java.util.ArrayList;
+import java.util.List;
/**
* The base class for all code generators.
*/
-public abstract class Generator {
-
- protected static final Logger _logger = LogDomains.getLogger(Generator.class, LogDomains.EJB_LOGGER);
-
- protected String ejbClassSymbol;
-
- public abstract String getGeneratedClass();
-
+public abstract class Generator implements ClassGeneratorFactory {
/**
* Get the package name from the class name.
+ *
* @param className class name.
* @return the package name.
*/
protected String getPackageName(String className) {
int dot = className.lastIndexOf('.');
- if (dot == -1)
+ if (dot == -1) {
return null;
+ }
return className.substring(0, dot);
}
- protected String getBaseName(String className) {
- int dot = className.lastIndexOf('.');
- if (dot == -1)
- return className;
- return className.substring(dot+1);
- }
-
- protected String printType(Class cls) {
- if (cls.isArray()) {
- return printType(cls.getComponentType()) + "[]";
- } else {
- return cls.getName();
- }
- }
-
- protected Method[] removeDups(Method[] orig) {
- // Remove duplicates from method array.
- // Duplicates will arise if a class/intf and super-class/intf
- // define methods with the same signature. Potentially the
- // throws clauses of the methods may be different (note Java
- // requires that the superclass/intf method have a superset of the
- // exceptions in the derived method).
- Vector nodups = new Vector();
- for ( int i=0; i<orig.length; i++ ) {
- Method m1 = orig[i];
- boolean dup = false;
- for ( Enumeration e=nodups.elements(); e.hasMoreElements(); ) {
- Method m2 = (Method)e.nextElement();
-
- // m1 and m2 are duplicates if they have the same signature
- // (name and same parameters).
- if ( !m1.getName().equals(m2.getName()) )
- continue;
-
- Class[] m1parms = m1.getParameterTypes();
- Class[] m2parms = m2.getParameterTypes();
- if ( m1parms.length != m2parms.length )
- continue;
-
- boolean parmsDup = true;
- for ( int j=0; j<m2parms.length; j++ ) {
- if ( m1parms[j] != m2parms[j] ) {
- parmsDup = false;
- break;
- }
- }
- if ( parmsDup ) {
- dup = true;
- // Select which of the duplicate methods to generate
- // code for: choose the one that is lower in the
- // inheritance hierarchy: this ensures that the generated
- // method will compile.
- if ( m2.getDeclaringClass().isAssignableFrom(
- m1.getDeclaringClass()) ) {
- // m2 is a superclass/intf of m1, so replace m2 with m1
- nodups.remove(m2);
- nodups.add(m1);
- }
- break;
- }
- }
-
- if ( !dup )
- nodups.add(m1);
- }
- return (Method[])nodups.toArray(new Method[nodups.size()]);
- }
/**
- * Return true if method is on a jakarta.ejb.EJBObject/EJBLocalObject/
- * jakarta.ejb.EJBHome,jakarta.ejb.EJBLocalHome interface.
+ * @param className
+ * @return simple class name (including wrapper class and dollar sign if it is internal class)
*/
- protected boolean isEJBIntfMethod(Class ejbIntfClz, Method methodToCheck) {
- boolean isEJBIntfMethod = false;
-
- Method[] ejbIntfMethods = ejbIntfClz.getMethods();
- for(int i = 0; i < ejbIntfMethods.length; i++) {
- Method next = ejbIntfMethods[i];
- if(methodCompare(methodToCheck, next)) {
- isEJBIntfMethod = true;
-
- String ejbIntfClzName = ejbIntfClz.getName();
- Class methodToCheckClz = methodToCheck.getDeclaringClass();
- if( !methodToCheckClz.getName().equals(ejbIntfClzName) ) {
- String[] logParams = {next.toString(), methodToCheck.toString()};
- _logger.log(Level.WARNING,
- "ejb.illegal_ejb_interface_override",
- logParams);
- }
-
- break;
- }
+ protected String getBaseName(String className) {
+ int dot = className.lastIndexOf('.');
+ if (dot == -1) {
+ return className;
}
-
- return isEJBIntfMethod;
+ return className.substring(dot + 1);
}
- private boolean methodCompare(Method factoryMethod, Method homeMethod) {
+ /**
+ * Remove duplicates from method array.
+ * <p>
+ * Duplicates will arise if a class/intf and super-class/intf
+ * define methods with the same signature. Potentially the
+ * throws clauses of the methods may be different (note Java
+ * requires that the superclass/intf method have a superset of the
+ * exceptions in the derived method).
+ *
+ * @param methods
+ * @return methods which can be generated in an interface
+ */
+ protected Method[] removeRedundantMethods(Method[] methods) {
+ final List<Method> nodups = new ArrayList<>();
+ for (Method method : methods) {
+ boolean duplicationDetected = false;
+ final List<Method> previousResult = new ArrayList<>(nodups);
+ for (Method alreadyProcessed : previousResult) {
+ // m1 and m2 are duplicates if they have the same signature
+ // (name and same parameters).
+ if (!method.getName().equals(alreadyProcessed.getName())) {
+ continue;
+ }
+ if (!haveSameParams(method, alreadyProcessed)) {
+ continue;
+ }
+ duplicationDetected = true;
+ // Select which of the duplicate methods to generate
+ // code for: choose the one that is lower in the
+ // inheritance hierarchy: this ensures that the generated
+ // method will compile.
+ if (alreadyProcessed.getDeclaringClass().isAssignableFrom(method.getDeclaringClass())) {
+ // alreadyProcessedMethod is a superclass/intf of method,
+ // so replace it with more concrete method
+ nodups.remove(alreadyProcessed);
+ nodups.add(method);
+ }
+ break;
+ }
- if (!factoryMethod.getName().equals(homeMethod.getName())) {
+ if (!duplicationDetected) {
+ nodups.add(method);
+ }
+ }
+ return nodups.toArray(new Method[nodups.size()]);
+ }
+
+
+ private boolean haveSameParams(final Method method1, final Method method2) {
+ Class<?>[] m1parms = method1.getParameterTypes();
+ Class<?>[] m2parms = method2.getParameterTypes();
+ if (m1parms.length != m2parms.length) {
return false;
}
-
- Class[] factoryParamTypes = factoryMethod.getParameterTypes();
- Class[] beanParamTypes = homeMethod.getParameterTypes();
- if (factoryParamTypes.length != beanParamTypes.length) {
- return false;
- }
- for(int i = 0; i < factoryParamTypes.length; i++) {
- if (factoryParamTypes[i] != beanParamTypes[i]) {
+ for (int i = 0; i < m2parms.length; i++) {
+ if (m1parms[i] != m2parms[i]) {
return false;
}
}
-
- // NOTE : Exceptions and return types are not part of equality check
return true;
}
-
-
- protected String getUniqueClassName(DeploymentContext context, String origName, String origSuffix,
- Vector existingClassNames) {
- String newClassName = null;
- boolean foundUniqueName = false;
- int count = 0;
- while (!foundUniqueName) {
- String suffix = origSuffix;
- if (count > 0) {
- suffix = origSuffix + count;
- }
- newClassName = origName + suffix;
- if (!existingClassNames.contains(newClassName)) {
- foundUniqueName = true;
- existingClassNames.add(newClassName);
- } else {
- count++;
- }
- }
- return newClassName;
- }
-
-
- protected String getTxAttribute(EjbDescriptor dd, Method method) {
- // The TX_* strings returned MUST match the TX_* constants in
- // com.sun.ejb.Container.
- if (dd instanceof EjbSessionDescriptor && ((EjbSessionDescriptor) dd).getTransactionType().equals("Bean")) {
- return "TX_BEAN_MANAGED";
- }
-
- String txAttr = null;
- MethodDescriptor mdesc = new MethodDescriptor(method, ejbClassSymbol);
- ContainerTransaction ct = dd.getContainerTransactionFor(mdesc);
- if (ct != null) {
- String attr = ct.getTransactionAttribute();
- if (attr.equals(ContainerTransaction.NOT_SUPPORTED)) {
- txAttr = "TX_NOT_SUPPORTED";
- } else if (attr.equals(ContainerTransaction.SUPPORTS)) {
- txAttr = "TX_SUPPORTS";
- } else if (attr.equals(ContainerTransaction.REQUIRED)) {
- txAttr = "TX_REQUIRED";
- } else if (attr.equals(ContainerTransaction.REQUIRES_NEW)) {
- txAttr = "TX_REQUIRES_NEW";
- } else if (attr.equals(ContainerTransaction.MANDATORY)) {
- txAttr = "TX_MANDATORY";
- } else if (attr.equals(ContainerTransaction.NEVER)) {
- txAttr = "TX_NEVER";
- }
- }
-
- if (txAttr == null) {
- throw new RuntimeException("Transaction Attribute not found for method " + method);
- }
- return txAttr;
- }
-
- protected String getSecurityAttribute(EjbDescriptor dd, Method m) {
- // The SEC_* strings returned MUST match the SEC_* constants in
- // com.sun.ejb.Container.
- MethodDescriptor thisMethodDesc = new MethodDescriptor(m, ejbClassSymbol);
- Set unchecked = dd.getUncheckedMethodDescriptors();
- if (unchecked != null) {
- Iterator i = unchecked.iterator();
- while (i.hasNext()) {
- MethodDescriptor md = (MethodDescriptor) i.next();
- if (thisMethodDesc.equals(md)) {
- return "SEC_UNCHECKED";
- }
- }
- }
-
- Set excluded = dd.getExcludedMethodDescriptors();
- if (excluded != null) {
- Iterator i = excluded.iterator();
- while (i.hasNext()) {
- MethodDescriptor md = (MethodDescriptor) i.next();
- if (thisMethodDesc.equals(md)) {
- return "SEC_EXCLUDED";
- }
- }
- }
-
- return "SEC_CHECKED";
- }
}
diff --git a/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/codegen/GenericHomeGenerator.java b/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/codegen/GenericHomeGenerator.java
index 256b8dd..789dc91 100644
--- a/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/codegen/GenericHomeGenerator.java
+++ b/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/codegen/GenericHomeGenerator.java
@@ -1,5 +1,6 @@
/*
* Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021 Contributors to the Eclipse Foundation
*
* 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,74 +17,70 @@
package com.sun.ejb.codegen;
+import com.sun.ejb.containers.GenericEJBHome;
-import com.sun.ejb.EJBUtils;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
-import com.sun.enterprise.util.LocalStringManagerImpl;
-
-import static java.lang.reflect.Modifier.*;
-
-import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper.*;
+import static java.lang.reflect.Modifier.ABSTRACT;
+import static java.lang.reflect.Modifier.PUBLIC;
+import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._String;
+import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._arg;
+import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._classGenerator;
+import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._clear;
+import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._end;
+import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._interface;
+import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._method;
+import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._package;
+import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._t;
/**
* This class is used to generate a sub-interface of the
* GenericEJBHome interface that will be loaded within each
* application.
*/
+public class GenericHomeGenerator extends Generator {
-public class GenericHomeGenerator extends Generator
- implements ClassGeneratorFactory {
-
- private static LocalStringManagerImpl localStrings = new LocalStringManagerImpl(GenericHomeGenerator.class);
-
- private String genericEJBHomeClassName;
- private ClassLoader loader;
+ /**
+ * This class name is relative to the classloader used, but has always the same name.
+ */
+ public static final String GENERIC_HOME_CLASSNAME = GenericHomeGenerator.class.getPackageName()
+ + ".GenericEJBHome_Generated";
/**
* Get the fully qualified name of the generated class.
* @return the name of the generated class.
*/
- public String getGeneratedClass() {
- return genericEJBHomeClassName;
- }
-
- // For corba codegen infrastructure
- public String className() {
- return getGeneratedClass();
+ @Override
+ public final String getGeneratedClassName() {
+ return GENERIC_HOME_CLASSNAME;
}
- public GenericHomeGenerator(ClassLoader cl) throws GeneratorException {
- super();
-
- genericEJBHomeClassName = EJBUtils.getGenericEJBHomeClassName();
- loader = cl;
+ @Override
+ public Class<?> getAnchorClass() {
+ return GenericHomeGenerator.class;
}
+ @Override
public void evaluate() {
-
_clear();
- String packageName = getPackageName(genericEJBHomeClassName);
- String simpleName = getBaseName (genericEJBHomeClassName);
+ String packageName = getPackageName(getGeneratedClassName());
+ String simpleName = getBaseName(getGeneratedClassName());
_package(packageName);
- _interface(PUBLIC, simpleName,
- _t("com.sun.ejb.containers.GenericEJBHome"));
+ _interface(PUBLIC, simpleName, _t(GenericEJBHome.class.getName()));
- // Create method
- _method(PUBLIC | ABSTRACT, _t("java.rmi.Remote"),
- "create", _t("java.rmi.RemoteException"));
+ _method(PUBLIC | ABSTRACT, _t(Remote.class.getName()), "create", _t(RemoteException.class.getName()));
_arg(_String(), "generatedBusinessIntf");
_end();
_classGenerator() ;
-
- return;
}
}
diff --git a/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/codegen/Remote30WrapperGenerator.java b/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/codegen/Remote30WrapperGenerator.java
index 66b1ce8..d288bc7 100644
--- a/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/codegen/Remote30WrapperGenerator.java
+++ b/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/codegen/Remote30WrapperGenerator.java
@@ -1,5 +1,6 @@
/*
* Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021 Contributors to the Eclipse Foundation
*
* 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,85 +17,104 @@
package com.sun.ejb.codegen;
-import java.lang.reflect.Method;
-import java.util.*;
-
-
-import static java.lang.reflect.Modifier.*;
-
-import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper.*;
-import org.glassfish.pfl.dynamic.codegen.spi.Type ;
-import org.glassfish.pfl.dynamic.codegen.spi.Expression ;
-
import com.sun.ejb.EJBUtils;
+import com.sun.ejb.containers.InternalEJBContainerException;
+import com.sun.ejb.containers.InternalRemoteException;
+import com.sun.ejb.containers.RemoteBusinessWrapperBase;
import com.sun.enterprise.util.LocalStringManagerImpl;
-public class Remote30WrapperGenerator extends Generator
- implements ClassGeneratorFactory {
+import java.lang.reflect.Method;
+import java.rmi.AccessException;
+import java.rmi.NoSuchObjectException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Properties;
+import java.util.logging.Level;
+import java.util.logging.Logger;
- private static LocalStringManagerImpl localStrings = new LocalStringManagerImpl(Remote30WrapperGenerator.class);
+import org.glassfish.pfl.dynamic.codegen.spi.Expression;
+import org.glassfish.pfl.dynamic.codegen.spi.Type;
+import org.omg.CORBA.SystemException;
- private String remoteInterfaceName;
- private Class businessInterface;
- private String remoteClientClassName;
- private String remoteClientPackageName;
- private String remoteClientSimpleName;
- private Method[] bizMethods;
+import jakarta.ejb.EJBAccessException;
+import jakarta.ejb.EJBException;
+import jakarta.ejb.EJBTransactionRequiredException;
+import jakarta.ejb.EJBTransactionRolledbackException;
+import jakarta.ejb.NoSuchEJBException;
+import jakarta.transaction.TransactionRequiredException;
+import jakarta.transaction.TransactionRolledbackException;
- private ClassLoader loader;
+import static java.lang.reflect.Modifier.PRIVATE;
+import static java.lang.reflect.Modifier.PUBLIC;
+import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper.*;
- public String getGeneratedClass() {
- return remoteClientClassName;
- }
+public final class Remote30WrapperGenerator extends Generator {
- // For corba codegen infrastructure
- public String className() {
- return getGeneratedClass();
- }
+ private static final LocalStringManagerImpl localStrings = new LocalStringManagerImpl(Remote30WrapperGenerator.class);
+ private static final Logger LOG = Logger.getLogger(Remote30WrapperGenerator.class.getName());
+
+ private final String remoteInterfaceName;
+ private final Class<?> businessInterface;
+ private final String remoteClientClassName;
+ private final String remoteClientPackageName;
+ private final String remoteClientSimpleName;
+ private final Method[] methodsToGenerate;
+
+ private final ClassLoader loader;
/**
* Construct the Wrapper generator with the specified deployment
* descriptor and class loader.
*
- * @exception GeneratorException
+ * @param loader
+ * @param businessIntfName must already exist and be loadable by the loader
+ * @param remoteInterfaceName generated class will implement this
+ *
+ * @throws GeneratorException
*/
- public Remote30WrapperGenerator(ClassLoader cl, String businessIntfName, String remoteIntfName)
+ public Remote30WrapperGenerator(ClassLoader loader, String businessIntfName, String remoteInterfaceName)
throws GeneratorException {
- super();
- remoteInterfaceName = remoteIntfName;
- loader = cl;
+ this.loader = loader;
+ this.remoteInterfaceName = remoteInterfaceName;
try {
- this.businessInterface = cl.loadClass(businessIntfName);
+ businessInterface = loader.loadClass(businessIntfName);
} catch (ClassNotFoundException ex) {
- throw new InvalidBean(
- localStrings.getLocalString(
- "generator.remote_interface_not_found",
- "Business interface " + businessInterface + " not found "));
+ throw new InvalidBean(localStrings.getLocalString(
+ "generator.remote_interface_not_found",
+ "Business interface " + businessIntfName + " not found "));
}
if (jakarta.ejb.EJBObject.class.isAssignableFrom(businessInterface)) {
- throw new GeneratorException("Invalid Remote Business Interface " +
- businessInterface + ". A Remote Business interface MUST " +
- "not extend jakarta.ejb.EJBObject.");
+ throw new GeneratorException("Invalid Remote Business Interface " + businessInterface
+ + ". A Remote Business interface MUST not extend jakarta.ejb.EJBObject.");
}
- remoteClientClassName = EJBUtils.
- getGeneratedRemoteWrapperName(businessInterface.getName());
-
+ remoteClientClassName = EJBUtils.getGeneratedRemoteWrapperName(businessIntfName);
remoteClientPackageName = getPackageName(remoteClientClassName);
remoteClientSimpleName = getBaseName(remoteClientClassName);
- bizMethods = removeDups(businessInterface.getMethods());
+ methodsToGenerate = removeRedundantMethods(businessInterface.getMethods());
// NOTE : no need to remove ejb object methods because EJBObject
// is only visible through the RemoteHome view.
-
}
+ @Override
+ public String getGeneratedClassName() {
+ return remoteClientClassName;
+ }
+ @Override
+ public Class<?> getAnchorClass() {
+ return businessInterface;
+ }
+
+ @Override
public void evaluate() {
_clear();
@@ -107,7 +127,7 @@
}
_class(PUBLIC, remoteClientSimpleName,
- _t("com.sun.ejb.containers.RemoteBusinessWrapperBase"),
+ _t(RemoteBusinessWrapperBase.class.getName()),
_t(businessInterface.getName()));
_data(PRIVATE, _t(remoteInterfaceName), "delegate_");
@@ -117,45 +137,42 @@
_arg(_String(), "busIntf");
_body();
- _expr(_super(_s(_void(), _t("java.rmi.Remote"), _String()), _v("stub"), _v("busIntf")));
+ _expr(_super(_s(_void(), _t(Remote.class.getName()), _String()), _v("stub"), _v("busIntf")));
_assign(_v("delegate_"), _v("stub"));
_end();
- for(int i = 0; i < bizMethods.length; i++) {
- printMethodImpl(bizMethods[i]);
+ for (Method method : methodsToGenerate) {
+ printMethodImpl(method);
}
_end();
try {
- java.util.Properties p = new java.util.Properties();
+ Properties p = new Properties();
p.put("Wrapper.DUMP_AFTER_SETUP_VISITOR", "true");
p.put("Wrapper.TRACE_BYTE_CODE_GENERATION", "true");
p.put("Wrapper.USE_ASM_VERIFIER", "true");
_byteCode(loader, p);
} catch(Exception e) {
- System.out.println("Got exception when generating byte code");
- e.printStackTrace();
+ LOG.log(Level.WARNING, "Got exception when generating byte code", e);
}
_classGenerator() ;
-
- return;
}
private void printMethodImpl(Method m) {
- List<Type> exceptionList = new LinkedList<Type>();
- for (Class exception : m.getExceptionTypes()) {
+ List<Type> exceptionList = new LinkedList<>();
+ for (Class<?> exception : m.getExceptionTypes()) {
exceptionList.add(Type.type(exception));
}
_method(PUBLIC, Type.type(m.getReturnType()), m.getName(), exceptionList);
int i = 0;
- List<Type> expressionListTypes = new LinkedList<Type>();
- List<Expression> expressionList = new LinkedList<Expression>();
- for (Class param : m.getParameterTypes()) {
+ List<Type> expressionListTypes = new LinkedList<>();
+ List<Expression> expressionList = new LinkedList<>();
+ for (Class<?> param : m.getParameterTypes()) {
String paramName = "param" + i;
_arg(Type.type(param), paramName);
i++;
@@ -167,7 +184,7 @@
_try();
- Class returnType = m.getReturnType();
+ Class<?> returnType = m.getReturnType();
if (returnType == void.class) {
_expr(
@@ -177,76 +194,93 @@
_call(_v("delegate_"), m.getName(), _s(Type.type(returnType), expressionListTypes), expressionList));
}
- boolean doExceptionTranslation = !java.rmi.Remote.class.isAssignableFrom(businessInterface);
+ boolean doExceptionTranslation = !Remote.class.isAssignableFrom(businessInterface);
if (doExceptionTranslation) {
+ _catch(_t(TransactionRolledbackException.class.getName()), "trex");
- _catch(_t("jakarta.transaction.TransactionRolledbackException"), "trex");
-
- _define( _t("java.lang.RuntimeException"), "r",
- _new( _t("jakarta.ejb.EJBTransactionRolledbackException"), _s(_void())));
+ _define(_t(RuntimeException.class.getName()), "r",
+ _new(_t(EJBTransactionRolledbackException.class.getName()), _s(_void())));
_expr(
- _call( _v("r"), "initCause", _s(_t("java.lang.Throwable"), _t("java.lang.Throwable")), _v("trex"))
+ _call(
+ _v("r"), "initCause",
+ _s(_t(Throwable.class.getName()), _t(Throwable.class.getName())),
+ _v("trex")
+ )
);
_throw(_v("r"));
- _catch(_t("jakarta.transaction.TransactionRequiredException"), "treqex");
+ _catch(_t(TransactionRequiredException.class.getName()), "treqex");
- _define( _t("java.lang.RuntimeException"), "r",
- _new( _t("jakarta.ejb.EJBTransactionRequiredException"), _s(_void())));
+ _define(_t(RuntimeException.class.getName()), "r",
+ _new(_t(EJBTransactionRequiredException.class.getName()), _s(_void())));
+
_expr(
- _call( _v("r"), "initCause", _s(_t("java.lang.Throwable"), _t("java.lang.Throwable")), _v("treqex"))
+ _call(
+ _v("r"), "initCause",
+ _s(_t(Throwable.class.getName()), _t(Throwable.class.getName())),
+ _v("treqex")
+ )
);
_throw(_v("r"));
- _catch(_t("java.rmi.NoSuchObjectException"), "nsoe");
+ _catch(_t(NoSuchObjectException.class.getName()), "nsoe");
- _define( _t("java.lang.RuntimeException"), "r",
- _new( _t("jakarta.ejb.NoSuchEJBException"), _s(_void())));
+ _define(_t(RuntimeException.class.getName()), "r",
+ _new(_t(NoSuchEJBException.class.getName()), _s(_void())));
_expr(
- _call( _v("r"), "initCause", _s(_t("java.lang.Throwable"), _t("java.lang.Throwable")), _v("nsoe"))
+ _call(
+ _v("r"), "initCause",
+ _s(_t(Throwable.class.getName()), _t(Throwable.class.getName())),
+ _v("nsoe")
+ )
);
_throw(_v("r"));
- _catch(_t("java.rmi.AccessException"), "accex");
+ _catch(_t(AccessException.class.getName()), "accex");
- _define( _t("java.lang.RuntimeException"), "r",
- _new( _t("jakarta.ejb.EJBAccessException"), _s(_void())));
+ _define(_t(RuntimeException.class.getName()), "r",
+ _new(_t(EJBAccessException.class.getName()), _s(_void())));
_expr(
- _call( _v("r"), "initCause", _s(_t("java.lang.Throwable"), _t("java.lang.Throwable")), _v("accex"))
+ _call(
+ _v("r"), "initCause",
+ _s(_t(Throwable.class.getName()), _t(Throwable.class.getName())),
+ _v("accex")
+ )
);
_throw(_v("r"));
- _catch(_t("com.sun.ejb.containers.InternalEJBContainerException"), "iejbcEx");
+ _catch(_t(InternalEJBContainerException.class.getName()), "iejbcEx");
- // This wraps an EJBException. Pull out the cause and throw
- // it as is.
- //_define( _t("java.lang.Throwable"), "r", _null());
-
-
- // _throw(_cast(_t("jakarta.ejb.EJBException"), _v("r")));
_throw(
- _cast(_t("jakarta.ejb.EJBException"), _call( _v("iejbcEx"), "getCause", _s(_t("java.lang.Throwable"))))
+ _cast(
+ _t(EJBException.class.getName()),
+ _call(_v("iejbcEx"), "getCause", _s(_t(Throwable.class.getName())))
+ )
);
- _catch(_t("java.rmi.RemoteException"), "re");
+ _catch(_t(RemoteException.class.getName()), "re");
- _throw( _new( _t("jakarta.ejb.EJBException"), _s(_void(), _t("java.lang.Exception")), _v("re")));
+ _throw( _new( _t(EJBException.class.getName()), _s(_void(), _t(Exception.class.getName())), _v("re")));
- _catch( _t("org.omg.CORBA.SystemException"), "corbaSysEx");
- _define( _t("java.lang.RuntimeException"), "r", _new( _t("jakarta.ejb.EJBException"), _s(_void())));
+ _catch( _t(SystemException.class.getName()), "corbaSysEx");
+ _define( _t(RuntimeException.class.getName()), "r", _new( _t(EJBException.class.getName()), _s(_void())));
_expr(
- _call( _v("r"), "initCause", _s(_t("java.lang.Throwable"), _t("java.lang.Throwable")), _v("corbaSysEx"))
+ _call(
+ _v("r"), "initCause",
+ _s(_t(Throwable.class.getName()), _t(Throwable.class.getName())),
+ _v("corbaSysEx")
+ )
);
_throw(_v("r"));
_end();
} else {
- _catch(_t("com.sun.ejb.containers.InternalEJBContainerException"), "iejbcEx");
+ _catch(_t(InternalEJBContainerException.class.getName()), "iejbcEx");
_throw(
- _new( _t("com.sun.ejb.containers.InternalRemoteException"),
- _s(_void(), _t("com.sun.ejb.containers.InternalEJBContainerException")),
+ _new( _t(InternalRemoteException.class.getName()),
+ _s(_void(), _t(InternalEJBContainerException.class.getName())),
_v("iejbcEx"))
);
_end();
diff --git a/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/codegen/RemoteGenerator.java b/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/codegen/RemoteGenerator.java
index 2bb8271..9de52f8 100644
--- a/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/codegen/RemoteGenerator.java
+++ b/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/codegen/RemoteGenerator.java
@@ -1,5 +1,6 @@
/*
* Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021 Contributors to the Eclipse Foundation
*
* 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,80 +17,88 @@
package com.sun.ejb.codegen;
-import java.lang.reflect.Method;
-import java.io.*;
-import java.util.*;
import com.sun.ejb.EJBUtils;
+import com.sun.ejb.containers.InternalEJBContainerException;
+import com.sun.ejb.containers.RemoteBusinessObject;
+import com.sun.enterprise.util.LocalStringManagerImpl;
-import static java.lang.reflect.Modifier.*;
+import java.lang.reflect.Method;
+import java.util.LinkedList;
+import java.util.List;
-import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper.*;
import org.glassfish.pfl.dynamic.codegen.spi.Type ;
-import com.sun.enterprise.util.LocalStringManagerImpl;
+import static java.lang.reflect.Modifier.ABSTRACT;
+import static java.lang.reflect.Modifier.PUBLIC;
+import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._arg;
+import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._classGenerator;
+import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._clear;
+import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._end;
+import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._interface;
+import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._method;
+import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._package;
+import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._t;
/**
* This class is used to generate the RMI-IIOP version of a
* remote business interface.
*/
-
-public class RemoteGenerator extends Generator
- implements ClassGeneratorFactory {
+public final class RemoteGenerator extends Generator {
private static LocalStringManagerImpl localStrings = new LocalStringManagerImpl(RemoteGenerator.class);
+ private Class<?> businessInterface;
+ private final Method[] methodsToGenerate;
+ private final String remoteInterfacePackageName;
+ private final String remoteInterfaceSimpleName;
+ private final String remoteInterfaceName;
- private Class businessInterface;
- private Method[] bizMethods;
- private String remoteInterfacePackageName;
- private String remoteInterfaceSimpleName;
- private String remoteInterfaceName;
-
- /**
- * Get the fully qualified name of the generated class.
- * Note: the remote/local implementation class is in the same package
- * as the bean class, NOT the remote/local interface.
- * @return the name of the generated class.
- */
- public String getGeneratedClass() {
- return remoteInterfaceName;
- }
-
- // For corba codegen infrastructure
- public String className() {
- return getGeneratedClass();
- }
/**
* Construct the Wrapper generator with the specified deployment
* descriptor and class loader.
- * @exception GeneratorException
+ *
+ * @param classLoader
+ * @param businessIntf
+ * @throws InvalidBean if the businessInterface doesn't exist.
*/
- public RemoteGenerator(ClassLoader cl, String businessIntf) throws GeneratorException {
- super();
-
+ public RemoteGenerator(ClassLoader classLoader, String businessIntf) throws InvalidBean {
try {
- businessInterface = cl.loadClass(businessIntf);
+ businessInterface = classLoader.loadClass(businessIntf);
} catch (ClassNotFoundException ex) {
throw new InvalidBean(
- localStrings.getLocalString(
- "generator.remote_interface_not_found",
- "Remote interface not found "));
+ localStrings.getLocalString("generator.remote_interface_not_found", "Remote interface not found "));
}
- remoteInterfaceName = EJBUtils.getGeneratedRemoteIntfName
- (businessInterface.getName());
-
+ remoteInterfaceName = EJBUtils.getGeneratedRemoteIntfName(businessInterface.getName());
remoteInterfacePackageName = getPackageName(remoteInterfaceName);
remoteInterfaceSimpleName = getBaseName(remoteInterfaceName);
- bizMethods = removeDups(businessInterface.getMethods());
+ methodsToGenerate = removeRedundantMethods(businessInterface.getMethods());
// NOTE : no need to remove ejb object methods because EJBObject
// is only visible through the RemoteHome view.
}
+ /**
+ * Get the fully qualified name of the generated class.
+ * <p>
+ * Note: the remote/local implementation class is in the same package
+ * as the bean class, NOT the remote/local interface.
+ *
+ * @return the name of the generated class.
+ */
+ @Override
+ public String getGeneratedClassName() {
+ return remoteInterfaceName;
+ }
+ @Override
+ public Class<?> getAnchorClass() {
+ return businessInterface;
+ }
+
+ @Override
public void evaluate() {
_clear();
@@ -97,51 +106,46 @@
if (remoteInterfacePackageName != null) {
_package(remoteInterfacePackageName);
} else {
- // no-arg _package() call is required for default package
_package();
}
_interface(PUBLIC, remoteInterfaceSimpleName,
- _t("java.rmi.Remote"),
- _t("com.sun.ejb.containers.RemoteBusinessObject"));
+ _t(java.rmi.Remote.class.getName()),
+ _t(RemoteBusinessObject.class.getName())
+ );
- for(int i = 0; i < bizMethods.length; i++) {
- printMethod(bizMethods[i]);
+ for (Method method : methodsToGenerate) {
+ printMethod(method);
}
_end();
_classGenerator() ;
-
- return;
-
}
private void printMethod(Method m) {
boolean throwsRemoteException = false;
- List<Type> exceptionList = new LinkedList<Type>();
- for(Class exception : m.getExceptionTypes()) {
+ List<Type> exceptionList = new LinkedList<>();
+ for (Class<?> exception : m.getExceptionTypes()) {
exceptionList.add(Type.type(exception));
- if( exception.getName().equals("java.rmi.RemoteException") ) {
+ if (exception.getName().equals("java.rmi.RemoteException")) {
throwsRemoteException = true;
}
}
- if( !throwsRemoteException ) {
+ if (!throwsRemoteException) {
exceptionList.add(_t("java.rmi.RemoteException"));
}
- exceptionList.add(_t("com.sun.ejb.containers.InternalEJBContainerException"));
+ exceptionList.add(_t(InternalEJBContainerException.class.getName()));
_method(PUBLIC | ABSTRACT, Type.type(m.getReturnType()), m.getName(), exceptionList);
int i = 0;
- for(Class param : m.getParameterTypes()) {
+ for (Class<?> param : m.getParameterTypes()) {
_arg(Type.type(param), "param" + i);
i++;
}
_end();
}
-
-
}
diff --git a/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/codegen/ServiceInterfaceGenerator.java b/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/codegen/ServiceInterfaceGenerator.java
index d639f2a..ed9abd8 100644
--- a/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/codegen/ServiceInterfaceGenerator.java
+++ b/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/codegen/ServiceInterfaceGenerator.java
@@ -1,5 +1,6 @@
/*
* Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021 Contributors to the Eclipse Foundation
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -18,21 +19,23 @@
import java.lang.reflect.Method;
-import java.util.List;
+import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.LinkedList;
-
-import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper.*;
+import java.util.List;
import org.glassfish.pfl.dynamic.codegen.spi.Type ;
-import java.util.logging.Logger;
-
import jakarta.jws.WebMethod;
-import static java.lang.reflect.Modifier.*;
-
-import com.sun.enterprise.util.LocalStringManagerImpl;
-import com.sun.logging.LogDomains;
+import static java.lang.reflect.Modifier.ABSTRACT;
+import static java.lang.reflect.Modifier.PUBLIC;
+import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._arg;
+import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._clear;
+import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._end;
+import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._interface;
+import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._method;
+import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._package;
+import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._t;
/**
* This class is responsible for generating the SEI when it is not packaged
@@ -40,98 +43,52 @@
*
* @author Jerome Dochez
*/
-public class ServiceInterfaceGenerator extends Generator
- implements ClassGeneratorFactory {
+public class ServiceInterfaceGenerator extends Generator {
- private static LocalStringManagerImpl localStrings =
- new LocalStringManagerImpl(ServiceInterfaceGenerator.class);
- private static Logger _logger=null;
- static{
- _logger=LogDomains.getLogger(ServiceInterfaceGenerator.class, LogDomains.DPL_LOGGER);
- }
-
- Class sib=null;
- String serviceIntfName;
- String packageName;
- String serviceIntfSimpleName;
- Method[] intfMethods;
+ private final Class<?> ejbClass;
+ private final String packageName;
+ private final String serviceIntfName;
+ private final String serviceIntfSimpleName;
+ private final Method[] intfMethods;
/**
* Construct the Wrapper generator with the specified deployment
* descriptor and class loader.
- * @exception GeneratorException.
*/
- public ServiceInterfaceGenerator(ClassLoader cl, Class sib)
- throws GeneratorException, ClassNotFoundException
- {
- super();
-
- this.sib = sib;
- serviceIntfSimpleName = getServiceIntfName();
-
- packageName = getPackageName();
- serviceIntfName = packageName + "." + serviceIntfSimpleName;
-
- intfMethods = calculateMethods(sib, removeDups(sib.getMethods()));
+ public ServiceInterfaceGenerator(Class<?> ejbClass) {
+ this.ejbClass = ejbClass;
+ packageName = getPackageName(ejbClass.getName());
+ serviceIntfSimpleName = getServiceIntfName(ejbClass);
+ serviceIntfName = (packageName == null ? "" : packageName + ".") + serviceIntfSimpleName;
+ intfMethods = calculateMethods(ejbClass, removeRedundantMethods(ejbClass.getMethods()));
// NOTE : no need to remove ejb object methods because EJBObject
// is only visible through the RemoteHome view.
}
- public String getServiceIntfName() {
- String serviceIntfSimpleName = sib.getSimpleName();
- if (serviceIntfSimpleName.endsWith("EJB")) {
- return serviceIntfSimpleName.substring(0, serviceIntfSimpleName.length()-3);
- } else {
- return serviceIntfSimpleName+"SEI";
- }
- }
-
- public String getPackageName() {
- return sib.getPackage().getName()+".internal.jaxws";
- }
/**
* Get the fully qualified name of the generated class.
+ * <p>
* Note: the remote/local implementation class is in the same package
* as the bean class, NOT the remote/local interface.
+ *
* @return the name of the generated class.
*/
- public String getGeneratedClass() {
+ @Override
+ public String getGeneratedClassName() {
return serviceIntfName;
}
- // For corba codegen infrastructure
- public String className() {
- return getGeneratedClass();
+
+ @Override
+ public Class<?> getAnchorClass() {
+ return ejbClass;
}
- private Method[] calculateMethods(Class sib, Method[] initialList) {
- // we start by assuming the @WebMethod was NOT used on this class
- boolean webMethodAnnotationUsed = false;
- List<Method> list = new ArrayList<Method>();
-
- for (Method m : initialList) {
- WebMethod wm = m.getAnnotation(WebMethod.class);
- if ( (wm != null) && !webMethodAnnotationUsed) {
- webMethodAnnotationUsed=true;
- // reset the list, this is the first annotated method we find
- list.clear();
- }
- if (wm!=null) {
- list.add(m);
- } else {
- if (!webMethodAnnotationUsed && !m.getDeclaringClass().equals(java.lang.Object.class)) {
- list.add(m);
- }
- }
- }
- return list.toArray(new Method[list.size()]);
- }
-
+ @Override
public void evaluate() {
-
_clear();
if (packageName != null) {
@@ -140,38 +97,31 @@
_interface(PUBLIC, serviceIntfSimpleName);
- for(int i = 0; i < intfMethods.length; i++) {
- printMethod(intfMethods[i]);
+ for (Method intfMethod : intfMethods) {
+ printMethod(intfMethod);
}
_end();
-
- return;
-
}
- private void printMethod(Method m)
- {
-
+ private void printMethod(Method m) {
boolean throwsRemoteException = false;
- List<Type> exceptionList = new LinkedList<Type>();
- for(Class exception : m.getExceptionTypes()) {
+ List<Type> exceptionList = new LinkedList<>();
+ for (Class<?> exception : m.getExceptionTypes()) {
exceptionList.add(Type.type(exception));
- if( exception.getName().equals("java.rmi.RemoteException") ) {
+ if (exception.getName().equals(RemoteException.class.getName())) {
throwsRemoteException = true;
}
- }
- if( !throwsRemoteException ) {
- exceptionList.add(_t("java.rmi.RemoteException"));
+ }
+ if (!throwsRemoteException) {
+ exceptionList.add(_t(RemoteException.class.getName()));
}
- _method( PUBLIC | ABSTRACT, Type.type(m.getReturnType()),
- m.getName(), exceptionList);
+ _method(PUBLIC | ABSTRACT, Type.type(m.getReturnType()), m.getName(), exceptionList);
int i = 0;
-
- for(Class param : m.getParameterTypes()) {
+ for (Class<?> param : m.getParameterTypes()) {
_arg(Type.type(param), "param" + i);
i++;
}
@@ -179,4 +129,36 @@
_end();
}
+
+ private static String getServiceIntfName(Class<?> ejbClass) {
+ String serviceIntfSimpleName = ejbClass.getSimpleName();
+ if (serviceIntfSimpleName.endsWith("EJB")) {
+ return serviceIntfSimpleName.substring(0, serviceIntfSimpleName.length() - 3) + "_GeneratedSEI";
+ }
+ return serviceIntfSimpleName + "_GeneratedSEI";
+ }
+
+
+ private static Method[] calculateMethods(Class sib, Method[] initialList) {
+ // we start by assuming the @WebMethod was NOT used on this class
+ boolean webMethodAnnotationUsed = false;
+ List<Method> list = new ArrayList<>();
+
+ for (Method m : initialList) {
+ WebMethod wm = m.getAnnotation(WebMethod.class);
+ if (wm != null && !webMethodAnnotationUsed) {
+ webMethodAnnotationUsed = true;
+ // reset the list, this is the first annotated method we find
+ list.clear();
+ }
+ if (wm != null) {
+ list.add(m);
+ } else {
+ if (!webMethodAnnotationUsed && !m.getDeclaringClass().equals(Object.class)) {
+ list.add(m);
+ }
+ }
+ }
+ return list.toArray(new Method[list.size()]);
+ }
}
diff --git a/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/containers/BaseContainer.java b/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/containers/BaseContainer.java
index 48b787a..8c89bea 100644
--- a/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/containers/BaseContainer.java
+++ b/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/containers/BaseContainer.java
@@ -1103,8 +1103,8 @@
Class serviceEndpointIntfClass = loader.loadClass(webServiceEndpoint.getServiceEndpointInterface());
if (!serviceEndpointIntfClass.isInterface()) {
- ServiceInterfaceGenerator generator = new ServiceInterfaceGenerator(loader, ejbClass);
- serviceEndpointIntfClass = EJBUtils.generateSEI(generator, loader, this.ejbClass);
+ ServiceInterfaceGenerator generator = new ServiceInterfaceGenerator(ejbClass);
+ serviceEndpointIntfClass = EJBUtils.generateSEI(generator, loader);
if (serviceEndpointIntfClass == null) {
throw new RuntimeException(localStrings.getLocalString("ejb.error_generating_sei",
"Error in generating service endpoint interface class for EJB class {0}", this.ejbClass));
diff --git a/appserver/ejb/ejb-container/src/test/java/com/sun/ejb/EJBUtilsTest.java b/appserver/ejb/ejb-container/src/test/java/com/sun/ejb/EJBUtilsTest.java
index ab949d8..b81f13d 100644
--- a/appserver/ejb/ejb-container/src/test/java/com/sun/ejb/EJBUtilsTest.java
+++ b/appserver/ejb/ejb-container/src/test/java/com/sun/ejb/EJBUtilsTest.java
@@ -18,13 +18,16 @@
import com.sun.ejb.codegen.ClassGeneratorFactory;
import com.sun.ejb.codegen.Generator;
+import com.sun.ejb.codegen.Remote30WrapperGenerator;
import com.sun.ejb.codegen.ServiceInterfaceGenerator;
import java.util.Collection;
import java.util.concurrent.TimeUnit;
-import org.glassfish.pfl.dynamic.codegen.spi.Wrapper;
+import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
+import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.results.Result;
@@ -34,7 +37,6 @@
import org.openjdk.jmh.runner.options.OptionsBuilder;
import org.openjdk.jmh.runner.options.TimeValue;
-import static java.lang.reflect.Modifier.PUBLIC;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.lessThan;
@@ -47,53 +49,71 @@
/**
* @author David Matejcek
*/
+@TestMethodOrder(OrderAnnotation.class)
public class EJBUtilsTest {
+ /**
+ * The value shall be high enough to pass on all standard environments,
+ * but lower than when we are generating classes. See warmup results in logs.
+ */
+ private static final double MAX_TIME_PER_OPERATION = 1_000_000d;
private static final ClassLoader loader = EJBUtilsTest.class.getClassLoader();
+ private static double firstRunScore;
@Test
- public void generateSEI_Benchmark() throws Exception {
+ @Order(1)
+ public void generateAndLoad_firstRun() throws Exception {
Options options = new OptionsBuilder()
.include(getClass().getName() + ".*")
- .mode(Mode.AverageTime)
.warmupIterations(0)
- .measurementIterations(2)
- .measurementTime(TimeValue.seconds(1L))
- .forks(1)
- .threads(20)
- .shouldFailOnError(true)
- .shouldDoGC(true)
- .timeout(TimeValue.seconds(5L))
- .timeUnit(TimeUnit.NANOSECONDS)
+ .measurementIterations(1).forks(1).measurementTime(TimeValue.milliseconds(50L))
+ // should be able to detect deadlocks and race conditions when generating classes
+ .threads(100).timeout(TimeValue.seconds(5L))
+ .timeUnit(TimeUnit.MICROSECONDS)
+ .mode(Mode.SingleShotTime).shouldFailOnError(true)
.build();
Collection<RunResult> results = new Runner(options).run();
assertThat(results, hasSize(1));
- Result<?> result = results.iterator().next().getAggregatedResult().getPrimaryResult();
- assertThat(result.getScore(), lessThan(100000d));
+ Result<?> primaryResult = results.iterator().next().getPrimaryResult();
+ firstRunScore = primaryResult.getScore();
+ assertThat(primaryResult.getScore(), lessThan(MAX_TIME_PER_OPERATION));
+ }
+
+
+ @Test
+ @Order(2)
+ public void generateAndLoad_Benchmark() throws Exception {
+ Options options = new OptionsBuilder()
+ .include(getClass().getName() + ".*")
+ .warmupBatchSize(1).warmupForks(0).warmupIterations(1).warmupTime(TimeValue.milliseconds(50L))
+ .measurementIterations(1).forks(1).measurementTime(TimeValue.milliseconds(200L))
+ // should be able to detect race conditions when loading classes generated in previous test
+ .threads(100).timeout(TimeValue.seconds(5L))
+ .timeUnit(TimeUnit.MICROSECONDS)
+ .mode(Mode.AverageTime).shouldFailOnError(true)
+ .build();
+
+ Collection<RunResult> results = new Runner(options).run();
+ assertThat(results, hasSize(1));
+ Result<?> primaryResult = results.iterator().next().getPrimaryResult();
+ assertThat(primaryResult.getScore(), lessThan(firstRunScore / 4));
}
@Benchmark
- public void generateSei_Benchmark() throws Exception {
- ClassGeneratorFactory generator = new CustomGenerator();
- Class<?> newClass = EJBUtils.generateSEI(generator, loader, EJbUtilsEjbTestClass.class);
+ public void generateAndLoad() throws Exception {
+ // random interface for the test
+ String interfaceName = ClassGeneratorFactory.class.getName();
+ Generator generator = new Remote30WrapperGenerator(loader, interfaceName, interfaceName);
+ Class<?> newClass = EJBUtils.generateAndLoad(generator, loader);
assertNotNull(newClass);
- assertEquals(generator.className(), newClass.getName());
+ assertEquals(generator.getGeneratedClassName(), newClass.getName());
}
@Test
- public void generateSei_ServiceInterfaceGenerator() throws Exception {
- ServiceInterfaceGenerator generator = new ServiceInterfaceGenerator(loader, EJbUtilsEjbTestClass.class);
- // FIXME: com.sun.ejb.EJBUtilsTest$EJbUtilsEjbTestClass doesn't have expected package com.sun.ejb.internal.jaxws
- Class<?> newClass = EJBUtils.generateSEI(generator, loader, EJbUtilsEjbTestClass.class);
- assertNotNull(newClass);
- assertEquals(generator.className(), newClass.getName());
- }
-
-
- @Test
+ @Order(10)
public void loadGeneratedRemoteBusinessClasses() throws Exception {
EJBUtils.loadGeneratedRemoteBusinessClasses(EjbUtilsTestInterface.class.getName());
Class<?> ifaceRemote = loader.loadClass("com.sun.ejb._EJBUtilsTest$EjbUtilsTestInterface_Remote");
@@ -105,6 +125,7 @@
@Test
+ @Order(20)
public void loadGeneratedGenericEJBHomeClass() throws Exception {
Class<?> newClass = EJBUtils.loadGeneratedGenericEJBHomeClass(loader);
assertNotNull(newClass);
@@ -113,34 +134,18 @@
assertSame(newClass, EJBUtils.loadGeneratedGenericEJBHomeClass(loader));
}
- private static class CustomGenerator extends Generator implements ClassGeneratorFactory {
- @Override
- public String getGeneratedClass() {
- return "com.sun.ejb.EJBUtilsTestImplFromCustomGenerator";
- }
-
- @Override
- public String className() {
- return getGeneratedClass();
- }
-
- @Override
- public void evaluate() {
- Wrapper._clear();
- Wrapper._package(getPackageName(className()));
- Wrapper._interface(PUBLIC, getBaseName(className()));
- Wrapper._classGenerator();
- }
+ @Test
+ @Order(30)
+ public void generateSEI() throws Exception {
+ Generator generator = new ServiceInterfaceGenerator(ClassGeneratorFactory.class);
+ Class<?> newClass = EJBUtils.generateSEI(generator, loader);
+ assertNotNull(newClass);
+ assertEquals(generator.getGeneratedClassName(), newClass.getName());
}
interface EjbUtilsTestInterface {
void doSomething();
}
-
-
- public static class EJbUtilsEjbTestClass {
-
- }
}