/*
 * The contents of this file are subject to the JOnAS Public License Version 
 * 1.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License on the JOnAS web site.
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied.
 * See the License for the specific terms governing rights and limitations under 
 * the License.
 *
 * The Original Code is JOnAS application server code released July 1999.
 *
 * The Initial Developer of the Original Code is Bull S.A.
 * The Original Code and portions created by Bull S.A. are
 *    Copyright (C) 1999 Bull S.A. All Rights Reserved.
 *
 * Contributor(s): ______________________________________.
 *
 * --------------------------------------------------------------------------
 * $Id: GenIC.java,v 1.4 2000/12/15 15:09:19 jonas Exp $
 * --------------------------------------------------------------------------
 */



package org.objectweb.jonas_ejb.tools;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Vector;

import com.lutris.classloader.MultiClassLoader;

import org.objectweb.common.Env;
import org.objectweb.common.Cmd;
import org.objectweb.jonas_ejb.deployment.api.BeanDesc;
import org.objectweb.jonas_ejb.deployment.api.DeploymentDesc;
import org.objectweb.jonas_ejb.deployment.api.DeploymentDescException;
import org.objectweb.jonas_ejb.deployment.api.EntityDesc;
import org.objectweb.jonas_ejb.deployment.api.EntityBmpDesc;
import org.objectweb.jonas_ejb.deployment.api.EntityCmpDesc;
import org.objectweb.jonas_ejb.deployment.api.EntityJdbcCmpDesc;
import org.objectweb.jonas_ejb.deployment.api.SessionDesc;
import org.objectweb.jonas_ejb.lib.BeanNaming;
import org.objectweb.jonas_ejb.lib.Version;


/**
 *  This class allows to generate:
 * <ul>
 * <li>
 *  the class that implements the Enterprise bean's remote interface, and
 * <li>
 *  the class that implements the Enterprise bean's home interface,
 * </ul>
 * of a given Enterprise Java Bean.
 */

public class GenIC {

    // Is the command is verbose ?
    private boolean verbose = false;

    // Names of the implementation classes (Full names and base names)
    private String wrpRemoteName     = null;
    private String wrpHomeName       = null;
    private String wrpRemoteBaseName = null;
    private String wrpHomeBaseName   = null;
    private String wrpHandleName     = null;
    private String wrpHandleBaseName = null;
    private String wrpBeanName       = null;
    private String wrpBeanBaseName   = null;

    // Path of the java files of the implementation classes
    private String wrpRemoteFileName = null;
    private String wrpHomeFileName   = null;
    private String wrpHandleFileName = null;
    private String wrpBeanFileName   = null;

    // Sources of the Implementation Remote and Home classes
    private GenICHome   srcICHome   = null;
    private GenICRemote srcICRemote = null;
    private GenICHandle srcICHandle = null;      // Warning: May stay to null in case of Session !
    private GenICBean   srcICBean   = null;      // Warning: May stay to null !
    
    // Generate with or without the  propagation of the security  context
    private boolean withSecPropag;

    // Path of the generated files to delete
    private Vector fileNamesToDelete = null;

    // Name of the directory where to place the generated file
    private String directoryOutputName = null;


