0001: /**
0002: * JOnAS: Java(TM) Open Application Server
0003: * Copyright (C) 1999-2005 Bull S.A.
0004: * Contact: jonas-team@objectweb.org
0005: *
0006: * This library is free software; you can redistribute it and/or
0007: * modify it under the terms of the GNU Lesser General Public
0008: * License as published by the Free Software Foundation; either
0009: * version 2.1 of the License, or any later version.
0010: *
0011: * This library is distributed in the hope that it will be useful,
0012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0014: * Lesser General Public License for more details.
0015: *
0016: * You should have received a copy of the GNU Lesser General Public
0017: * License along with this library; if not, write to the Free Software
0018: * USA
0019: *
0020: * --------------------------------------------------------------------------
0021: * $Id: GenIC.java 9721 2006-10-11 11:37:32Z benoitf $
0022: * --------------------------------------------------------------------------
0023: */package org.objectweb.jonas_ejb.genic;
0024:
0025: import java.io.File;
0026: import java.io.FileInputStream;
0027: import java.io.FileOutputStream;
0028: import java.io.IOException;
0029: import java.io.InputStream;
0030: import java.io.OutputStream;
0031: import java.io.PrintStream;
0032: import java.lang.reflect.InvocationTargetException;
0033: import java.lang.reflect.Method;
0034: import java.net.MalformedURLException;
0035: import java.net.URL;
0036: import java.util.ArrayList;
0037: import java.util.Enumeration;
0038: import java.util.Iterator;
0039: import java.util.List;
0040: import java.util.Properties;
0041: import java.util.StringTokenizer;
0042: import java.util.jar.Attributes;
0043: import java.util.jar.JarEntry;
0044: import java.util.jar.JarFile;
0045: import java.util.jar.JarOutputStream;
0046: import java.util.jar.Manifest;
0047:
0048: import org.apache.velocity.app.VelocityEngine;
0049: import org.apache.velocity.runtime.RuntimeConstants;
0050: import org.objectweb.common.Cmd;
0051: import org.objectweb.common.Env;
0052: import org.objectweb.jonas.common.Log;
0053: import org.objectweb.jonas.container.Protocols;
0054: import org.objectweb.jonas.server.JClassLoader;
0055: import org.objectweb.jonas_ejb.deployment.api.BeanDesc;
0056: import org.objectweb.jonas_ejb.deployment.api.DeploymentDesc;
0057: import org.objectweb.jonas_ejb.deployment.api.DeploymentDescEjb2;
0058: import org.objectweb.jonas_ejb.deployment.api.EntityCmp2Desc;
0059: import org.objectweb.jonas_ejb.deployment.api.MessageDrivenDesc;
0060: import org.objectweb.jonas_ejb.deployment.lib.EjbDeploymentDescManager;
0061: import org.objectweb.jonas_ejb.lib.BeanNaming;
0062: import org.objectweb.jonas_lib.deployment.api.DeploymentDescException;
0063: import org.objectweb.jonas_lib.files.FileUtils;
0064: import org.objectweb.jonas_lib.files.FileUtilsException;
0065: import org.objectweb.jonas_lib.version.Version;
0066: import org.objectweb.jorm.api.PException;
0067: import org.objectweb.jorm.compiler.api.JormCompilerConfigurator;
0068: import org.objectweb.jorm.compiler.lib.JormCompiler;
0069: import org.objectweb.jorm.metainfo.api.Manager;
0070: import org.objectweb.medor.api.MedorException;
0071: import org.objectweb.util.monolog.api.BasicLevel;
0072: import org.objectweb.util.monolog.api.Logger;
0073: import org.objectweb.util.monolog.wrapper.velocity.VelocityLogger;
0074:
0075: /**
0076: * This class allows to generate:
0077: * <ul>
0078: * <li>the classes that implements the Enterprise bean's remote interface,
0079: * <li>the classes that implements the Enterprise bean's home interface,
0080: * <li>the classes that implements the Handles of the Entity beans,
0081: * <li>the classes that implements the persistence of the Entity beans with
0082: * CMP,
0083: * </ul>
0084: * of all the Enterprise Java Beans defined in the given Deployment Descriptor.
0085: *
0086: * @author Helene Joanin : Initial developer
0087: * @author Christophe Ney (Lutris Technologies) : Fix to handle arguments containing white spaces.
0088: * @author Guillaume Riviere : Fix the addClassesInJar() method (on David, the Stub/Skel classes names are different).
0089: * @author Dean Jennings : Remove System Exit (called now from server)
0090: * @author Sami Lehtinen : use of java.util.jar api instead of jar command
0091: */
0092: public class GenIC {
0093:
0094: /**
0095: * install.root property name
0096: */
0097: private static final String INSTALL_ROOT_PROPERTY = "install.root";
0098:
0099: /**
0100: * java.home property value (ended with '/')
0101: */
0102: private static String javaHomeBin = null;
0103:
0104: /**
0105: * Is the command is verbose ?
0106: */
0107: private boolean verbose = false;
0108:
0109: /**
0110: * Name of the directory where to place the generated file
0111: */
0112: private String outputdir = null;
0113:
0114: /**
0115: * Are some container classes generated ?
0116: */
0117: private boolean generatedIC;
0118:
0119: /**
0120: * Path names of the generated files to delete
0121: */
0122: private ArrayList filesToDelete = null;
0123:
0124: /**
0125: * Path names of the java generated sources (remote)
0126: */
0127: private ArrayList remoteJavas = null;
0128:
0129: /**
0130: * Path names of the java generated sources (no remote)
0131: */
0132: private ArrayList noRemoteJavas = null;
0133:
0134: /**
0135: * Names of the remote classes (package name included)
0136: */
0137: private ArrayList remoteClasses = null;
0138:
0139: /**
0140: * GenIC Parameters
0141: */
0142: private GenICParameters gp = null;
0143:
0144: /**
0145: * Logger used by GenIC
0146: */
0147: private static Logger logger = null;
0148:
0149: /**
0150: * Buffer size
0151: */
0152: private static final int BUFFER_SIZE = 1024;
0153:
0154: /** META dir */
0155: private static final String META_DIR = "META-INF";
0156:
0157: /** The jar entry for the MANIFEST file */
0158: private static final String MANIFEST_JAR_ENTRY = META_DIR
0159: + "/MANIFEST.MF";
0160:
0161: /** The path to the MANIFEST file */
0162: private static final String MANIFEST_PATH = META_DIR
0163: + File.separator + "MANIFEST.MF";
0164:
0165: /**
0166: * GenIC allows to generate the container classes for JOnAS for the given
0167: * Enterprise Java Beans.
0168: * <p>
0169: * Usage: java org.objectweb.jonas_ejb.genic.GenIC -help <br>
0170: * to print this help message
0171: * <p>
0172: * or java org.objectweb.jonas_ejb.genic.GenIC <Options><Input_File><br>
0173: * to generate the container classes for the given EJBs.
0174: * <p>
0175: * Options include:
0176: * <ul>
0177: * <li>-d <output_dir>specify where to place the generated files</li>
0178: * <li>-noaddinjar do not add the generated classes in the given ejb-jar
0179: * file</li>
0180: * <li>-classpath <path> define the classpath to be used to compile classes</li>
0181: * <li>-nocompil do not compile the generated source files via the java and
0182: * rmi compilers</li>
0183: * <li>-novalidation parse the XML deployment descriptors without
0184: * validation</li>
0185: * <li>-javac <opt>specify the name of the java compiler to use</li>
0186: * <li>-javacopts <opt>specify the options to pass to the java compiler
0187: * </li>
0188: * <li>-rmicopts <opt>specify the options to pass to the rmi compiler</li>
0189: * <li>-protocols list of protocol, separated by comma</li>
0190: * <li>-keepgenerated do not delete intermediate generated source files
0191: * </li>
0192: * <li>-verbose</li>
0193: * <li>-invokecmd invoke, in some case, directly the method of the java
0194: * class corresponding to the command</li>
0195: * </ul>
0196: * <p>
0197: * Input_File file name of the standard deployment descriptor (.xml ended),
0198: * or file name of the EJB-jar (.jar ended).
0199: * @param args arguments for GenIC
0200: */
0201: public static void main(String[] args) {
0202: boolean error = false;
0203:
0204: // don't use the fastrmic compiler by default
0205: //boolean nofastrmic = false;
0206:
0207: String protocolNames = Protocols.RMI_JRMP; // Default to jrmp
0208:
0209: // Holder for GenIC params
0210: GenICParameters gp = new GenICParameters();
0211:
0212: // Init logger
0213: Log.configure("trace");
0214: logger = Log.getLogger(Log.JONAS_GENIC_PREFIX);
0215:
0216: // If no arg at all: print help message.
0217: if (args.length == 0) {
0218: usage();
0219: return;
0220: }
0221: // Get args
0222: for (int argn = 0; argn < args.length; argn++) {
0223: String arg = args[argn];
0224: if (arg.equals("-help") || arg.equals("-?")) {
0225: gp.setHelp(true);
0226: continue;
0227: }
0228: if (arg.equals("-verbose")) {
0229: gp.setVerbose(true);
0230: continue;
0231: }
0232: if (arg.equals("-debug")) {
0233: // deprecated
0234: continue;
0235: }
0236: if (arg.equals("-mappernames")) {
0237: argn++;
0238: // deprecated
0239: warning("The -mappernames option is ignored (deprecated)");
0240: }
0241: if (arg.equals("-protocols")) {
0242: argn++;
0243: if (argn < args.length) {
0244: protocolNames = args[argn];
0245: continue;
0246: } else {
0247: error = true;
0248: }
0249: }
0250: if (arg.equals("-keepgenerated")) {
0251: gp.setKeepGenerated(true);
0252: gp.getRmicOptions().add(args[argn]);
0253: continue;
0254: }
0255: if (arg.equals("-nocompil")) {
0256: gp.setCompil(false);
0257: gp.setKeepGenerated(true);
0258: continue;
0259: }
0260: if (arg.equals("-noaddinjar")) {
0261: gp.setAddInJar(false);
0262: continue;
0263: }
0264: if (arg.equals("-novalidation")) {
0265: gp.setParseWithValidation(false);
0266: continue;
0267: }
0268: if (arg.equals("-classpath")) {
0269: gp.setClasspathParam(args[++argn]);
0270: continue;
0271: }
0272: if (arg.equals("-javac")) {
0273: argn++;
0274: if (argn < args.length) {
0275: gp.setJavacName(args[argn]);
0276: } else {
0277: error = true;
0278: }
0279: continue;
0280: }
0281: if (arg.equals("-javacopts")) {
0282: argn++;
0283: if (argn < args.length) {
0284: StringTokenizer st = new StringTokenizer(args[argn]);
0285: while (st.hasMoreTokens()) {
0286: gp.getJavacOptions().add(st.nextToken());
0287: }
0288: } else {
0289: error = true;
0290: }
0291: continue;
0292: }
0293: if (arg.equals("-rmicopts")) {
0294: argn++;
0295: if (argn < args.length) {
0296: StringTokenizer st = new StringTokenizer(args[argn]);
0297: while (st.hasMoreTokens()) {
0298: gp.getRmicOptions().add(st.nextToken());
0299: }
0300: } else {
0301: error = true;
0302: }
0303: continue;
0304: }
0305: if (arg.equals("-d")) {
0306: argn++;
0307: if (argn < args.length) {
0308: gp.setOutputDirectory(args[argn]);
0309: } else {
0310: error = true;
0311: }
0312: continue;
0313: }
0314: if (arg.equals("-invokecmd")) {
0315: gp.setInvokeCmd(true);
0316: continue;
0317: }
0318: if (arg.equals("-fastrmic")) {
0319: argn++;
0320: // deprecated
0321: warning("The -fastrmic option is ignored as it is the default value. Use -nofastrmic to disable it.");
0322: continue;
0323: }
0324:
0325: if (arg.equals("-nofastrmic")) {
0326: argn++;
0327: gp.setFastRmicEnabled(false);
0328: continue;
0329: }
0330:
0331: gp.setInputFilename(args[argn]);
0332: }
0333:
0334: // Usage ?
0335: if (gp.isHelp()) {
0336: usage();
0337: return;
0338: }
0339:
0340: // Check args
0341: if (error || (gp.getInputFilename() == null)) {
0342: usage();
0343: throw new RuntimeException();
0344: }
0345: // The -d option is deprecated since JOnAS 3.0.7 when the file input is an ejb-jar
0346: // Instead, the output directory must be a temporary directory to make easier
0347: // the ejb-jar updated.
0348: if ((gp.getOutputDirectory() != null) && gp.isAddInJar()
0349: && gp.getInputFilename().endsWith(".jar")) {
0350: warning("The -d '" + gp.getOutputDirectory()
0351: + "' option is ignored"
0352: + " (deprecated with an ejb-jar as input file)");
0353: }
0354:
0355: if (gp.getOutputDirectory() == null) {
0356: gp.setOutputDirectory("");
0357: }
0358:
0359: // Build the array of protocols name
0360: gp.setProtocols(new Protocols(protocolNames, true));
0361:
0362: // In case of ejb-jar file, the dirOutputName must be initialized with a
0363: // tempo. directory.
0364: if (gp.getInputFilename().endsWith(".jar") && gp.isAddInJar()) {
0365: try {
0366: gp.setOutputDirectory(GenIC.createTempDir());
0367: } catch (IOException ioe) {
0368: GenIC.fatalError(ioe);
0369: }
0370: }
0371:
0372: // Init the classpath used for javac, rmic, JRMICompiler
0373: JClassLoader pcl = (JClassLoader) Thread.currentThread()
0374: .getContextClassLoader();
0375:
0376: String classpath = pcl.getClassPath();
0377: if (gp.getInputFilename().endsWith(".jar")) {
0378: classpath = gp.getInputFilename() + File.pathSeparator
0379: + classpath;
0380: }
0381: if (!"".equals(gp.getOutputDirectory())) {
0382: classpath = gp.getOutputDirectory() + File.pathSeparator
0383: + classpath;
0384: }
0385: // add -classpath value
0386: if (gp.getClasspathParam() != null) {
0387: classpath = gp.getClasspathParam() + File.pathSeparator
0388: + classpath;
0389: }
0390:
0391: // Set the parsing mode (with or without validation)
0392: if (!gp.isParseWithValidation()) {
0393: EjbDeploymentDescManager.setParsingWithValidation(false);
0394: }
0395:
0396: // Generates the classes for the set of the beans
0397: try {
0398: DeploymentDesc ejbJarDD = null;
0399: if (gp.getInputFilename().endsWith(".jar")) {
0400: // ejb-jar file
0401: URL[] url = new URL[1];
0402: url[0] = (new File(gp.getInputFilename())).toURL();
0403: JClassLoader cl = new JClassLoader("GenIC-"
0404: + gp.getInputFilename(), url, pcl);
0405: if (gp.getClasspathParam() != null) {
0406: // add -classpath value inside ClassLoader
0407: addClasspath(cl, gp.getClasspathParam());
0408: }
0409: ejbJarDD = EjbDeploymentDescManager.getDeploymentDesc(
0410: gp.getInputFilename(), cl);
0411: } else {
0412: // xml file
0413: ejbJarDD = EjbDeploymentDescManager.getDeploymentDesc(
0414: gp.getInputFilename(),
0415: BeanNaming.getJonasXmlName(gp
0416: .getInputFilename()), BeanNaming
0417: .getParentName(gp.getInputFilename()));
0418: }
0419:
0420: GenIC gwc = new GenIC(ejbJarDD, gp);
0421:
0422: // Reset the beans deployment descriptors to unload the beans
0423: // classes
0424: // (loaded from the ejb-jar when creating the
0425: // jonas_ejb.deployment.api.BeanDesc),
0426: // to be able to update the ejb-jar file on Windows.
0427: // See Bug #270
0428: ejbJarDD = null;
0429: System.gc();
0430:
0431: if (gp.isCompil()) {
0432: gwc.compilClasses(classpath);
0433: if (gp.getInputFilename().endsWith(".jar")
0434: && gp.isAddInJar()) {
0435: gwc.addClassesInJar();
0436: }
0437: if (!gp.isKeepGenerated()) {
0438: gwc.clean();
0439: }
0440: }
0441:
0442: // Add into META_INF/MANIFEST jonas information for autogeneration functionnality
0443: if (gp.getInputFilename() != null
0444: && gp.getInputFilename().endsWith(".jar")
0445: && gp.isAddInJar()) {
0446: try {
0447: updateAttributeInManifest(gp.getInputFilename(),
0448: "Genic-Jonas-Version", Version.getNumber());
0449: updateAttributeInManifest(gp.getInputFilename(),
0450: "Genic-Jonas-protocols", gp.getProtocols()
0451: .list());
0452: } catch (FileUtilsException e) {
0453: if (logger.isLoggable(BasicLevel.WARN)) {
0454: logger.log(BasicLevel.WARN,
0455: "Cannot update the Genic attributes (version/protocols) of the application '"
0456: + gp.getInputFilename() + "'.",
0457: e);
0458: }
0459: }
0460: } else if (gp.getOutputDirectory() != null
0461: && !gp.isAddInJar()) {
0462: // case of Genic call by ant task
0463: // noaddinjar = true && -d specified we must add manifest into the directory output
0464: Manifest mf = new Manifest();
0465: Attributes attributes = mf.getMainAttributes();
0466: attributes.putValue("Genic-Jonas-Version", Version
0467: .getNumber());
0468: attributes.putValue("Genic-Jonas-protocols", gp
0469: .getProtocols().list());
0470: createManifest(gp.getOutputDirectory(), mf);
0471: }
0472: } catch (MalformedURLException e) {
0473: GenIC.fatalError("Invalid ejb-jar file name : ", e);
0474: } catch (GenICException e) {
0475: GenIC.fatalError(e);
0476: } catch (DeploymentDescException e) {
0477: GenIC.fatalError(
0478: "Cannot read the Deployment Descriptors from "
0479: + gp.getInputFilename() + ": ", e);
0480: }
0481: // End
0482: }
0483:
0484: /**
0485: * Change the attribute value in a jar file (and update file if required)
0486: * @param jarName : output jar file
0487: * @param attributeName : Name of attribute to update
0488: * @param attributeValue : Value of attribute
0489: * @throws FileUtilsException if update fails (replacing file with the updated file)
0490: */
0491: private static void updateAttributeInManifest(String jarName,
0492: String attributeName, String attributeValue)
0493: throws FileUtilsException {
0494:
0495: // Initialize a flag that will indicate that the jar was updated.
0496: boolean jarUpdated = false;
0497: JarFile jar = null;
0498: File tempJarFile = null;
0499:
0500: File jarFile = new File(jarName);
0501: try {
0502: jar = new JarFile(jarFile);
0503:
0504: // Create a temp jar file with no manifest. (The manifest will
0505: // be copied when the entries are copied.)
0506: tempJarFile = File.createTempFile("filetoadd", ".jar");
0507:
0508: JarOutputStream tempJar = new JarOutputStream(
0509: new FileOutputStream(tempJarFile));
0510:
0511: // Allocate a buffer for reading entry data.
0512:
0513: byte[] buffer = new byte[BUFFER_SIZE];
0514: int bytesRead;
0515:
0516: // Loop through the jar entries and add them to the temp jar,
0517: // skipping the entry that was added to the temp jar already.
0518:
0519: for (Enumeration entries = jar.entries(); entries
0520: .hasMoreElements();) {
0521: // Get the next entry.
0522:
0523: JarEntry entry = (JarEntry) entries.nextElement();
0524: String entryName = entry.getName();
0525: // If the entry has not been added already, add it.
0526: // If the entry is not the META-INF/MANIFEST.MF and it skipManifest is true
0527: if (!entryName.equalsIgnoreCase(MANIFEST_JAR_ENTRY)) {
0528: // Get an input stream for the entry.
0529: InputStream entryStream = jar.getInputStream(entry);
0530: // Read the entry and write it to the temp jar.
0531:
0532: tempJar.putNextEntry(entry);
0533:
0534: while ((bytesRead = entryStream.read(buffer)) != -1) {
0535: tempJar.write(buffer, 0, bytesRead);
0536: }
0537: } else {
0538: File tempManifestFile = File.createTempFile(
0539: "MANIFEST", ".MF");
0540: FileOutputStream fileOutputStream = new FileOutputStream(
0541: tempManifestFile);
0542: InputStream entryStream = jar.getInputStream(entry);
0543:
0544: Manifest mf = new Manifest(entryStream);
0545:
0546: // try to see if attribute name is present
0547: Attributes mainAttributes = mf.getMainAttributes();
0548: String existingValueAttribute = mainAttributes
0549: .getValue(attributeName);
0550:
0551: // No value or previous entry not matching the value
0552: if (attributeValue != null
0553: && !attributeValue
0554: .equals(existingValueAttribute)) {
0555: // set the value
0556: mainAttributes.putValue(attributeName,
0557: attributeValue);
0558:
0559: // Jar is updated
0560: jarUpdated = true;
0561: }
0562:
0563: // Write new Manifest
0564: mf.write(fileOutputStream);
0565: fileOutputStream.close();
0566:
0567: // Add the new MANIFEST
0568: FileInputStream fileInputManifest = new FileInputStream(
0569: tempManifestFile);
0570: try {
0571: // Create a jar entry and add it to the temp jar.
0572: JarEntry newEntry = new JarEntry(
0573: MANIFEST_JAR_ENTRY);
0574: tempJar.putNextEntry(newEntry);
0575:
0576: // Read the file and write it to the jar.
0577:
0578: while ((bytesRead = fileInputManifest
0579: .read(buffer)) != -1) {
0580: tempJar.write(buffer, 0, bytesRead);
0581: }
0582: } catch (Exception ex) {
0583: logger.log(BasicLevel.WARN,
0584: "Can't update manifest", ex);
0585: } finally {
0586: fileInputManifest.close();
0587: tempManifestFile.delete();
0588: }
0589: }
0590: }
0591: jar.close();
0592: tempJar.close();
0593: } catch (Exception ex) {
0594: logger.log(BasicLevel.ERROR, ex);
0595: }
0596:
0597: // Attribute has changed, need to update the file (with the updated copy)
0598: if (jarUpdated) {
0599: FileUtils.copyFile(tempJarFile, jarFile);
0600: }
0601:
0602: // delete temp file
0603: tempJarFile.delete();
0604: }
0605:
0606: /**
0607: * Create Manifest file with name/value
0608: * @param dirOutputName : output file
0609: * @param manifest : The manifest file to write
0610: * @return false if problem during file creation
0611: */
0612: private static boolean createManifest(String dirOutputName,
0613: Manifest manifest) {
0614:
0615: // Ensure that there is the MANIFEST_VERSION
0616: Attributes mainAttributes = manifest.getMainAttributes();
0617: mainAttributes.putValue("Manifest-Version", "1.0");
0618:
0619: try {
0620: File fileOutput = new File(dirOutputName + File.separator
0621: + META_DIR);
0622:
0623: if (!fileOutput.exists()) {
0624: fileOutput.mkdirs();
0625: }
0626: if (!fileOutput.exists()) {
0627: GenIC
0628: .warning("Can't create META-INF directory into temp dir : "
0629: + dirOutputName + "/META-INF");
0630: return false;
0631: }
0632:
0633: fileOutput = new File(dirOutputName + File.separator
0634: + MANIFEST_PATH);
0635: if (!fileOutput.exists()) {
0636: fileOutput.createNewFile();
0637: }
0638: if (!fileOutput.exists()) {
0639: GenIC.warning("Can't create manifest.mf file into "
0640: + dirOutputName + File.separator + "META-INF");
0641: return false;
0642: }
0643: OutputStream os = new FileOutputStream(fileOutput);
0644: manifest.write(os);
0645: os.close();
0646: return true;
0647: } catch (Exception e) {
0648: GenIC
0649: .warning("Problem during creation of META-INF/manifest.mf file into tempdir : "
0650: + e.getMessage());
0651: e.printStackTrace();
0652: return false;
0653: }
0654: }
0655:
0656: /**
0657: * Add To the given ClassLoader the given classpath
0658: * @param cl ClassLoader to be updated
0659: * @param classpath the classpath to add inside the ClassLoader
0660: * @throws GenICException When classpath contains invalid URL
0661: */
0662: private static void addClasspath(JClassLoader cl, String classpath)
0663: throws GenICException {
0664: String[] elems = classpath.split(File.pathSeparator);
0665: for (int i = 0; i < elems.length; i++) {
0666: try {
0667: cl.addURL(new File(elems[i]).toURL());
0668: } catch (MalformedURLException e) {
0669: throw new GenICException("Cannot create URL from '"
0670: + elems[i] + "'", e);
0671: }
0672: }
0673: }
0674:
0675: /**
0676: * GenIC Constructor: generates the container classes sources of each beans
0677: * @param ejbJarDesc deployment descriptors of the beans
0678: * @param gp GenIC parameters
0679: * @throws GenICException In error case
0680: */
0681: public GenIC(DeploymentDesc ejbJarDesc, GenICParameters gp)
0682: throws GenICException {
0683:
0684: // A BeanSources for each bean
0685: ArrayList beanList = null;
0686: this .gp = gp;
0687:
0688: verbose = gp.isVerbose();
0689:
0690: if (javaHomeBin == null) {
0691: javaHomeBin = System.getProperty("java.home", "");
0692: if (!("".equals(javaHomeBin))) {
0693: if (Env.isOsMacOsX()) {
0694: javaHomeBin = javaHomeBin + File.separator + "bin"
0695: + File.separator;
0696: } else {
0697: javaHomeBin = javaHomeBin + File.separator + ".."
0698: + File.separator + "bin" + File.separator;
0699: }
0700: }
0701: }
0702: outputdir = gp.getOutputDirectory();
0703: filesToDelete = new ArrayList();
0704: remoteJavas = new ArrayList();
0705: noRemoteJavas = new ArrayList();
0706: remoteClasses = new ArrayList();
0707: beanList = new ArrayList();
0708: BeanDesc[] beansDD = ejbJarDesc.getBeanDesc();
0709: JormCompiler jormCompiler = null;
0710: VelocityEngine ve = allocateVelocityEngine();
0711: // Display the bean's names
0712: StringBuffer message = new StringBuffer();
0713: message.append("GenIC for JOnAS " + Version.getNumber() + ": ");
0714: String sep = "";
0715: for (int i = 0; i < beansDD.length; i++) {
0716:
0717: // If CMI is not supported, the cluster replicated parameter is set to disabled
0718: if (!gp.getProtocols().isSupported("cmi")) {
0719: if (beansDD[i].isClusterReplicated()) {
0720: GenIC
0721: .warning("CMI protocol is not supported -> force 'cluster-replicated' to false for the bean "
0722: + beansDD[i].getEjbName());
0723: beansDD[i].setClusterReplicated(false);
0724: }
0725: }
0726:
0727: BeanSources bs = null;
0728: if ((beansDD[i] instanceof MessageDrivenDesc)) {
0729: //Nothing to generate in case of MessageDriven Bean
0730: continue;
0731: }
0732: if (beansDD[i] instanceof EntityCmp2Desc) {
0733: if (jormCompiler == null) {
0734: // Load the jorm meta information of the class
0735: try {
0736: jormCompiler = allocateJormCompiler(((DeploymentDescEjb2) ejbJarDesc)
0737: .getJormManager());
0738: } catch (DeploymentDescException e) {
0739: throw new GenICException(
0740: "Impossible to load jorm meta information",
0741: e);
0742: }
0743: }
0744: bs = new BeanSources(beansDD[i], gp, ve, jormCompiler);
0745: } else {
0746: bs = new BeanSources(beansDD[i], gp, ve);
0747: }
0748: beanList.add(bs);
0749: //compute message
0750: message.append(sep);
0751: sep = ", ";
0752: message.append("'");
0753: message.append(bs.getEjbName());
0754: message.append("'");
0755: }
0756: generatedIC = !beanList.isEmpty();
0757: if (generatedIC) {
0758: message.append(" generation ...");
0759: } else {
0760: message
0761: .append("No generation to do (only message driven beans)");
0762: }
0763: GenIC.info(message.toString());
0764:
0765: // Generates the sources of the container classes of the beans
0766: // and Init the lists of the remote/non-remote java sources and the
0767: // remote classes
0768: for (Iterator it = beanList.iterator(); it.hasNext();) {
0769: BeanSources ics = (BeanSources) it.next();
0770: ics.generate();
0771: String cchfn = ics.getWrpHomeClusterFileName();
0772: if (cchfn != null) {
0773: filesToDelete.add(cchfn);
0774: }
0775: String ccrfn = ics.getWrpRemoteClusterFileName();
0776: if (ccrfn != null) {
0777: filesToDelete.add(ccrfn);
0778: }
0779: trace("Sources classes successfully generated" + " for '"
0780: + ics.getEjbName() + "'");
0781: noRemoteJavas.addAll(ics.getNoRemoteJavas());
0782: if (ics.getWrpHomeFileName() != null) {
0783: remoteJavas.add(ics.getWrpHomeFileName());
0784: remoteClasses.add(ics.getWrpHomeClassName());
0785: }
0786: if (ics.getWrpRemoteFileName() != null) {
0787: remoteJavas.add(ics.getWrpRemoteFileName());
0788: remoteClasses.add(ics.getWrpRemoteClassName());
0789: }
0790: if (ics.getWrpServiceEndpointFileName() != null) {
0791: remoteJavas.add(ics.getWrpServiceEndpointFileName());
0792: remoteClasses.add(ics.getWrpServiceEndpointClassName());
0793: }
0794: }
0795: jormCompiler = null;
0796:
0797: }
0798:
0799: /**
0800: * Allocate and configure a JORM compiler
0801: * @param miManager the JORM Meta-Information manager
0802: * @return a JORM compiler
0803: */
0804: private JormCompiler allocateJormCompiler(Manager miManager) {
0805: // Allocate and configure a Jorm Compiler
0806: JormCompiler jormCompiler = new JormCompiler();
0807: JormCompilerConfigurator jcc = jormCompiler
0808: .getCompilerConfigurator();
0809: Properties prop = new Properties();
0810: prop.put("jorm.generator",
0811: "org.objectweb.jorm.generator.lib.JormGenerator");
0812: prop.put("jorm.mimanager",
0813: "org.objectweb.jorm.metainfo.lib.JormManager");
0814: prop.put("jorm.writer",
0815: "org.objectweb.jorm.mi2xml.lib.BasicDomWriter");
0816: prop.put("jorm.mapper.list", "rdb");
0817: prop
0818: .put("jorm.mapper.mifactory.rdb",
0819: "org.objectweb.jorm.mapper.rdb.metainfo.RdbMappingFactory");
0820: prop
0821: .put("jorm.mapper.mopfactory.rdb",
0822: "org.objectweb.jorm.mapper.rdb.generator.RdbMOPFactory");
0823: prop
0824: .put("jorm.mapper.gcmapping.rdb",
0825: "org.objectweb.jorm.mapper.rdb.genclass.RdbGenClassMapping");
0826: prop
0827: .put("jorm.mapper.schmgr.rdb",
0828: "org.objectweb.jorm.mapper.rdb.lib.RdbPMappingStructuresManager");
0829: prop
0830: .put("jorm.mapper.writer.rdb",
0831: "org.objectweb.jorm.mapper.rdb.mi2xml.RdbDomtreeBuilder");
0832: prop.put("use.context.classloader", "true");
0833: prop.put("jorm.mapper.submappers.rdb", "generic");
0834: jcc.configure(prop);
0835: jcc.setLoggerFactory(Log.getLoggerFactory());
0836: jormCompiler.setMIManager(miManager);
0837: return jormCompiler;
0838: }
0839:
0840: /**
0841: * Allocate and configure a Velocity Engine
0842: * @return the Velocity Engine
0843: * @throws GenICException in error case
0844: */
0845: private VelocityEngine allocateVelocityEngine()
0846: throws GenICException {
0847: VelocityEngine ve = new VelocityEngine();
0848: ve.setProperty(RuntimeConstants.VM_LIBRARY, "GenICMacros.vm");
0849: ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "file");
0850:
0851: String jonasRoot = System.getProperty(INSTALL_ROOT_PROPERTY);
0852: if (jonasRoot == null) {
0853: throw new GenICException("System property '"
0854: + INSTALL_ROOT_PROPERTY + "' not set");
0855: }
0856: String path2Tmpl = new String(jonasRoot + File.separatorChar
0857: + "templates" + File.separatorChar + "genic");
0858: ve.setProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH,
0859: path2Tmpl);
0860: // Velocity logs
0861: Logger vLogger = Log.getLogger(Log.JONAS_GENIC_VELOCITY_PREFIX);
0862: if (vLogger.isLoggable(BasicLevel.DEBUG)) {
0863: // No more velocity logs to avoid the creation of an empty file
0864: // "velocity.log"
0865: ve.setProperty(
0866: RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS,
0867: "org.apache.velocity.runtime.log.NullLogSystem");
0868: } else {
0869: // Connect the velocity log system to monolog
0870: ve.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM,
0871: new VelocityLogger(vLogger));
0872: }
0873: try {
0874: ve.init();
0875: } catch (Exception e) {
0876: throw new GenICException(
0877: "Cannot initialize the Velocity engine", e);
0878: }
0879: return ve;
0880: }
0881:
0882: /**
0883: * Compiles the java sources generated by the constructor I.e. :
0884: * <ul>
0885: * <li>compile the classes via javac,
0886: * <li>create the stubs and skeletons for the protocols supported(RMI/JRMP,
0887: * RMI/IIOP,JEREMIE) via rmic/jrmic
0888: * </ul>
0889: * @param classpath classpath value
0890: * @exception GenICException In error case
0891: */
0892: public void compilClasses(String classpath) throws GenICException {
0893:
0894: Cmd jrmpCmd;
0895: Cmd iiopCmd;
0896: Cmd jeremieCmd;
0897: Cmd cmd;
0898:
0899: String cmdJava;
0900: String cmdJavac;
0901: String cmdRmic;
0902:
0903: if (!generatedIC) {
0904: return;
0905: }
0906:
0907: /*
0908: * Init the command names
0909: */
0910: cmdJava = javaHomeBin + "java";
0911: if (gp.getJavacName() == null) {
0912: cmdJavac = javaHomeBin + "javac";
0913: } else {
0914: cmdJavac = gp.getJavacName();
0915: }
0916: cmdRmic = javaHomeBin + "rmic";
0917:
0918: /*
0919: * Compile the generated sources
0920: */
0921: if (!new File(cmdJavac).exists()) {
0922: // Maybe this is on windows
0923: if (!new File(cmdJavac + ".exe").exists()) {
0924: logger
0925: .log(
0926: BasicLevel.INFO,
0927: "No javac command was found at '"
0928: + cmdJavac
0929: + "'. Check that you are using a JDK and not a JRE.");
0930: }
0931: }
0932: cmd = new Cmd(cmdJavac, gp.isInvokeCmd());
0933: cmd.addArgument("-classpath");
0934: cmd.addArgument(classpath);
0935: cmd.addArgument("-d");
0936: if ((outputdir.length() == 0)) {
0937: cmd.addArgument(".");
0938: } else {
0939: cmd.addArgument(outputdir);
0940: }
0941: cmd.addArguments(gp.getJavacOptions());
0942:
0943: for (Iterator it = remoteJavas.iterator(); it.hasNext();) {
0944: String srcName = (String) it.next();
0945: cmd.addArgument(srcName);
0946: filesToDelete.add(srcName);
0947: }
0948: for (Iterator it = noRemoteJavas.iterator(); it.hasNext();) {
0949: String srcName = (String) it.next();
0950: cmd.addArgument(srcName);
0951: filesToDelete.add(srcName);
0952: }
0953:
0954: trace("Running '" + cmd.toString() + "'");
0955: if (cmd.run()) {
0956: trace("Sources classes successfully compiled via java compiler.");
0957: } else {
0958: throw new GenICException(
0959: "Failed when compiling the generated classes via java compiler");
0960: }
0961:
0962: if (remoteJavas.size() == 0) {
0963: return;
0964: }
0965:
0966: /*
0967: * Generate the stub and skeletons of the home and remote implementations
0968: */
0969:
0970: if (!new File(cmdRmic).exists()) {
0971: // Maybe this is on windows
0972: if (!new File(cmdRmic + ".exe").exists()) {
0973: logger
0974: .log(
0975: BasicLevel.INFO,
0976: "No rmic command was found at '"
0977: + cmdRmic
0978: + "'. Check that you are using a JDK and not a JRE.");
0979: }
0980: }
0981: jrmpCmd = new Cmd(cmdRmic);
0982: jrmpCmd.addArgument("-classpath");
0983: jrmpCmd.addArgument(classpath);
0984:
0985: iiopCmd = new Cmd(cmdRmic);
0986: iiopCmd.addArgument("-classpath");
0987: iiopCmd.addArgument(classpath);
0988: iiopCmd.addArgument("-iiop");
0989: iiopCmd.addArgument("-poa");
0990: iiopCmd.addArgument("-always");
0991:
0992: jeremieCmd = new Cmd(cmdJava);
0993: jeremieCmd.addArgument("-classpath");
0994: jeremieCmd.addArgument(classpath);
0995: jeremieCmd
0996: .addArgument("org.objectweb.jeremie.tools.jrmic.JRMICompiler");
0997: jeremieCmd.addArgument("-opt");
0998: jeremieCmd.addArgument("-owext");
0999: if (gp.getJavacName() != null) {
1000: jeremieCmd.addArgument("-c");
1001: jeremieCmd.addArgument(gp.getJavacName());
1002: }
1003:
1004: if (!"".equals(outputdir)) {
1005: jrmpCmd.addArgument("-d");
1006: jrmpCmd.addArgument(outputdir);
1007: iiopCmd.addArgument("-d");
1008: iiopCmd.addArgument(outputdir);
1009: jeremieCmd.addArgument("-d");
1010: jeremieCmd.addArgument(outputdir);
1011: }
1012:
1013: jrmpCmd.addArguments(gp.getRmicOptions());
1014: iiopCmd.addArguments(gp.getRmicOptions());
1015: jeremieCmd.addArguments(gp.getRmicOptions());
1016:
1017: for (Iterator it = remoteClasses.iterator(); it.hasNext();) {
1018: String className = (String) it.next();
1019: jrmpCmd.addArgument(className);
1020: iiopCmd.addArgument(className);
1021: jeremieCmd.addArgument(className);
1022: }
1023:
1024: // Use fast rmic, if there are failures, fallback to rmic
1025: if (gp.getProtocols().isSupported(Protocols.RMI_JRMP)
1026: && gp.isFastRmicEnabled()) {
1027: trace("Running fastrmic for '" + jrmpCmd.toString() + "'");
1028: ArrayList args = new ArrayList();
1029: boolean skip = true;
1030: for (Iterator it = jrmpCmd.getCommandLine(); it.hasNext();) {
1031: Object o = it.next();
1032: if (skip) {
1033: skip = false;
1034: continue;
1035: }
1036: args.add(o);
1037: }
1038:
1039: String[] a = (String[]) args.toArray(new String[] {});
1040: Method m = null;
1041: try {
1042: Class c = Class.forName("org.objectweb.fastrmic.RMIC");
1043: m = c.getMethod("main", new Class[] { String[].class });
1044: } catch (ClassNotFoundException cnfe) {
1045: logger.log(BasicLevel.ERROR,
1046: "continuing after class not found ", cnfe);
1047: gp.setFastRmicEnabled(false);
1048: } catch (NoSuchMethodException nsme) {
1049: logger.log(BasicLevel.ERROR,
1050: "continuing after no such method ", nsme);
1051: gp.setFastRmicEnabled(false);
1052: }
1053:
1054: if (m != null) {
1055: try {
1056: m.invoke(null, new Object[] { a });
1057: // Call to the GC for bug (#303750)
1058: // fastRMIC load classes of the jar, then there is a lock on the file until the GC is called.
1059: System.gc();
1060: } catch (IllegalAccessException iae) {
1061: logger.log(BasicLevel.ERROR,
1062: "continuing after illegal access", iae);
1063: gp.setFastRmicEnabled(false);
1064: } catch (InvocationTargetException ite) {
1065: throw new GenICException("error in fastrmic", ite);
1066: }
1067: info("Stubs and Skels successfully generated with fastrmic for rmi/jrmp");
1068: }
1069: }
1070:
1071: if (gp.getProtocols().isSupported(Protocols.RMI_JRMP)
1072: && !gp.isFastRmicEnabled()) {
1073: trace("Running '" + jrmpCmd.toString() + "'");
1074: if (jrmpCmd.run()) {
1075: info("Stubs and Skels successfully generated for rmi/jrmp");
1076: } else {
1077: throw new GenICException(
1078: "Failed when generating the Stubs and Skels with rmic jrmp");
1079: }
1080: }
1081:
1082: if (gp.getProtocols().isSupported(Protocols.RMI_IIOP)) {
1083: trace("Running '" + iiopCmd.toString() + "'");
1084: if (iiopCmd.run()) {
1085: info("Stubs and Skels successfully generated for rmi/iiop");
1086: } else {
1087: throw new GenICException(
1088: "Failed when generating the Stubs and Skels with rmic iiop");
1089: }
1090:
1091: }
1092:
1093: if (gp.getProtocols().isSupported(Protocols.JEREMIE)) {
1094: trace("Running '" + jeremieCmd.toString() + "'");
1095: if (jeremieCmd.run()) {
1096: info("Stubs and Skels successfully generated with rmi/jeremie");
1097: } else {
1098: throw new GenICException(
1099: "Failed when generating the Stubs and Skels with jeremie jrmic");
1100: }
1101: }
1102: }
1103:
1104: /**
1105: * Add the generated classes in the given ejb-jar file.
1106: * @throws GenICException if the classes cannot be added in the jar file
1107: */
1108: public void addClassesInJar() throws GenICException {
1109:
1110: if (!generatedIC) {
1111: return;
1112: }
1113:
1114: filesToDelete.add(outputdir);
1115:
1116: ArrayList lf = new ArrayList();
1117: getFilesList(outputdir, lf, !gp.isKeepGenerated());
1118:
1119: updateJar(gp.getInputFilename(), outputdir, lf);
1120:
1121: }
1122:
1123: /**
1124: * Convert a name from any format in Jar filename format
1125: * @param name filename to be converted
1126: * @return converted filename
1127: */
1128: protected String convertName(String name) {
1129: return name.replace('\\', '/');
1130: }
1131:
1132: /**
1133: * Add some classes in an existing jar file via the java.util.jar api.
1134: * @param jfn jar filename
1135: * @param od base directory of generated files
1136: * @param lfn list of filenames to add
1137: * @throws GenICException if the classes cannot be added
1138: */
1139: private void updateJar(String jfn, String od, List lfn)
1140: throws GenICException {
1141:
1142: File jarFile = null;
1143: File tempJarFile = null;
1144: JarFile jarArchive = null;
1145: JarOutputStream tempJarArchive = null;
1146:
1147: try {
1148: jarFile = new File(jfn);
1149: tempJarFile = new File(jfn + ".tmp");
1150:
1151: // open existing jar file
1152: jarArchive = new JarFile(jarFile);
1153:
1154: // create temporary jar
1155: tempJarArchive = new JarOutputStream(new FileOutputStream(
1156: tempJarFile));
1157:
1158: byte[] buffer = new byte[BUFFER_SIZE];
1159: int read = 0;
1160:
1161: // Add all generated files to temporary jar
1162: FileInputStream file = null;
1163: int is = od.length() + 1;
1164: Iterator iterFiles = lfn.iterator();
1165: while (iterFiles.hasNext()) {
1166: try {
1167: String fileName = (String) iterFiles.next();
1168:
1169: file = new FileInputStream(fileName);
1170: JarEntry entry = new JarEntry(convertName(fileName
1171: .substring(is)));
1172: tempJarArchive.putNextEntry(entry);
1173: // contents
1174: while ((read = file.read(buffer)) != -1) {
1175: tempJarArchive.write(buffer, 0, read);
1176: }
1177: } finally {
1178: file.close();
1179: }
1180: }
1181:
1182: // Add the rest of files (except if already included)
1183: Enumeration ents = jarArchive.entries();
1184: while (ents.hasMoreElements()) {
1185: JarEntry entry = (JarEntry) ents.nextElement();
1186: // add only if there is not a newer version
1187: // already included
1188: // In a windows plateform we must replace / by \ for a correct path
1189: if (!lfn.contains(od
1190: + File.separator
1191: + entry.getName().replace('/',
1192: File.separatorChar))) {
1193: InputStream enStream = jarArchive
1194: .getInputStream(entry);
1195: tempJarArchive.putNextEntry(entry);
1196: // contents
1197: while ((read = enStream.read(buffer)) != -1) {
1198: tempJarArchive.write(buffer, 0, read);
1199: }
1200: }
1201: }
1202:
1203: } catch (Exception e) {
1204: throw new GenICException(
1205: "Failed when adding the generated classes "
1206: + "in the given ejb-jar file '" + jfn
1207: + "': " + e);
1208: } finally {
1209: // close jar archives
1210: try {
1211: jarArchive.close();
1212: } catch (IOException e1) {
1213: warning("Failed to close jar archive file '"
1214: + jarArchive.getName());
1215: }
1216: try {
1217: tempJarArchive.close();
1218: } catch (IOException e1) {
1219: warning("Failed to close temporary jar archive file '"
1220: + jarArchive.getName() + "'");
1221: }
1222: }
1223:
1224: // Copy temporary jar file -> original jar
1225: boolean deleted = jarFile.delete();
1226: boolean rename = tempJarFile.renameTo(jarFile);
1227: if (!deleted || !rename) {
1228: error("Failed to update jar archive file '"
1229: + jarArchive.getName() + "'");
1230: }
1231: }
1232:
1233: /**
1234: * Clean the intermediate generated files.
1235: */
1236: public void clean() {
1237: trace("Deleting " + filesToDelete.toString());
1238: for (Iterator it = filesToDelete.iterator(); it.hasNext();) {
1239: String name = (String) it.next();
1240: File f = new File(name);
1241: delete(f);
1242: }
1243: }
1244:
1245: /**
1246: * Delete a file or directory recursively
1247: * @param f file or directory to be deleted
1248: * @return true if deletion ok, false otherwise.
1249: */
1250: private boolean delete(File f) {
1251: if (f.isFile()) {
1252: return f.delete();
1253: } else {
1254: File[] childs = f.listFiles();
1255: if (childs == null) {
1256: // no childs
1257: return f.delete();
1258: } else {
1259: // childs
1260: boolean result = true;
1261: for (int i = 0; i < childs.length; i++) {
1262: result &= delete(childs[i]);
1263: }
1264: return result && f.delete();
1265: }
1266: }
1267: }
1268:
1269: /**
1270: * Display the usage
1271: */
1272: static void usage() {
1273: StringBuffer msg = new StringBuffer();
1274: msg
1275: .append("Usage: java org.objectweb.jonas_ejb.genic.GenIC -help \n");
1276: msg.append(" to print this help message \n");
1277: msg
1278: .append(" or java org.objectweb.jonas_ejb.genic.GenIC <Options> <Input_File> \n");
1279: msg
1280: .append(" to generate the container-specific classes for given EJB(s). \n");
1281: msg.append(" \n");
1282: msg.append("Options include: \n");
1283: msg
1284: .append(" -d <output_dir> specify where to place the generated files \n");
1285: msg
1286: .append(" -noaddinjar do not add the generated classes in the given \n");
1287: msg.append(" ejb-jar file \n");
1288: msg
1289: .append(" -nocompil do not compile the generated source files via \n");
1290: msg
1291: .append(" the java and rmi compilers \n");
1292: msg
1293: .append(" -novalidation parse the XML deployment descriptors without \n");
1294: msg.append(" validation \n");
1295: msg
1296: .append(" -classpath <path> define the classpath to be used to compile classes \n");
1297: msg
1298: .append(" -javac <opt> specify the java compiler to use \n");
1299: msg
1300: .append(" -javacopts <opt> specify the options to pass to the java compiler \n");
1301: msg
1302: .append(" -rmicopts <opt> specify the options to pass to the rmi compiler \n");
1303: msg
1304: .append(" -protocols list of protocol, separated by comma \n");
1305: msg.append(" (default is jrmp) \n");
1306: msg
1307: .append(" -invokecmd invoke, in some case, directly the method of the java class\n");
1308: msg
1309: .append(" corresponding to the command \n");
1310: msg
1311: .append(" -keepgenerated do not delete intermediate generated source files \n");
1312: msg.append(" -verbose \n");
1313: msg
1314: .append(" -debug deprecated (use the JOnAS trace properties file)\n");
1315: msg.append(" \n");
1316: msg
1317: .append(" Input_File standard deployment descriptor file's name or \n");
1318: msg.append(" ejb-jar file's name \n");
1319: GenIC.info(msg.toString());
1320: }
1321:
1322: /**
1323: * Display the specified message only if verbose.
1324: * @param msg the message to display
1325: */
1326: void trace(String msg) {
1327: int level = BasicLevel.DEBUG;
1328: if (verbose) {
1329: level = BasicLevel.INFO;
1330: }
1331: logger.log(level, msg);
1332: }
1333:
1334: /**
1335: * Display the specified message.
1336: * @param msg the message to display
1337: */
1338: static void info(String msg) {
1339: logger.log(BasicLevel.INFO, msg);
1340: }
1341:
1342: /**
1343: * Display the specified warning message.
1344: * @param msg the warning message to display
1345: */
1346: static void warning(String msg) {
1347: logger.log(BasicLevel.WARN, msg);
1348: }
1349:
1350: /**
1351: * Display the specified error message.
1352: * @param msg the error message to display
1353: */
1354: static void error(String msg) {
1355: logger.log(BasicLevel.ERROR, msg);
1356: }
1357:
1358: /**
1359: * Display the specified error message and exits with an EXIT_FAILURE
1360: * status.
1361: * @param msg the error message to display
1362: * @param e the exception raised
1363: */
1364: static void fatalError(String msg, Exception e) {
1365: error("GenIC fatal error: " + msg + e.getMessage());
1366: throw new RuntimeException(msg);
1367: }
1368:
1369: /**
1370: * Display the specified error message and exits with an EXIT_FAILURE
1371: * status.
1372: * @param e the error to display
1373: */
1374: static void fatalError(Exception e) {
1375: System.err.println("GenIC fatal error: ");
1376: printException(e, System.err);
1377: throw new RuntimeException(e.getMessage());
1378: }
1379:
1380: /**
1381: * Display the exception and its nested exception if exists, on the given
1382: * printstream.
1383: * @param e the exception to display
1384: * @param out the PrintStream on which the exception has to displayed
1385: */
1386: static void printException(Exception e, PrintStream out) {
1387: Exception inner = null;
1388: if (e instanceof GenICException
1389: && (inner = ((GenICException) e).inner) != null) {
1390: out.println(e.getMessage());
1391: printException(inner, out);
1392: } else if (e instanceof PException
1393: && (inner = ((PException) e).getNestedException()) != null) {
1394: out.println(e.getMessage());
1395: printException(inner, out);
1396: } else if (e instanceof MedorException
1397: && (inner = ((MedorException) e).getNestedException()) != null) {
1398: out.println(e.getMessage());
1399: printException(inner, out);
1400: } else {
1401: e.printStackTrace();
1402: }
1403: }
1404:
1405: /**
1406: * Create a cleaned temporary directory.
1407: * @return the temp directory file name
1408: * @throws IOException if a temp directory cannot be created.
1409: */
1410: static String createTempDir() throws IOException {
1411: File tmpDir = File.createTempFile("genic", null, null);
1412: tmpDir.delete();
1413: if (!tmpDir.mkdir()) {
1414: throw new IOException(
1415: "Cannot create the temporary directory '" + tmpDir
1416: + "'.");
1417: }
1418: return tmpDir.getAbsolutePath();
1419: }
1420:
1421: /**
1422: * Get the list file names recursively of the given directory
1423: * @param dir the directory used to list files
1424: * @param list list to store filenames
1425: * @param onlyClass stores only class or not ?
1426: */
1427: static void getFilesList(String dir, ArrayList list,
1428: boolean onlyClass) {
1429: File df = new File(dir);
1430: if (df.exists() && df.isDirectory()) {
1431: File[] ls = df.listFiles();
1432: for (int i = 0; i < ls.length; i++) {
1433: File f = ls[i];
1434: String fn = f.getAbsolutePath();
1435: if (f.isDirectory()) {
1436: getFilesList(fn, list, onlyClass);
1437: } else {
1438: if (!onlyClass || fn.endsWith(".class")) {
1439: if (!fn.endsWith(".save")) {
1440: list.add(fn);
1441: }
1442: }
1443: }
1444: }
1445: }
1446: }
1447: }
|