IASEJBCpublic final class IASEJBC extends Object Handles all ejb related codegen. Also does webservices code generation. |
Fields Summary |
---|
private static final com.sun.enterprise.util.i18n.StringManager | localStrings | private static final Logger | _logger |
Constructors Summary |
---|
private IASEJBC()This class is only instantiated internally.
|
Methods Summary |
---|
private void | addGeneratedFiles(java.util.Set stubClasses, java.util.Vector allClientFiles, java.io.File stubsDir)Assembles the name of the client jar files into the given vector.
for (Iterator iter = stubClasses.iterator(); iter.hasNext();) {
String next = (String) iter.next();
String stubFile = stubsDir.toString() + File.separator +
GeneratedNames.getStubName(next).replace('.",
File.separatorChar) + ".class";
allClientFiles.add(stubFile);
}
_logger.log(Level.FINE,
"[EJBC] Generated client files: " + allClientFiles);
| private void | compileAndRmic(java.lang.String classPath, java.util.List rmicOptions, java.util.Set stubClasses, java.io.File destDir, java.lang.String repository)Compile all the generated .java files, run rmic on them.
if( (stubClasses.size() == 0) ) {
_logger.log(Level.FINE, "[EJBC] No code generation required");
return;
}
progress(localStrings.getStringWithDefault(
"generator.compiling_rmi_iiop",
"Compiling RMI-IIOP code."));
List options = new ArrayList();
List fileList = new ArrayList();
options.addAll(rmicOptions);
options.add("-classpath");
String bigClasspath = System.getProperty("java.class.path")
+ File.pathSeparator + classPath
+ File.pathSeparator + repository;
options.add(bigClasspath);
options.add("-d");
options.add(destDir.toString());
for(Iterator extraIter = stubClasses.iterator();
extraIter.hasNext();) {
String next = (String) extraIter.next();
_logger.log(Level.FINE,"[EJBC] rmic " + next + "...");
fileList.add(next);
}
try {
RMICompiler rmic = new RMICompiler(options, fileList);
rmic.setClasspath(bigClasspath);
rmic.compile();
} catch(JavaCompilerException e) {
_logger.log(Level.FINE,"ejbc.codegen_rmi_fail",e);
String msg =
localStrings.getString("generator.rmic_compilation_failed");
GeneratorException ge = new GeneratorException(msg);
ge.initCause(e);
throw ge;
}
if (_logger.isLoggable(Level.FINE)){
StringBuffer sbuf = new StringBuffer();
for(Iterator it = options.iterator(); it.hasNext(); ) {
sbuf.append("\n\t").append(it.next());
}
for(Iterator it = fileList.iterator(); it.hasNext(); ) {
sbuf.append("\n\t").append(it.next());
}
_logger.log(Level.FINE,"[EJBC] RMIC COMMAND: " + sbuf.toString());
}
return;
| public static void | compileClasses(java.lang.String classPath, java.util.Vector files, java.io.File destDir, java.lang.String repository, java.util.List javacOptions)Compile .java files.
List options = new ArrayList();
List fileList = new ArrayList();
if (files.size() <= 0) {
return;
}
// adds the passed in javac options
options.addAll(javacOptions);
options.add("-d");
options.add(destDir.toString());
options.add("-classpath");
options.add(System.getProperty("java.class.path")
+ File.pathSeparator + classPath
+ File.pathSeparator + repository);
fileList.addAll(files);
for(Iterator it = fileList.iterator(); it.hasNext(); )
{
String file = (String)it.next();
_logger.log(Level.FINE,localStrings.getStringWithDefault(
"generator.compile",
"Compiling {0} ...", new Object[] {file} ));
}
if (_logger.isLoggable(Level.FINE)) {
StringBuffer sbuf = new StringBuffer();
for ( Iterator it = options.iterator(); it.hasNext(); ) {
sbuf.append("\n\t").append((String)it.next());
}
_logger.log(Level.FINE,"[EJBC] JAVAC COMMAND: " + sbuf.toString());
}
long start = System.currentTimeMillis();
long end = start;
try {
JavaCompiler jc = new JavaCompiler(options, fileList);
jc.compile();
} catch(JavaCompilerException jce) {
_logger.log(Level.FINE,"ejbc.codegen_compile_failed", jce);
String msg =
localStrings.getStringWithDefault(
"generator.java_complilation_failed",
"Compilation failed: {0}",
new Object[] {jce.getMessage()} );
GeneratorException ge = new GeneratorException(msg);
ge.initCause(jce);
throw ge;
}
end = System.currentTimeMillis();
_logger.log(Level.FINE,"JAVA compile time (" + fileList.size()
+ " files) = " + (end - start));
| private java.io.OutputStream | createOutputStream(java.lang.String fileName)Create the FileOutputStream for the specified class.
File file = new File(fileName);
File parent = null;
if ( (parent=file.getParentFile()) != null)
{
if ( !parent.exists() )
{
parent.mkdirs();
}
}
FileOutputStream out = new FileOutputStream(fileName);
BufferedOutputStream bout = new BufferedOutputStream(out);
return bout;
| private com.sun.enterprise.util.zip.ZipItem[] | doCompile(EjbcContext ejbcCtx)
// stubs dir for the current deployment
File stubsDir = ejbcCtx.getStubsDir();
// deployment descriptor object representation
Application application = ejbcCtx.getDescriptor();
long startTime = now();
long time; // scratchpad variable
_logger.log(Level.FINE, "ejbc.begin",application.getRegistrationName());
// class path to be used for this application during javac & rmic
String classPath = getClassPath(ejbcCtx.getClasspathUrls(), stubsDir);
// Warning: A class loader is passed in while constructing the
// application object
final ClassLoader jcl = application.getClassLoader();
// creates the stubs dir if it does not exist
if (!stubsDir.exists()) {
stubsDir.mkdirs();
}
// stubs dir is used as repository for code generator
final String gnrtrTMP = stubsDir.getCanonicalPath();
// previous thread context class loader
final ClassLoader oContextCL =
Thread.currentThread().getContextClassLoader();
// sets the thread context classloader for use by rmic etc.
if(System.getSecurityManager() == null) {
Thread.currentThread().setContextClassLoader(jcl);
} else {
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() {
public Object run() {
Thread.currentThread().setContextClassLoader(jcl);
return null;
}
});
}
// ---- CMP --------------------------------------------------------
if (application.containsCMPEntity()) {
CmpCompiler cmpc = new CmpCompiler(ejbcCtx);
cmpc.compile();
}
// ---- END OF CMP -------------------------------------------------
// ---- EJB DEPLOYMENT DESCRIPTORS -------------------------------
Vector ejbRemoteDeploymentDescriptors = new Vector();
Set ejbHomeInterfaces = new HashSet();
Set ejbRemoteInterfaces = new HashSet();
Set<String> nonSerializableSfulClasses = new HashSet();
Set<String> ejb30RemoteBusinessInterfaces = new HashSet();
// Open the app using the JarClassLoader to load classes.
// This allows the descriptors to find generated classes
// (e.g. the generated CMP bean class) as soon as they are
// compiled below.
int ejbCount = 0;
Iterator iter = application.getEjbDescriptors().iterator();
// The main use-case we want to support is the one where existing
// stand-alone java clients that access ejbs in our appserver
// through CosNaming need the generated stubs. We don't want to
// force them to run rmic themselves so it's better for them
// just to tell us during the deployment of an ejb client app
// or ejb app that we should run rmic and put the stubs in the
// client.jar. Turning on the deployment-time rmic flag ONLY
// controls the generation of rmic stubs. It is independent of the
// run-time decision about whether to use dynamic RMI stubs. By
// default, dynamic stubs will be used in the server, in
// the Application Client container, and in stand-alone clients
// that instantiate our naming service. If the server has been
// explicitly configured for static RMI stubs by use of the
// internal ORB system property, we will always call RMIC.
boolean generateRmicStubs =
( ejbcCtx.getDeploymentRequest().getGenerateRMIStubs() );
// ||
// !EJBUtils.getOrbUseDynamicStubs() );
while (iter.hasNext()) {
ejbCount++;
EjbDescriptor next = (EjbDescriptor) iter.next();
if( next.isLocalBusinessInterfacesSupported() ) {
for(String nextBusIntfStr :
next.getLocalBusinessClassNames() ) {
Class intf = jcl.loadClass(nextBusIntfStr);
if(javax.ejb.EJBLocalObject.class.isAssignableFrom(intf)) {
throw new GeneratorException("Invalid Local Business "
+ "Interface " + intf + ". A Local Business " +
"interface MUST not extend javax.ejb.EJBLocalObject");
}
}
}
if( next.isRemoteInterfacesSupported() ) {
if( generateRmicStubs ) {
ejbRemoteDeploymentDescriptors.addElement(next);
ejbHomeInterfaces.add(next.getHomeClassName());
ejbRemoteInterfaces.add(next.getRemoteClassName());
} else {
_logger.log(Level.FINE,
"Skipping RMI-IIOP STUB generation for"
+ " " + next.getName());
}
}
if( next.isRemoteBusinessInterfacesSupported() ) {
for(String nextIntf : next.getRemoteBusinessClassNames() ) {
// If there's more than one ejb with same
// Remote business interface, only generate
// the artifacts once. This will work since
// there is nothing bean-specific about the
// generated artifacts. Their only dependency is
// the corresponding Remote business interface.
if( !ejb30RemoteBusinessInterfaces.contains(nextIntf) ) {
ejb30RemoteBusinessInterfaces.add(nextIntf);
}
}
}
if( next.getType().equals(EjbSessionDescriptor.TYPE) &&
((EjbSessionDescriptor)next).isStateful() ) {
Set<String> classNames = new HashSet<String>();
classNames.add(next.getEjbClassName());
classNames.addAll(next.getInterceptorClassNames());
for(String className : classNames) {
Class clazz = jcl.loadClass(className);
if( !Serializable.class.isAssignableFrom(clazz) ) {
// Add for processing. Duplicates will be ignored
// by Set.
nonSerializableSfulClasses.add(className);
}
}
}
}
// Need to generate Remote 3.0 internal intf/wrappers for
// EJB 3.0 Remote clients as well. This will be removed
// when we move to the new codegen API.
Vector ejbRefs = application.getEjbReferenceDescriptors();
for (int i = 0; i < ejbRefs.size(); i++) {
EjbReferenceDescriptor next =
(EjbReferenceDescriptor) ejbRefs.get(i);
if( next.isEJB30ClientView() && !next.isLocal() ) {
String busInterface = next.getEjbInterface();
if( !ejb30RemoteBusinessInterfaces.contains(busInterface) ) {
ejb30RemoteBusinessInterfaces.add(busInterface);
}
}
}
progress(localStrings.getStringWithDefault
("generator.processing_beans", "Processing beans..."));
// ---- END OF EJB DEPLOYMENT DESCRIPTORS --------------------------
// ---- LOCAL HOME & OBJECT ----------------------------------------
FileArchive dArchive = new FileArchive();
dArchive.open(gnrtrTMP);
DeploymentContext context = new DeploymentContext(dArchive,application);
// Generate code for Remote EJB 30 business interfaces
Vector remote30Files = new Vector();
if( EJBUtils.useStaticCodegen() ) {
// Generic a single generic home interface for this application.
Generator genericHomeGen = new GenericHomeGenerator
(context.getClassLoader());
generateCode(genericHomeGen, remote30Files, stubsDir);
for (String businessIntf : ejb30RemoteBusinessInterfaces) {
// generate RMI-IIOP version of Remote business interface
Generator remoteGen =
new RemoteGenerator(context.getClassLoader(),
businessIntf);
generateCode(remoteGen, remote30Files, stubsDir);
Generator clientGen = new Remote30WrapperGenerator
(context.getClassLoader(), businessIntf,
remoteGen.getGeneratedClass());
generateCode(clientGen, remote30Files, stubsDir);
}
// log completion message
if (remote30Files.size() > 0) {
// compile generated Remote business interfaces
time = now();
compileClasses(classPath, remote30Files, stubsDir, gnrtrTMP,
ejbcCtx.getJavacOptions());
ejbcCtx.getTiming().javaCompileTime += (now() - time);
_logger.fine("Done generating Remote business intfs");
}
// Generate any serializable sub-classes for EJB 3.0 stateful
// session beans and stateful session bean interceptors that
// don't implement Serializable. These classes
// are not put in the client.jar.
Vector serializableSfulSubClasses = new Vector();
for(String className : nonSerializableSfulClasses) {
Generator serializableSfulGen =
new SerializableBeanGenerator(context.getClassLoader(),
className);
generateCode(serializableSfulGen, serializableSfulSubClasses,
stubsDir);
}
if( serializableSfulSubClasses.size() > 0 ) {
// compile generated stateful serializable sub-classes
time = now();
compileClasses(classPath, serializableSfulSubClasses, stubsDir,
gnrtrTMP, ejbcCtx.getJavacOptions());
ejbcCtx.getTiming().javaCompileTime += (now() - time);
_logger.fine("Generated Stateful Serializable subclasses");
}
}
// ---- WEB SERVICES -----------------------------------------------
if (_logger.isLoggable(Level.FINE)) {
_logger.log(Level.FINE, "ejbc.start_jaxrpc_generation",
application.getRegistrationName());
}
time = now();
JaxRpcCodegenFactory jaxrpcFactory =
JaxRpcCodegenFactory.newInstance();
JaxRpcCodegenAdapter jaxrpcAdapter = jaxrpcFactory.getAdapter();
jaxrpcAdapter.run(ejbcCtx);
ejbcCtx.getTiming().jaxrpcGenerationTime += (now() - time);
if (_logger.isLoggable(Level.FINE)) {
_logger.log(Level.FINE, "ejbc.end_jaxrpc_generation",
application.getRegistrationName());
}
// this should not be here but in AppDeployer or such but since
// the archive file is saved at then end of this ejbc process, and
// the servlet swith may require to save the DDs, I decided to put
// it here until we rework the codegen pluggability.
WebServiceDeployer deployer =
new WebServiceDeployer(ejbcCtx.getDeploymentRequest());
deployer.doWebServiceDeployment(ejbcCtx.getDescriptor(),
ejbcCtx.getSrcDir());
// ---- END OF WEB SERVICES ----------------------------------------
// ---- RMIC ALL STUB CLASSES --------------------------------------
Set allStubClasses = new HashSet();
if( generateRmicStubs ) {
// stubs classes for ejbs within this app that need rmic
Set ejbStubClasses = getStubClasses(jcl, ejbHomeInterfaces,
ejbRemoteInterfaces, ejbRemoteDeploymentDescriptors);
// stubs for any J2EE components within the app that are clients
// of remote ejbs but where the target ejbs are not defined within
// the app
Set ejbClientStubClasses =
getEjbClientStubClasses(jcl, application, ejbStubClasses);
allStubClasses.addAll(ejbStubClasses);
allStubClasses.addAll(ejbClientStubClasses);
// Compile and RMIC all Stubs
time = now();
compileAndRmic(classPath, ejbcCtx.getRmicOptions(), allStubClasses,
stubsDir, gnrtrTMP);
ejbcCtx.getTiming().RMICompileTime += (now() - time);
}
// ---- END OF RMIC ALL STUB CLASSES -------------------------------
// Create list of all server files and client files
Vector allClientFiles = new Vector();
// assemble the client files
addGeneratedFiles(allStubClasses, allClientFiles, stubsDir);
if( remote30Files.size() > 0 ) {
Iterator itr = remote30Files.iterator();
if (itr != null) {
for (;itr.hasNext();) {
String file = (String) itr.next();
allClientFiles.add(file.replace(".java", ".class"));
}
}
}
if (jaxrpcAdapter!=null) {
Iterator itr = jaxrpcAdapter.getListOfBinaryFiles();
if (itr!=null) {
for (;itr.hasNext();) {
allClientFiles.add(itr.next());
}
}
}
// client zip entries
ZipItem[] clientStubs = getClientZipEntries(allClientFiles, stubsDir);
_logger.log(Level.FINE, "ejbc.end", application.getRegistrationName());
ejbcCtx.getTiming().totalTime = now() - startTime;
// sets the old thread context classloader back
// this allows the EJB class loader to be garbage collected
if(System.getSecurityManager() == null) {
Thread.currentThread().setContextClassLoader(oContextCL);
} else {
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() {
public Object run() {
Thread.currentThread().setContextClassLoader(oContextCL);
return null;
}
}
);
}
/*
*Clean up, releasing the class loader.
*/
jaxrpcAdapter.done();
return clientStubs;
| public static com.sun.enterprise.util.zip.ZipItem[] | ejbc(EjbcContext ejbcCtx)Generates and compiles the necessary impl classes, stubs and skels.
This method makes the following assumptions:
- the deployment descriptor xmls are registered with Config
- the class paths are registered with Config
IASEJBC ejbc = new IASEJBC();
return ejbc.doCompile(ejbcCtx);
| private java.lang.String | generateCode(Generator gen, java.util.Vector files, java.io.File rep)Runs the generator and adds the generated file to files
String genClass = gen.getGeneratedClass();
String repository = rep.getCanonicalPath();
String genFile = getFileName(genClass, repository);
OutputStream out = createOutputStream(genFile);
PrintStream ps = new PrintStream(out);
((ClassGeneratorFactory)gen).evaluate();
_sourceCode(ps, null);
out.close();
_logger.log(Level.FINE,
"[EJBC] Adding to generated files: " + genFile);
files.addElement(genFile);
return genFile;
| private java.lang.String | getClassName(java.lang.String fileName, java.lang.String repository)Get the class name based on the specified file name.
String className = fileName;
if (className.startsWith(repository))
className = className.substring(repository.length());
if (className.indexOf(".java") != -1)
className = className.substring(0, className.indexOf(".java"));
else if (className.indexOf(".class") != -1)
className = className.substring(0, className.indexOf(".class"));
className = className.replace(File.separatorChar, '.");
if (className.charAt(0) == '.")
className = className.substring(1);
return className;
| private java.lang.String | getClassPath(java.lang.String[] paths, java.io.File other)Helper method - returns the class path as string with path separator.
StringBuffer sb = new StringBuffer();
for (int i=0; i<paths.length; i++) {
sb.append(paths[i]+File.pathSeparator);
}
if (other != null) {
sb.append(other.toString());
}
return sb.toString();
| private com.sun.enterprise.util.zip.ZipItem[] | getClientZipEntries(java.util.Vector allClientFiles, java.io.File stubsDir)Constructs the client zip entries.
// number of client stubs
final int CLIENT_SZ = allClientFiles.size();
ZipItem[] zipEntries = new ZipItem[CLIENT_SZ];
// string representaion of the stubs dir - please note that
// toString is used to convert the file object to string earlier.
// So, canonical path should not be used here
String stubsDirPath = stubsDir.toString();
for (int i=0; i<CLIENT_SZ; i++) {
String longName = (String) allClientFiles.elementAt(i);
File file = new File(longName);
_logger.log(Level.FINE,"[EJBC] stubs - >>"+longName);
// coverts the file name to a jar entry name
String entryName = "";
if (longName.startsWith(stubsDirPath)) {
entryName = longName.substring(stubsDirPath.length());
if (entryName.charAt(0) == File.separatorChar) {
entryName = entryName.substring(1);
}
} else {
// throw exception
String msg =
localStrings.getString("generator.unknown_class_prefix");
throw new RuntimeException(msg);
}
// zip entry has forward slashes
entryName = entryName.replace(File.separatorChar,'/");
// create the zip entry
zipEntries[i] = new ZipItem(file, entryName);
}
// returns the client stubs
return zipEntries;
| private java.util.Set | getEjbClientStubClasses(java.lang.ClassLoader jcl, Application application, java.util.Set stubClasses)Returns the EJB Remote and Home interfaces that do not correspond
to an ejb *within* this application. These will be used to generate
stubs for ejb clients so that no additional packaging is required by
the deployer in cases where the target ejb lives in another application.
Set ejbClientStubClasses = new HashSet();
final String BASE_HOME = "javax.ejb.EJBHome";
final String BASE_REMOTE = "javax.ejb.EJBObject";
Vector ejbRefs = application.getEjbReferenceDescriptors();
for (int i = 0; i < ejbRefs.size(); i++) {
EjbReferenceDescriptor next =
(EjbReferenceDescriptor) ejbRefs.get(i);
if( next.isLocal() || next.isEJB30ClientView() ) {
continue;
}
String home = next.getEjbHomeInterface();
String remote = next.getEjbInterface();
ejbClientStubClasses.add(home);
Set homeSuperIntfs = getRemoteSuperInterfaces(jcl, home);
ejbClientStubClasses.addAll(homeSuperIntfs);
ejbClientStubClasses.add(remote);
Set remoteSuperIntfs = getRemoteSuperInterfaces(jcl, remote);
ejbClientStubClasses.addAll(remoteSuperIntfs);
}
return ejbClientStubClasses;
| private java.lang.String | getFileName(java.lang.String className, java.lang.String repository)Get the java file name based on the specified class name.
return (repository + File.separator
+ className.replace('.", File.separatorChar) + ".java");
| private java.util.Set | getRemoteSuperInterfaces(java.lang.ClassLoader jcl, java.lang.String homeRemoteIntf)
// all super interfaces of home or remote that need to be
// processed for stubs.
Set allSuperInterfaces =
TypeUtil.getSuperInterfaces(jcl, homeRemoteIntf,"java.rmi.Remote");
Set remoteSuperInterfaces = new HashSet();
Iterator iter = allSuperInterfaces.iterator();
while (iter.hasNext()) {
String intfName = (String) iter.next();
Class intfClass = jcl.loadClass(intfName);
if ( java.rmi.Remote.class.isAssignableFrom(intfClass) &&
!(intfName.equals("javax.ejb.EJBHome")) &&
!(intfName.equals("javax.ejb.EJBObject")) ) {
remoteSuperInterfaces.add(intfName);
}
}
return remoteSuperInterfaces;
| private java.util.Set | getStubClasses(java.lang.ClassLoader jcl, java.util.Set ejbHomeInterfaces, java.util.Set ejbRemoteInterfaces, java.util.List remoteEjbDescriptors)Returns all the classes that require RMI-IIOP stubs.
Set stubClasses = new HashSet();
for (Iterator iter = remoteEjbDescriptors.iterator(); iter.hasNext();)
{
EjbDescriptor desc = (EjbDescriptor) iter.next();
String home = desc.getHomeClassName();
String remote = desc.getRemoteClassName();
stubClasses.add(home);
Set homeSuperIntfs = getRemoteSuperInterfaces(jcl, home);
stubClasses.addAll(homeSuperIntfs);
stubClasses.add(remote);
Set remoteSuperIntfs = getRemoteSuperInterfaces(jcl, remote);
stubClasses.addAll(remoteSuperIntfs);
}
return stubClasses;
| private long | now()
return System.currentTimeMillis();
| private void | progress(java.lang.String message)
try {
_logger.log(Level.FINE, message);
} catch(Throwable t) {
_logger.log(Level.FINER,"Cannot set status message",t);
}
|
|