    /**
     * GenIC Constructor
     *
     * @param     beanDescr      deployment descriptor of the bean
     * @param     dirOutputName  path of the directory where to place the generated files
     * @param     isSecPropag    generation with or without the security propagation
     *                           of the transactionnal context
     * @param     isVerbose      if true, some traces are print
     * @exception GenICException In error case
     */
    public GenIC(BeanDesc beanDesc, String dirOutputName, boolean isSecPropag, boolean isVerbose)
	throws GenICException {

	// Full names of the interfaces and the classes
	String ejbRemoteName;
	String ejbHomeName;
	
	verbose = isVerbose;

	if (verbose) {
	    System.out.println();
	}
	System.out.println("GenIC for JOnAS "+Version.NUMBER+
			   ": Bean '" + beanDesc.getEjbName() + "' generation...");

	withSecPropag = isSecPropag;
	fileNamesToDelete = new Vector();
	directoryOutputName = new String(dirOutputName);

	// Names building
	ejbRemoteName = beanDesc.getRemoteClass().getName();
	ejbHomeName = beanDesc.getHomeClass().getName();
	BeanNaming bn     = new BeanNaming(beanDesc);
	wrpRemoteBaseName = bn.getWrpRemoteName();
	wrpRemoteName     = bn.getFullWrpRemoteName();
	wrpHomeBaseName   = bn.getWrpHomeName();
	wrpHomeName       = bn.getFullWrpHomeName();
	wrpHandleBaseName = bn.getWrpHandleName();
	wrpHandleName     = bn.getFullWrpHandleName();
	wrpBeanBaseName   = bn.getDerivedBeanName();
	wrpBeanName       = bn.getFullDerivedBeanName();

	// Files Names building
	BeanNaming.getPackageName(ejbRemoteName);
	if (directoryOutputName.equals("")) {
	    wrpRemoteFileName = new String(wrpRemoteBaseName + ".java");
	    wrpHomeFileName   = new String(wrpHomeBaseName + ".java");
	    wrpHandleFileName = new String(wrpHandleBaseName + ".java");
	    wrpBeanFileName   = new String(wrpBeanBaseName + ".java");
	} else {
	    // FileName = directoryOutputName + '/' + packageName + '/' + wrpXxBaseName + ".java"
	    String sDir;
	    sDir = BeanNaming.getPackageName(wrpRemoteName);
	    if (! sDir.equals("")) {
		sDir = sDir.replace('.', File.separatorChar);
		sDir = sDir + File.separatorChar;
	    }
	    wrpRemoteFileName = new String(directoryOutputName + File.separatorChar + sDir +
					   wrpRemoteBaseName + ".java");
	    sDir = BeanNaming.getPackageName(wrpHomeName);
	    if (! sDir.equals("")) {
		sDir = sDir.replace('.', File.separatorChar);
		sDir = sDir + File.separatorChar;
	    }
	    wrpHomeFileName   = new String(directoryOutputName + File.separatorChar + sDir +
					   wrpHomeBaseName + ".java");
	    sDir = BeanNaming.getPackageName(wrpHandleName);
	    if (! sDir.equals("")) {
		sDir = sDir.replace('.', File.separatorChar);
		sDir = sDir + File.separatorChar;
	    }
	    wrpHandleFileName   = new String(directoryOutputName + File.separatorChar + sDir +
					   wrpHandleBaseName + ".java");
	    sDir = BeanNaming.getPackageName(wrpBeanName);
	    if (! sDir.equals("")) {
		sDir = sDir.replace('.', File.separatorChar);
		sDir = sDir + File.separatorChar;
	    }
	    wrpBeanFileName   = new String(directoryOutputName + File.separatorChar + sDir +
					   wrpBeanBaseName + ".java");
	}

	// Implementation Remote and Home classes
	if (beanDesc instanceof SessionDesc) {
	    // Session
	    srcICHome   = new GenICSessionHome((SessionDesc)beanDesc, wrpHomeFileName);
	    srcICRemote = new GenICSessionRemote((SessionDesc)beanDesc, wrpRemoteFileName);
	} else {
	    // Entity
	    srcICHandle = new GenICEntityHandle((EntityDesc)beanDesc, wrpHandleFileName);
	    srcICHome   = new GenICEntityHome((EntityDesc)beanDesc, wrpHomeFileName);
	    srcICRemote = new GenICEntityRemote((EntityDesc)beanDesc, wrpRemoteFileName);
	    if (beanDesc instanceof EntityJdbcCmpDesc) {
		// Entity Persistence Container Managed
		srcICBean   = new GenICEntityCMbyJDBCBean((EntityJdbcCmpDesc)beanDesc,
							  wrpBeanFileName);
	    }
	}
    }

