FileDocCategorySizeDatePackage
RMICompiler.javaAPI DocGlassfish v2 API9198Fri May 04 22:32:58 BST 2007com.sun.ejb.codegen

RMICompiler

public class RMICompiler extends Compiler

Fields Summary
private static final String
RMIC_EXT_DIRS_OPTION
private File
rmicExe
private File
javaExe
private Set
generatedFilenames
private String
classpath
private static int
timeout
Constructors Summary
RMICompiler(List theOptions, List theFiles)


	     
	
		super(theOptions, theFiles);
	
Methods Summary
java.util.SetgetGeneratedFilenames()

		return generatedFilenames;
	
private static intgetRmicTimeout()
Returns the timeout, in milliseconds, for each java file. The compiler calling code will multiply this value by the number of java files. If the compiler takes longer than this amount of time the process will be killed. This is to avoid hangs.

For flexibility, a environmental variable is checked first. Failing that, it will use the hard-coded default value.

This method caches the value of timeout in "timeout" variable to prevent memory leak seen in the System.getProperty method in Compiler.java

return
The timeout, in milliseconds, for each java file

	    	if(timeout < 0 ) 
		{
			timeout = getTimeout(Constants.RMIC_TIMEOUT_MS, Constants.DEFAULT_RMIC_TIMEOUT_MS, 5000, 300000);
		}
		return timeout;
	
protected voidinternal_compile()

		try
		{
			if(nativeExternalCompile())
				return;
		}
		catch(Throwable t)
		{
                    logger.log(Level.WARNING, 
                               "ejb.rmic_compilation_exception", t);
			// fall through to nativeCompile()
			// I know what you're thinking -- why run the native compile
			// if the the external already didn't work?  For some reason
			// the external will time out and we won't get an error message.
			// The native call will always give an error message.
		}
		
		nativeCompile();
	
protected voidinternal_init()

		rmicExe		= null;
		javaExe		= null;
		String rmicName, javaName;
	
		if(jdkDir == null)
			return;
		
		if(OS.isWindows())
		{
			rmicName	= "rmic.exe";
			javaName	= "java.exe";
		}
		else
		{
			rmicName	= "rmic";
			javaName	= "java";
		}
		
		// if rmic app can be located -- set it
		rmicExe = new File(jdkDir + "/bin/" + rmicName);
		
		if(rmicExe.exists())
			rmicExe = FileUtils.safeGetCanonicalFile(rmicExe);
		else
			rmicExe = null;

		// if external JVM can be located -- set it
		javaExe = new File(jdkDir + "/bin/" + javaName);
		
		if(javaExe.exists())
			javaExe = FileUtils.safeGetCanonicalFile(javaExe);
		else
			javaExe = null;

        logger.log(Level.FINE, "[RMICompiler] after internal_init: "
                + "javaExe: " + javaExe + "; rmicExe: " + rmicExe);
	
private voidnativeCompile()
This can't work -- the jdk's rmic executable doesn't have the iAS hacks private boolean rmicCompile() throws ProcessExecutorException { if(rmicExe == null || DONT_USE_RMIC_YET) return false; ArrayList cmd = new ArrayList(); cmd.add(rmicExe.getPath()); cmd.addAll(options); addJavaFiles(cmd); String[] cmds = new String[cmd.size()]; cmds = (String[])cmd.toArray(cmds); runProcess(cmds, getRmicTimeout() * files.size()); logCompilerName("stand-alone rmic"); return true; }

		//options.add("-Xnocompile");
		//options.add("-verbose");
            options.add(RMIC_EXT_DIRS_OPTION);
            options.add(System.getProperty(JAVA_EXT_DIRS_SYS_PROP));
		options.addAll(files);
		String[] cmds = new String[options.size()];
		cmds = (String[])options.toArray(cmds);
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		
		Main	compiler	= new Main(baos, "rmic");
		boolean	good		= compiler.compile(cmds);
		//good = true;	// it ALWAYS returns an "error" if -Xnocompile is used!!
		
		String output = baos.toString();
		parseGeneratedFilenames(output);
		
		if(!good)
		{
			throw new JavaCompilerException("rmi_compiler.error",
				"RMI compiler returned an error: {0}", output);
		}
		
		logCompilerName("native rmic (sun.rmi.rmic.Main)");
	
private booleannativeExternalCompile()

		if(classpath == null || javaExe == null)
			return false;
		
                
		ArrayList cmd = new ArrayList();
		cmd.add(javaExe.getPath());
		cmd.add("-classpath");
		cmd.add(classpath);
                if (OS.isDarwin()) {
                    // add lib/endorsed so it finds the right rmic
                    cmd.add("-Djava.endorsed.dirs=" + System.getProperty("com.sun.aas.installRoot") + 
                        File.separatorChar + "lib" + File.separatorChar + "endorsed");
                }
                cmd.add("-D" + JAVA_EXT_DIRS_SYS_PROP + "=" 
                        + System.getProperty(JAVA_EXT_DIRS_SYS_PROP));
		cmd.add("sun.rmi.rmic.Main");
		cmd.addAll(options);
		addJavaFiles(cmd);
		String[] cmds = new String[cmd.size()];
		cmds = (String[])cmd.toArray(cmds);

		runProcess(cmds, getRmicTimeout() * files.size());
		logCompilerName("rmic in external JVM");
		return true;
	
private voidparseGeneratedFilenames(java.lang.String s)
sun.rmi.rmic will return output like this: [generated d:\iAS7\domains\domain1\server1\generated\ejb\j2ee-apps\JDBCSimple\samples\jdbc\simple\ejb\_GreeterDBBean_EJBObjectImpl_Tie.java in 50 ms] [generated d:\iAS7\domains\domain1\server1\generated\ejb\j2ee-apps\JDBCSimple\org\omg\stub\com\sun\ejb\containers\_EJBObjectImpl_Tie.java in 20 ms] [loaded C:\iplanetx\jars\appserv-ext.jar(javax/ejb/CreateException.class) in 0 ms] A better solution is to modify rmic to simply return an array of filenames. But I can't get rmic changes to stick -- it's unclear which version is really being called. This will work for now

return
a Set of full path filenames of the generated files.

		generatedFilenames = new HashSet();
		
		StringTokenizer tk = new StringTokenizer(s);

		while(tk.hasMoreTokens()) 
		{
			String token = tk.nextToken();
			
			if(token.equals("[generated") && tk.hasMoreTokens())
			{
					String fName = tk.nextToken();
					generatedFilenames.add(fName);
					logger.log(Level.FINER, "[RMIC] Generated: " + fName);
			}
		}
	
voidsetClasspath(java.lang.String cp)

		classpath = cp;