    /**
     * Generates the java source that implements the enterprise Bean's remote interface,
     * (EJB Object class).
     * @param     withError to generate the java source with compilation errors
     *                      (Useful for test only!).
     * @exception GenICException In error case
     */
    public void genImplRemoteClass(boolean withError) throws GenICException {

	fileNamesToDelete.addElement(wrpRemoteFileName);

	srcICRemote.generate(withError);

	if (verbose) {
	    System.out.println("GenIC: The Implementation Remote Class is successfully generated in " +
			       wrpRemoteFileName + " file.");
	}
    }

    /**
     * Generates the java source that implements the enterprise Bean's home interface,
     * (EJB Home class).
     * @param     withError to generate the java source with compilation errors
     *                      (Useful for test only!).
     * @exception GenICException In error case
     */
    public void genImplHomeClass(boolean withError) throws GenICException {

	fileNamesToDelete.addElement(wrpHomeFileName);

	srcICHome.generate(withError);

	if (verbose) {
	    System.out.println("GenIC: The Implementation Home Class is successfully generated in " +
			       wrpHomeFileName + " file.");
	}
    }

    /**
     * Generates the java source that implements the Handle class of the bean,
     * @param     withError to generate the java source with compilation errors
     *                      (Useful for test only!).
     * @exception GenICException In error case
     */
    public void genImplHandleClass(boolean withError) throws GenICException {

	if (srcICHandle != null) {

	    fileNamesToDelete.addElement(wrpHandleFileName);

	    srcICHandle.generate(withError);

	    if (verbose) {
		System.out.println("GenIC: The Implementation Handle Class is successfully generated in " +
				   wrpHandleFileName + " file.");
	    }

	}
    }

    /**
     * Generates the java source of the derived class of the bean,
     * @param     withError to generate the java source with compilation errors
     *                      (Useful for test only!).
     * @exception GenICException In error case
     */
    public void genDerivedBeanClass(boolean withError) throws GenICException {

	if (srcICBean != null) {

	    fileNamesToDelete.addElement(wrpBeanFileName);

	    srcICBean.generate(withError);

	    if (verbose) {
		System.out.println("GenIC: The Derived Class of the Bean is successfully generated in " +
				   wrpBeanFileName + " file.");
	    }

	}
    }

    /**
     * Compiles the java sources EJB Objet class and EJB Home class.
     *
     * I.e. :
     * <ul>
     * <li>
     *   compile the classes via javac tool,
     * <li>
     *   creates the RMI stubs and skeletons via rmic tool,
     * <li>
     *   modify the RMI stubs and skeletons in case the propagation
     *   of the transactionnal context is implicite, and
     *   recompile the RMI skubs and skeletons via the javac tool.
     * </ul>
     * Nota Bene:
     * The EJB Objet and EJB Home classes must have been previously generated.
     *
     * @param     nameJavaC      name the javac tool to use
     * @param     optionsJavaC   options for the javac tool
     * @param     optionsRmiC    options for the rmic tool
     * @exception GenICException In error case
     */
    public void compilImplClasses(String nameJavaC,
				  String optionsJavaC,
				  String optionsRmiC,
				  String xtraClassPath)
	throws GenICException {

	String optDirOutput;
	String sCmd;
	String sRmic;
	Cmd cmd;

	if (directoryOutputName.length() == 0) {
	    optDirOutput = new String("-d .");
	} else {
	    optDirOutput = new String("-d " + "\"" + directoryOutputName + "\"");
	}
	sCmd = nameJavaC + " " + optDirOutput + " " + optionsJavaC + " "
	    + "\"" + wrpRemoteFileName + "\"" + " " + "\"" + wrpHomeFileName + "\"";
	if (srcICHandle != null) {
	    sCmd = sCmd + " " + wrpHandleFileName;
	}
	if (srcICBean != null) {
	    sCmd = sCmd + " " + wrpBeanFileName;
	}
	cmd = new Cmd(sCmd);
	if (verbose) {
	    System.out.println("GenIC: Running '" + sCmd + "'");
	}
	if (cmd.run()) {
	    if (verbose) {
		System.out.println("GenIC: The Implementation Remote and Home Classes are " +
				   "successfully compiled via java compiler.");
	    }
	} else {
	    throw new GenICException("Failed when compiling the implementation classes via java compiler");
	}

	if (directoryOutputName.length() == 0) {
	    optDirOutput = new String("");
	} else {
	    optDirOutput = new String("-d " + "\"" + directoryOutputName + "\"");
	}

	if (Env.isJeremie()) {
	    String jrmicClassName = "org.objectweb.jeremie.tools.jrmic.JRMICompiler";
	    try {
		Class jrmicClass = Class.forName(jrmicClassName);
	    } catch (ClassNotFoundException e) {
		throw new
		    GenICException("Failed when compiling the implementation classes: "+
				   "Jeremie stub compiler not found");
	    }
	    sRmic = "java " + jrmicClassName + " -opt ";
	    sCmd = new String(sRmic);
	} else {
	    sRmic = "rmic -v1.1";
	    sCmd = new String(sRmic);
	    sCmd = sCmd.concat(" -keepgenerated ");
	}

	sCmd = sCmd.concat(optDirOutput + " " + optionsRmiC +
			   " " + wrpRemoteName + " " + wrpHomeName);
	cmd = new Cmd(sCmd);
	if (verbose) {
	    System.out.println( "GenIC: Running '" + sCmd + "'");
	}
	if (cmd.run()) {
	    if (verbose) {
		System.out.println("GenIC: The Implementation Remote and Home Classes are " +
				   "successfully compiled via "+sRmic+".");
	    }
	} else {
	    throw new GenICException("Failed when compiling the implementation classes via '"+sRmic+"'");
	}
	if (Env.isJeremie()== false) {
	    String s;
	    String [] namesSkelStub = new String[4];
	    int lgSuffixe = (new String(".java")).length();
	    s = wrpRemoteFileName.substring(0, wrpRemoteFileName.length()-lgSuffixe);
	    namesSkelStub[0] = new String(s + "_Skel.java");
	    namesSkelStub[1] = new String(s + "_Stub.java");
	    s = wrpHomeFileName.substring(0, wrpHomeFileName.length()-lgSuffixe);
	    namesSkelStub[2] = new String(s + "_Skel.java");
	    namesSkelStub[3] = new String(s + "_Stub.java");
	    for (int i=0; i<namesSkelStub.length; i++) {
		fileNamesToDelete.addElement(namesSkelStub[i]);
	    }

	    for (int i=0; i<namesSkelStub.length; i++) {
		if (verbose) {
		    System.out.println("GenIC: Modifying the '" + namesSkelStub[i] + "' RMI file");
		}
		modifySkelStubRMI(namesSkelStub[i]);
	    }

	    if (directoryOutputName.length() == 0) {
		optDirOutput = new String("");
	    } else {
		optDirOutput = new String("-d " + "\"" + directoryOutputName + "\"");
	    }
	    // Add -nowarn to take off the 'deprecated' messages due to rmic -v1.1
	    sCmd = nameJavaC + " " + optDirOutput + " " + optionsJavaC + " -nowarn";
	    for (int i=0; i<namesSkelStub.length; i++) {
	    sCmd = sCmd.concat(" " + "\"" +namesSkelStub[i] + "\"");
	    }
	    if (verbose) {
		System.out.println("GenIC: Running '" + sCmd + "'");
	    }
	    cmd = new Cmd(sCmd);
	    if (cmd.run()) {
		if (verbose) {
		    System.out.println("GenIC: The RMI Skel. and Stub. Classes are " +
				       "successfully compiled.");
		}
	    } else {
		throw new GenICException("Failed when compiling the RMI Skel. and Stub. classes via 'javac'");
	    }
	}
    }

    /*
     * Modify the Skel or Stub RMI for the implicite propagation of contexts.
     * The modification is different depending on we need to propagate the security 
     * context or not.
     * The modifications to do are Operating System dependent.
     */
    private void modifySkelStubRMI(String fileName) throws GenICException {

	int javaVersion = Env.getJavaVersion();

	String fileSaveName = new String(fileName + ".save");
	fileNamesToDelete.addElement(fileSaveName);
	boolean isSkel = fileName.endsWith("_Skel.java");
	// Rename the original skel or stub file
	try {
	    File f = new File(fileName);
            File saveFile = new File(fileSaveName);
            if (saveFile.exists()) {
                saveFile.delete();
            }
	    f.renameTo(saveFile);
	} catch (Exception e) {
	    throw new GenICException("Failed when renaming a RMI Skel or Stub ("+e+")");
	}
	// Read and Modify the skel or stub file
	// The modifications of the RMI Skels and Stubs are differents
	// on the JDK 1.1.6 and on the others JDK !!!
	BufferedReader  fIn;
	BufferedWriter fOut;
	try {
	    fIn = new BufferedReader(new InputStreamReader(new FileInputStream(fileSaveName)));
	    fOut = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName)));
	} catch (Exception e) {
	    throw new GenICException("Failed when reading or writting a RMI Skel or Stub ("+e+")");
	}

	String skeletonName = new String("Skeleton");
	String stubName = new String("RemoteStub");
	skeletonName = withSecPropag ? "Security"+skeletonName : skeletonName;
	stubName = withSecPropag ? "Security"+stubName : stubName;
	try {
	    String line;
	    if (javaVersion == Env.JAVA_1_1_6) {
		line = fIn.readLine();
		while (line != null)  {
		    if (isSkel) {
			// Modify a Skel RMI file
			line = (new JString(line)).replace
			    ("extends java.lang.Object",
			     "extends org.objectweb.jonas.rmifilters."+skeletonName,
			     false);
			line = (new JString(line)).replace
			    ("call.releaseInputStream()",
			     "this.inRequest(call)",
			     false);
			line = (new JString(line)).replace
			    ("call.getResultStream(true)",
			     "this.outReply(call)",
			     false);
		    } else {
			// Modify a Stub RMI file
			line = (new JString(line)).replace
			    ("java.rmi.server.RemoteStub",
			     "org.objectweb.jonas.rmifilters."+stubName);
			line = (new JString(line)).replace
			    ("sub.invoke",
			     "this.invoke");
		    }
		    fOut.write(line, 0, line.length());
		    fOut.newLine();
		    line = fIn.readLine();
		}
	    } else {
		line = fIn.readLine();
		while (line != null)  {
		    if (isSkel) {
			// Modify a Skel RMI file
			line = (new JString(line)).replace
			    ("implements",
			     "extends org.objectweb.jonas.rmifilters."+skeletonName+" implements",
			     false);
			line = (new JString(line)).replace
			    ("call.releaseInputStream()",
			     "this.inRequest(call)",
			     false);
			line = (new JString(line)).replace
			    ("call.getResultStream(true)",
			     "this.outReply(call)",
			     false);
		    } else {
			// Modify a Stub RMI file
			line = (new JString(line)).replace
			    ("java.rmi.server.RemoteStub",
			     "org.objectweb.jonas.rmifilters."+stubName);
			line = (new JString(line)).replace
			    ("ref.invoke",
			     "this.invoke");
		    }
		    fOut.write(line, 0, line.length());
		    fOut.newLine();
		    line = fIn.readLine();
		}
	    }
	    fIn.close();
	    fOut.close();
	} catch (Exception e) {
	    throw new GenICException("Failed when reading or writting a RMI Skel. or Stub. ("+
				     e+")");
	}
    }

    /**
     * Clean the intermediate generated source files.
     */
    public void clean() {
	File f;
	if (verbose) {
	    System.out.println("GenIC: Deleting " + fileNamesToDelete.toString());
	}
	for (int i=0; i < fileNamesToDelete.size(); i++) {
	    f = new File((String)fileNamesToDelete.elementAt(i));
	    f.delete();
	}
    }

    /**
     * GenIC allows to generate the classes that implement
     * the EJB Home and the EJB remote interfaces.
     * <p>
     *
     * Usage: java org.objectweb.jonas_ejb.tools.GenIC -help
     * <br>
     *         to print this help message
     * <p>
     *
     * or    java org.objectweb.jonas_ejb.tools.GenIC <Options> <Input_File>
     * <br>
     *         to generate the classes that implement
     * <ul>
     * <li>
     *           - the EJB home interface, and
     * <li>
     *           - the EJB remote interface,
     * </ul>
     *         for a given EJB.
     * <p>
     *           Options include:
     * <ul>
     * <li>
     *             -d <output_dir>  specify where to place the generated files
     * <li>
     *             -keepgenerated   do not delete intermediate generated source files
     * <li>
     *             -nocompil        do not compile the generated source files via
     *                              the java and rmi compilers       
     * <li>
     *             -javac     <opt> specify the name of the java compiler to use
     * <li>
     *             -javacopts <opt> specify the options to pass to the java compiler
     * <li>
     *             -rmicopts <opt>  specify the options to pass to the rmi compiler
     * <li>
     *             -verbose
     * <li>
     *             -secpropag       modify the RMI Skel. and Stub. to implement
     *                              the implicit propagation of the transactionnal
     *                              context and security context
     * </ul>
     * <p>
     *           Input_File         file name of the standard deployment descriptor
     *                              (.xml ended), or
     *                              file name of the EJB-jar (.jar ended).
     */

    public static void main(String args[]) {

	boolean  error = false;

	boolean  isHelp          = false;
	boolean  isVerbose       = false;
	boolean  isKeepGenerated = false;
	boolean  isSecPropag    = false;
	boolean  isCompil        = true;
	boolean  isWithError     = false;
	String   fileInputName = null;
	String   dirOutputName = null;
	String   nameJavaC     = new String("javac");
	String   optionsJavaC  = new String("");
	String   optionsRmiC   = new String("");

	// Get args
	for (int argn=0; argn<args.length; argn++) {
	    String arg = args[argn];
	    if (arg.equals("-help") || arg.equals("-?")) {
		isHelp = true;
		continue;
	    }
	    if (arg.equals("-verbose")) {
		isVerbose = true;
		continue;
	    }
	    if (arg.equals("-keepgenerated")) {
		isKeepGenerated = true;
		optionsRmiC = optionsRmiC + " " + args[argn];
		continue;
	    }
	    if (arg.equals("-secpropag")) {
		isSecPropag = true; 
		continue;
	    }
	    if (arg.equals("-nocompil")) {
		isCompil = false;
		isKeepGenerated = true;
		continue;
	    }
	    if (arg.equals("-witherror")) {
		// hidden option for test only !!!
		// Generation of classes with errors to get compilation errors
		isWithError = true;
		continue;
	    }
	    if (arg.equals("-javac")) {
		argn++;
		if (argn<args.length) {
		    nameJavaC = args[argn];
		    if (Env.isJeremie()) {
			optionsRmiC = optionsRmiC + " -c " +  args[argn];
		    }
		} else {
		    error = true;
		}
		continue;
	    }
	    if (arg.equals("-javacopts")) {
		argn++;
		if (argn<args.length) {
		    optionsJavaC = optionsJavaC + " " + args[argn];
		} else {
		    error = true;
		}
		continue;
	    }
	    if (arg.equals("-rmicopts")) {
		argn++;
		if (argn<args.length) {
		    optionsRmiC = optionsRmiC + " " + args[argn];
		} else {
		    error = true;
		}
		continue;
	    }
	    if (arg.equals("-d")) {
		argn++;
		if (argn<args.length) {
		    dirOutputName = args[argn];
		} else {
		    error = true;
		}
		continue;
	    }
	    fileInputName = args[argn];
	}

	// Usage ?
	if (isHelp) {
	    usage();
	    System.exit(0);
	}

	// Check args
	if (error || (fileInputName == null)) {
	    usage();
	    System.exit(2);
	}
	if (dirOutputName == null) {
	    dirOutputName = new String("");
	}

	String classpath;
	if (fileInputName.endsWith(".jar")) {
	    classpath = fileInputName +
		System.getProperty("path.separator", "") +
		System.getProperty("java.class.path", "");
	} else {
	    classpath = System.getProperty("java.class.path", "");
	}
	optionsJavaC = optionsJavaC.concat(" -classpath \""+classpath+"\" ");
	optionsRmiC = optionsRmiC.concat(" -classpath \""+classpath+"\" ");

	// For each Bean, generates the EJB Home and the EJB Object classes
	try {
	    DeploymentDesc ejbJarDD = null;
	    if (fileInputName.endsWith(".jar")) {
		// ejb-jar file
		MultiClassLoader loader = new MultiClassLoader(
                ClassLoader.getSystemClassLoader(), null);
		loader.addClassPath(fileInputName);
		ejbJarDD = DeploymentDesc.getInstance(loader);
	    } else {
		// xml file
		ejbJarDD = DeploymentDesc.getInstance(fileInputName,
						      BeanNaming.getJonasXmlName(fileInputName));
	    }
	    BeanDesc[] beansDD = ejbJarDD.getBeanDesc();
	    for (int i=0; i<beansDD.length; i++) {
		GenIC gwc = new GenIC(beansDD[i], dirOutputName, isSecPropag, isVerbose);
		gwc.genImplRemoteClass(isWithError);
		gwc.genImplHomeClass(isWithError);
		gwc.genImplHandleClass(isWithError);
		gwc.genDerivedBeanClass(isWithError);
		if (isCompil) {
		    String xtraClassPath = null;
		    if (fileInputName.endsWith(".jar")) {
			xtraClassPath = fileInputName;
		    }
		    gwc.compilImplClasses(nameJavaC, optionsJavaC, optionsRmiC, xtraClassPath);
		}
		if (!isKeepGenerated) {
		    gwc.clean();
		}
		gwc = null;	// parano
	    }
	} catch (GenICException e) {
	    error = true;
	    System.err.println("GenIC ERROR: " + e.getMessage());
	} catch (DeploymentDescException e) {
	    error = true;
	    System.err.println("GenIC ERROR: When reading the Deployment Descriptors for "+fileInputName);	    
	    System.err.println(e.getMessage());
	}
	if (error) {
	    System.exit(2);
	}

	// End
    }

    private static void usage() {
	System.out.println("");
	System.out.println("Usage: java org.objectweb.jonas_ejb.tools.GenIC -help");
	System.out.println("         to print this help message");
	System.out.println("");
	System.out.println("");
	System.out.println(" or    java org.objectweb.jonas_ejb.tools.GenIC <Options> <Input_File>");
	System.out.println("");
	System.out.println("         to generate the container-specific classes for given EJB(s).");
	System.out.println("");
	System.out.println("           Options include:");
        System.out.println("             -d <output_dir>  specify where to place the generated files");
	System.out.println("             -keepgenerated   do not delete intermediate generated source files");
	System.out.println("             -nocompil        do not compile the generated source files via");
	System.out.println("                              the java and rmi compilers");
	System.out.println("             -javac     <opt> specify the java compiler to use");
	System.out.println("             -javacopts <opt> specify the options to pass to the java compiler");
	System.out.println("             -rmicopts <opt>  specify the options to pass to the rmi compiler");
	System.out.println("             -verbose");
	System.out.println("             -secpropag       modify the RMI Skel. and Stub. to implement");
	System.out.println("                              the implicit propagation of the transactionnal");
	System.out.println("                              context and security context");
	System.out.println("");
	System.out.println("           Input_File         standard deployment descriptor file's name or");
	System.out.println("                              ejb-jar file's name");
	System.out.println("");
    }
}


