diff options
Diffstat (limited to 'framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/ejb/IPlanetEjbc.java')
-rw-r--r-- | framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/ejb/IPlanetEjbc.java | 1495 |
1 files changed, 0 insertions, 1495 deletions
diff --git a/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/ejb/IPlanetEjbc.java b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/ejb/IPlanetEjbc.java deleted file mode 100644 index ed799d33..00000000 --- a/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/ejb/IPlanetEjbc.java +++ /dev/null @@ -1,1495 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.apache.tools.ant.taskdefs.optional.ejb; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.Hashtable; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.StringTokenizer; - -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; - -import org.xml.sax.AttributeList; -import org.xml.sax.HandlerBase; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; - -/** - * Compiles EJB stubs and skeletons for the iPlanet Application - * Server (iAS). The class will read a standard EJB descriptor (as well as an - * EJB descriptor specific to iPlanet Application Server) to identify one or - * more EJBs to process. It will search for EJB "source" classes (the remote -; * interface, home interface, and EJB implementation class) and the EJB stubs - * and skeletons in the specified destination directory. Only if the stubs and - * skeletons cannot be found or if they're out of date will the iPlanet - * Application Server ejbc utility be run. - * <p> - * Because this class (and it's assorted inner classes) may be bundled into the - * iPlanet Application Server distribution at some point (and removed from the - * Ant distribution), the class has been written to be independent of all - * Ant-specific classes. It is also for this reason (and to avoid cluttering - * the Apache Ant source files) that this utility has been packaged into a - * single source file. - * <p> - * For more information on Ant Tasks for iPlanet Application Server, see the - * <code>IPlanetDeploymentTool</code> and <code>IPlanetEjbcTask</code> classes. - * - * @see IPlanetDeploymentTool - * @see IPlanetEjbcTask - * @ant.task ignore="true" - */ -public class IPlanetEjbc { - - private static final int MIN_NUM_ARGS = 2; - private static final int MAX_NUM_ARGS = 8; - private static final int NUM_CLASSES_WITH_IIOP = 15; - private static final int NUM_CLASSES_WITHOUT_IIOP = 9; - - /* Constants used for the "beantype" attribute */ - private static final String ENTITY_BEAN = "entity"; - private static final String STATELESS_SESSION = "stateless"; - private static final String STATEFUL_SESSION = "stateful"; - - /* Filenames of the standard EJB descriptor and the iAS-specific descriptor */ - private File stdDescriptor; - private File iasDescriptor; - - /* - * Directory where "source" EJB files are stored and where stubs and - * skeletons will also be written. - */ - private File destDirectory; - - /* Classpath used when the iAS ejbc is called */ - private String classpath; - private String[] classpathElements; - - /* Options passed to the iAS ejbc */ - private boolean retainSource = false; - private boolean debugOutput = false; - - /* iAS installation directory (used if ejbc isn't on user's PATH) */ - private File iasHomeDir; - - /* Parser and handler used to process both EJB descriptor files */ - private SAXParser parser; - private EjbcHandler handler = new EjbcHandler(); - - /* - * This Hashtable maintains a list of EJB class files processed by the ejbc - * utility (both "source" class files as well as stubs and skeletons). The - * key for the Hashtable is a String representing the path to the class file - * (relative to the destination directory). The value for the Hashtable is - * a File object which reference the actual class file. - */ - private Hashtable ejbFiles = new Hashtable(); - - /* Value of the display-name element read from the standard EJB descriptor */ - private String displayName; - - /** - * Constructs an instance which may be used to process EJB descriptors and - * generate EJB stubs and skeletons, if needed. - * - * @param stdDescriptor File referencing a standard EJB descriptor. - * @param iasDescriptor File referencing an iAS-specific EJB descriptor. - * @param destDirectory File referencing the base directory where both - * EJB "source" files are found and where stubs and - * skeletons will be written. - * @param classpath String representation of the classpath to be used - * by the iAS ejbc utility. - * @param parser SAXParser to be used to process both of the EJB - * descriptors. - * @todo classpathElements is not needed here, its never used - * (at least IDEA tells me so! :) - */ - public IPlanetEjbc(File stdDescriptor, - File iasDescriptor, - File destDirectory, - String classpath, - SAXParser parser) { - this.stdDescriptor = stdDescriptor; - this.iasDescriptor = iasDescriptor; - this.destDirectory = destDirectory; - this.classpath = classpath; - this.parser = parser; - - /* - * Parse the classpath into it's individual elements and store the - * results in the "classpathElements" instance variable. - */ - List elements = new ArrayList(); - if (classpath != null) { - StringTokenizer st = new StringTokenizer(classpath, - File.pathSeparator); - while (st.hasMoreTokens()) { - elements.add(st.nextToken()); - } - classpathElements - = (String[]) elements.toArray(new String[elements.size()]); - } - } - - /** - * If true, the Java source files which are generated by the - * ejbc process are retained. - * - * @param retainSource A boolean indicating if the Java source files for - * the stubs and skeletons should be retained. - * @todo This is not documented in the HTML. On purpose? - */ - public void setRetainSource(boolean retainSource) { - this.retainSource = retainSource; - } - - /** - * If true, enables debugging output when ejbc is executed. - * - * @param debugOutput A boolean indicating if debugging output should be - * generated - */ - public void setDebugOutput(boolean debugOutput) { - this.debugOutput = debugOutput; - } - - /** - * Registers the location of a local DTD file or resource. By registering - * a local DTD, EJB descriptors can be parsed even when the remote servers - * which contain the "public" DTDs cannot be accessed. - * - * @param publicID The public DTD identifier found in an XML document. - * @param location The file or resource name for the appropriate DTD stored - * on the local machine. - */ - public void registerDTD(String publicID, String location) { - handler.registerDTD(publicID, location); - } - - /** - * May be used to specify the "home" directory for this iAS installation. - * The directory specified should typically be - * <code>[install-location]/iplanet/ias6/ias</code>. - * - * @param iasHomeDir The home directory for the user's iAS installation. - */ - public void setIasHomeDir(File iasHomeDir) { - this.iasHomeDir = iasHomeDir; - } - - /** - * Returns a Hashtable which contains a list of EJB class files processed by - * the ejbc utility (both "source" class files as well as stubs and - * skeletons). The key for the Hashtable is a String representing the path - * to the class file (relative to the destination directory). The value for - * the Hashtable is a File object which reference the actual class file. - * - * @return The list of EJB files processed by the ejbc utility. - */ - public Hashtable getEjbFiles() { - return ejbFiles; - } - - /** - * Returns the display-name element read from the standard EJB descriptor. - * - * @return The EJB-JAR display name. - */ - public String getDisplayName() { - return displayName; - } - - /** - * Returns the list of CMP descriptors referenced in the EJB descriptors. - * - * @return An array of CMP descriptors. - */ - public String[] getCmpDescriptors() { - List returnList = new ArrayList(); - - EjbInfo[] ejbs = handler.getEjbs(); - - for (int i = 0; i < ejbs.length; i++) { - List descriptors = (List) ejbs[i].getCmpDescriptors(); - returnList.addAll(descriptors); - } - - return (String[]) returnList.toArray(new String[returnList.size()]); - } - - /** - * Main application method for the iPlanet Application Server ejbc utility. - * If the application is run with no commandline arguments, a usage - * statement is printed for the user. - * - * @param args The commandline arguments passed to the application. - */ - public static void main(String[] args) { - File stdDescriptor; - File iasDescriptor; - File destDirectory = null; - String classpath = null; - SAXParser parser = null; - boolean debug = false; - boolean retainSource = false; - IPlanetEjbc ejbc; - - if ((args.length < MIN_NUM_ARGS) || (args.length > MAX_NUM_ARGS)) { - usage(); - return; - } - - stdDescriptor = new File(args[args.length - 2]); - iasDescriptor = new File(args[args.length - 1]); - - for (int i = 0; i < args.length - 2; i++) { - if (args[i].equals("-classpath")) { - classpath = args[++i]; - } else if (args[i].equals("-d")) { - destDirectory = new File(args[++i]); - } else if (args[i].equals("-debug")) { - debug = true; - } else if (args[i].equals("-keepsource")) { - retainSource = true; - } else { - usage(); - return; - } - } - - /* If the -classpath flag isn't specified, use the system classpath */ - if (classpath == null) { - Properties props = System.getProperties(); - classpath = props.getProperty("java.class.path"); - } - - /* - * If the -d flag isn't specified, use the working directory as the - * destination directory - */ - if (destDirectory == null) { - Properties props = System.getProperties(); - destDirectory = new File(props.getProperty("user.dir")); - } - - /* Construct a SAXParser used to process the descriptors */ - SAXParserFactory parserFactory = SAXParserFactory.newInstance(); - parserFactory.setValidating(true); - try { - parser = parserFactory.newSAXParser(); - } catch (Exception e) { - // SAXException or ParserConfigurationException may be thrown - System.out.println("An exception was generated while trying to "); - System.out.println("create a new SAXParser."); - e.printStackTrace(); - return; - } - - /* Build and populate an instance of the ejbc utility */ - ejbc = new IPlanetEjbc(stdDescriptor, iasDescriptor, destDirectory, - classpath, parser); - ejbc.setDebugOutput(debug); - ejbc.setRetainSource(retainSource); - - /* Execute the ejbc utility -- stubs/skeletons are rebuilt, if needed */ - try { - ejbc.execute(); - } catch (IOException e) { - System.out.println("An IOException has occurred while reading the " - + "XML descriptors (" + e.getMessage() + ")."); - return; - } catch (SAXException e) { - System.out.println("A SAXException has occurred while reading the " - + "XML descriptors (" + e.getMessage() + ")."); - return; - } catch (IPlanetEjbc.EjbcException e) { - System.out.println("An error has occurred while executing the ejbc " - + "utility (" + e.getMessage() + ")."); - return; - } - } - - /** - * Print a usage statement. - */ - private static void usage() { - System.out.println("java org.apache.tools.ant.taskdefs.optional.ejb.IPlanetEjbc \\"); - System.out.println(" [OPTIONS] [EJB 1.1 descriptor] [iAS EJB descriptor]"); - System.out.println(""); - System.out.println("Where OPTIONS are:"); - System.out.println(" -debug -- for additional debugging output"); - System.out.println(" -keepsource -- to retain Java source files generated"); - System.out.println(" -classpath [classpath] -- classpath used for compilation"); - System.out.println(" -d [destination directory] -- directory for compiled classes"); - System.out.println(""); - System.out.println("If a classpath is not specified, the system classpath"); - System.out.println("will be used. If a destination directory is not specified,"); - System.out.println("the current working directory will be used (classes will"); - System.out.println("still be placed in subfolders which correspond to their"); - System.out.println("package name)."); - System.out.println(""); - System.out.println("The EJB home interface, remote interface, and implementation"); - System.out.println("class must be found in the destination directory. In"); - System.out.println("addition, the destination will look for the stubs and skeletons"); - System.out.println("in the destination directory to ensure they are up to date."); - } - - /** - * Compiles the stub and skeletons for the specified EJBs, if they need to - * be updated. - * - * @throws EjbcException If the ejbc utility cannot be correctly configured - * or if one or more of the EJB "source" classes - * cannot be found in the destination directory - * @throws IOException If the parser encounters a problem reading the XML - * file - * @throws SAXException If the parser encounters a problem processing the - * XML descriptor (it may wrap another exception) - */ - public void execute() throws EjbcException, IOException, SAXException { - - checkConfiguration(); // Throws EjbcException if unsuccessful - - EjbInfo[] ejbs = getEjbs(); // Returns list of EJBs for processing - - for (int i = 0; i < ejbs.length; i++) { - log("EJBInfo..."); - log(ejbs[i].toString()); - } - - for (int i = 0; i < ejbs.length; i++) { - EjbInfo ejb = ejbs[i]; - - ejb.checkConfiguration(destDirectory); // Throws EjbcException - - if (ejb.mustBeRecompiled(destDirectory)) { - log(ejb.getName() + " must be recompiled using ejbc."); - - String[] arguments = buildArgumentList(ejb); - callEjbc(arguments); - - } else { - log(ejb.getName() + " is up to date."); - } - } - } - - /** - * Executes the iPlanet Application Server ejbc command-line utility. - * - * @param arguments Command line arguments to be passed to the ejbc utility. - */ - private void callEjbc(String[] arguments) { - - /* Concatenate all of the command line arguments into a single String */ - StringBuffer args = new StringBuffer(); - for (int i = 0; i < arguments.length; i++) { - args.append(arguments[i]).append(" "); - } - - /* If an iAS home directory is specified, prepend it to the commmand */ - String command; - if (iasHomeDir == null) { - command = ""; - } else { - command = iasHomeDir.toString() + File.separator + "bin" - + File.separator; - } - command += "ejbc "; - - log(command + args); - - /* - * Use the Runtime object to execute an external command. Use the - * RedirectOutput inner class to direct the standard and error output - * from the command to the JRE's standard output - */ - try { - Process p = Runtime.getRuntime().exec(command + args); - RedirectOutput output = new RedirectOutput(p.getInputStream()); - RedirectOutput error = new RedirectOutput(p.getErrorStream()); - output.start(); - error.start(); - p.waitFor(); - p.destroy(); - } catch (IOException e) { - log("An IOException has occurred while trying to execute ejbc."); - e.printStackTrace(); - } catch (InterruptedException e) { - // Do nothing - } - } - - /** - * Verifies that the user selections are valid. - * - * @throws EjbcException If the user selections are invalid. - */ - protected void checkConfiguration() throws EjbcException { - - String msg = ""; - - if (stdDescriptor == null) { - msg += "A standard XML descriptor file must be specified. "; - } - if (iasDescriptor == null) { - msg += "An iAS-specific XML descriptor file must be specified. "; - } - if (classpath == null) { - msg += "A classpath must be specified. "; - } - if (parser == null) { - msg += "An XML parser must be specified. "; - } - - if (destDirectory == null) { - msg += "A destination directory must be specified. "; - } else if (!destDirectory.exists()) { - msg += "The destination directory specified does not exist. "; - } else if (!destDirectory.isDirectory()) { - msg += "The destination specified is not a directory. "; - } - - if (msg.length() > 0) { - throw new EjbcException(msg); - } - } - - /** - * Parses the EJB descriptors and returns a list of EJBs which may need to - * be compiled. - * - * @return An array of objects which describe the EJBs to be - * processed. - * @throws IOException If the parser encounters a problem reading the XML - * files - * @throws SAXException If the parser encounters a problem processing the - * XML descriptor (it may wrap another exception) - */ - private EjbInfo[] getEjbs() throws IOException, SAXException { - EjbInfo[] ejbs = null; - - /* - * The EJB information is gathered from the standard XML EJB descriptor - * and the iAS-specific XML EJB descriptor using a SAX parser. - */ - - parser.parse(stdDescriptor, handler); - parser.parse(iasDescriptor, handler); - ejbs = handler.getEjbs(); - - return ejbs; - } - - /** - * Based on this object's instance variables as well as the EJB to be - * processed, the correct flags and parameters are set for the ejbc - * command-line utility. - * @param ejb The EJB for which stubs and skeletons will be compiled. - * @return An array of Strings which are the command-line parameters for - * for the ejbc utility. - */ - private String[] buildArgumentList(EjbInfo ejb) { - - List arguments = new ArrayList(); - - /* OPTIONAL COMMAND LINE PARAMETERS */ - - if (debugOutput) { - arguments.add("-debug"); - } - - /* No beantype flag is needed for an entity bean */ - if (ejb.getBeantype().equals(STATELESS_SESSION)) { - arguments.add("-sl"); - } else if (ejb.getBeantype().equals(STATEFUL_SESSION)) { - arguments.add("-sf"); - } - - if (ejb.getIiop()) { - arguments.add("-iiop"); - } - - if (ejb.getCmp()) { - arguments.add("-cmp"); - } - - if (retainSource) { - arguments.add("-gs"); - } - - if (ejb.getHasession()) { - arguments.add("-fo"); - } - - /* REQUIRED COMMAND LINE PARAMETERS */ - - arguments.add("-classpath"); - arguments.add(classpath); - - arguments.add("-d"); - arguments.add(destDirectory.toString()); - - arguments.add(ejb.getHome().getQualifiedClassName()); - arguments.add(ejb.getRemote().getQualifiedClassName()); - arguments.add(ejb.getImplementation().getQualifiedClassName()); - - /* Convert the List into an Array and return it */ - return (String[]) arguments.toArray(new String[arguments.size()]); - } - - /** - * Convenience method used to print messages to the user if debugging - * messages are enabled. - * - * @param msg The String to print to standard output. - */ - private void log(String msg) { - if (debugOutput) { - System.out.println(msg); - } - } - - - /* Inner classes follow */ - - - /** - * This inner class is used to signal any problems during the execution of - * the ejbc compiler. - * - */ - public class EjbcException extends Exception { - - /** - * Constructs an exception with the given descriptive message. - * - * @param msg Description of the exception which has occurred. - */ - public EjbcException(String msg) { - super(msg); - } - } // End of EjbcException inner class - - - /** - * This inner class is an XML document handler that can be used to parse EJB - * descriptors (both the standard EJB descriptor as well as the iAS-specific - * descriptor that stores additional values for iAS). Once the descriptors - * have been processed, the list of EJBs found can be obtained by calling - * the <code>getEjbs()</code> method. - * - * @see IPlanetEjbc.EjbInfo - */ - private class EjbcHandler extends HandlerBase { - /** EJB 1.1 ID */ - private static final String PUBLICID_EJB11 = - "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 1.1//EN"; - /** IPlanet ID */ - private static final String PUBLICID_IPLANET_EJB_60 = - "-//Sun Microsystems, Inc.//DTD iAS Enterprise JavaBeans 1.0//EN"; - /** EJB 1.1 location */ - private static final String DEFAULT_IAS60_EJB11_DTD_LOCATION = - "ejb-jar_1_1.dtd"; - /** IAS60 location */ - private static final String DEFAULT_IAS60_DTD_LOCATION = - "IASEjb_jar_1_0.dtd"; - - /* - * Two Maps are used to track local DTDs that will be used in case the - * remote copies of these DTDs cannot be accessed. The key for the Map - * is the DTDs public ID and the value is the local location for the DTD - */ - private Map resourceDtds = new HashMap(); - private Map fileDtds = new HashMap(); - - private Map ejbs = new HashMap(); // List of EJBs found in XML - private EjbInfo currentEjb; // One item within the Map - private boolean iasDescriptor = false; // Is doc iAS or EJB descriptor - - private String currentLoc = ""; // Tracks current element - private String currentText; // Tracks current text data - private String ejbType; // "session" or "entity" - - /** - * Constructs a new instance of the handler and registers local copies - * of the standard EJB 1.1 descriptor DTD as well as iAS's EJB - * descriptor DTD. - */ - public EjbcHandler() { - registerDTD(PUBLICID_EJB11, DEFAULT_IAS60_EJB11_DTD_LOCATION); - registerDTD(PUBLICID_IPLANET_EJB_60, DEFAULT_IAS60_DTD_LOCATION); - } - - /** - * Returns the list of EJB objects found during the processing of the - * standard EJB 1.1 descriptor and iAS-specific EJB descriptor. - * - * @return An array of EJBs which were found during the descriptor - * parsing. - */ - public EjbInfo[] getEjbs() { - return (EjbInfo[]) ejbs.values().toArray(new EjbInfo[ejbs.size()]); - } - - /** - * Returns the value of the display-name element found in the standard - * EJB 1.1 descriptor. - * - * @return String display-name value. - */ - public String getDisplayName() { - return displayName; - } - - /** - * Registers a local DTD that will be used when parsing an EJB - * descriptor. When the DTD's public identifier is found in an XML - * document, the parser will reference the local DTD rather than the - * remote DTD. This enables XML documents to be processed even when the - * public DTD isn't available. - * - * @param publicID The DTD's public identifier. - * @param location The location of the local DTD copy -- the location - * may either be a resource found on the classpath or a - * local file. - */ - public void registerDTD(String publicID, String location) { - log("Registering: " + location); - if ((publicID == null) || (location == null)) { - return; - } - - if (ClassLoader.getSystemResource(location) != null) { - log("Found resource: " + location); - resourceDtds.put(publicID, location); - } else { - File dtdFile = new File(location); - if (dtdFile.exists() && dtdFile.isFile()) { - log("Found file: " + location); - fileDtds.put(publicID, location); - } - } - } - - /** - * Resolves an external entity found during XML processing. If a public - * ID is found that has been registered with the handler, an <code> - * InputSource</code> will be returned which refers to the local copy. - * If the public ID hasn't been registered or if an error occurs, the - * superclass implementation is used. - * - * @param publicId The DTD's public identifier. - * @param systemId The location of the DTD, as found in the XML document. - */ - public InputSource resolveEntity(String publicId, String systemId) - throws SAXException { - InputStream inputStream = null; - - - try { - - /* Search the resource Map and (if not found) file Map */ - - String location = (String) resourceDtds.get(publicId); - if (location != null) { - inputStream - = ClassLoader.getSystemResource(location).openStream(); - } else { - location = (String) fileDtds.get(publicId); - if (location != null) { - inputStream = new FileInputStream(location); - } - } - } catch (IOException e) { - return super.resolveEntity(publicId, systemId); - } - - if (inputStream == null) { - return super.resolveEntity(publicId, systemId); - } else { - return new InputSource(inputStream); - } - } - - /** - * Receive notification that the start of an XML element has been found. - * - * @param name String name of the element found. - * @param atts AttributeList of the attributes included with the element - * (if any). - * @throws SAXException If the parser cannot process the document. - */ - public void startElement(String name, AttributeList atts) - throws SAXException { - - /* - * I need to "push" the element onto the String (currentLoc) which - * always represents the current location in the XML document. - */ - currentLoc += "\\" + name; - - /* A new element has started, so reset the text being captured */ - currentText = ""; - - if (currentLoc.equals("\\ejb-jar")) { - iasDescriptor = false; - } else if (currentLoc.equals("\\ias-ejb-jar")) { - iasDescriptor = true; - } - - if ((name.equals("session")) || (name.equals("entity"))) { - ejbType = name; - } - } - - /** - * Receive notification that character data has been found in the XML - * document - * - * @param ch Array of characters which have been found in the document. - * @param start Starting index of the data found in the document. - * @param len The number of characters found in the document. - * @throws SAXException If the parser cannot process the document. - */ - public void characters(char[] ch, int start, int len) - throws SAXException { - - currentText += new String(ch).substring(start, start + len); - } - - /** - * Receive notification that the end of an XML element has been found. - * - * @param name String name of the element. - * @throws SAXException If the parser cannot process the document. - */ - public void endElement(String name) throws SAXException { - - /* - * If this is a standard EJB 1.1 descriptor, we are looking for one - * set of data, while if this is an iAS-specific descriptor, we're - * looking for different set of data. Hand the processing off to - * the appropriate method. - */ - if (iasDescriptor) { - iasCharacters(currentText); - } else { - stdCharacters(currentText); - } - - /* - * I need to "pop" the element off the String (currentLoc) which - * always represents my current location in the XML document. - */ - - int nameLength = name.length() + 1; // Add one for the "\" - int locLength = currentLoc.length(); - - currentLoc = currentLoc.substring(0, locLength - nameLength); - } - - /** - * Receive notification that character data has been found in a standard - * EJB 1.1 descriptor. We're interested in retrieving the home - * interface, remote interface, implementation class, the type of bean, - * and if the bean uses CMP. - * - * @param value String data found in the XML document. - */ - private void stdCharacters(String value) { - - if (currentLoc.equals("\\ejb-jar\\display-name")) { - displayName = value; - return; - } - - String base = "\\ejb-jar\\enterprise-beans\\" + ejbType; - - if (currentLoc.equals(base + "\\ejb-name")) { - currentEjb = (EjbInfo) ejbs.get(value); - if (currentEjb == null) { - currentEjb = new EjbInfo(value); - ejbs.put(value, currentEjb); - } - } else if (currentLoc.equals(base + "\\home")) { - currentEjb.setHome(value); - } else if (currentLoc.equals(base + "\\remote")) { - currentEjb.setRemote(value); - } else if (currentLoc.equals(base + "\\ejb-class")) { - currentEjb.setImplementation(value); - } else if (currentLoc.equals(base + "\\prim-key-class")) { - currentEjb.setPrimaryKey(value); - } else if (currentLoc.equals(base + "\\session-type")) { - currentEjb.setBeantype(value); - } else if (currentLoc.equals(base + "\\persistence-type")) { - currentEjb.setCmp(value); - } - } - - /** - * Receive notification that character data has been found in an - * iAS-specific descriptor. We're interested in retrieving data - * indicating whether the bean must support RMI/IIOP access, whether - * the bean must provide highly available stubs and skeletons (in the - * case of stateful session beans), and if this bean uses additional - * CMP XML descriptors (in the case of entity beans with CMP). - * - * @param value String data found in the XML document. - */ - private void iasCharacters(String value) { - String base = "\\ias-ejb-jar\\enterprise-beans\\" + ejbType; - - if (currentLoc.equals(base + "\\ejb-name")) { - currentEjb = (EjbInfo) ejbs.get(value); - if (currentEjb == null) { - currentEjb = new EjbInfo(value); - ejbs.put(value, currentEjb); - } - } else if (currentLoc.equals(base + "\\iiop")) { - currentEjb.setIiop(value); - } else if (currentLoc.equals(base + "\\failover-required")) { - currentEjb.setHasession(value); - } else if (currentLoc.equals(base + "\\persistence-manager" - + "\\properties-file-location")) { - currentEjb.addCmpDescriptor(value); - } - } - } // End of EjbcHandler inner class - - - /** - * This inner class represents an EJB that will be compiled using ejbc. - * - */ - private class EjbInfo { - private String name; // EJB's display name - private Classname home; // EJB's home interface name - private Classname remote; // EJB's remote interface name - private Classname implementation; // EJB's implementation class - private Classname primaryKey; // EJB's primary key class - private String beantype = "entity"; // or "stateful" or "stateless" - private boolean cmp = false; // Does this EJB support CMP? - private boolean iiop = false; // Does this EJB support IIOP? - private boolean hasession = false; // Does this EJB require failover? - private List cmpDescriptors = new ArrayList(); // CMP descriptor list - - /** - * Construct a new EJBInfo object with the given name. - * - * @param name The display name for the EJB. - */ - public EjbInfo(String name) { - this.name = name; - } - - /** - * Returns the display name of the EJB. If a display name has not been - * set, it returns the EJB implementation classname (if the - * implementation class is not set, it returns "[unnamed]"). - * - * @return The display name for the EJB. - */ - public String getName() { - if (name == null) { - if (implementation == null) { - return "[unnamed]"; - } else { - return implementation.getClassName(); - } - } - return name; - } - - /* - * Below are getter's and setter's for each of the instance variables. - * Note that (in addition to supporting setters with the same type as - * the instance variable) a setter is provided with takes a String - * argument -- this are provided so the XML document handler can set - * the EJB values using the Strings it parses. - */ - - public void setHome(String home) { - setHome(new Classname(home)); - } - - public void setHome(Classname home) { - this.home = home; - } - - public Classname getHome() { - return home; - } - - public void setRemote(String remote) { - setRemote(new Classname(remote)); - } - - public void setRemote(Classname remote) { - this.remote = remote; - } - - public Classname getRemote() { - return remote; - } - - public void setImplementation(String implementation) { - setImplementation(new Classname(implementation)); - } - - public void setImplementation(Classname implementation) { - this.implementation = implementation; - } - - public Classname getImplementation() { - return implementation; - } - - public void setPrimaryKey(String primaryKey) { - setPrimaryKey(new Classname(primaryKey)); - } - - public void setPrimaryKey(Classname primaryKey) { - this.primaryKey = primaryKey; - } - - public Classname getPrimaryKey() { - return primaryKey; - } - - public void setBeantype(String beantype) { - this.beantype = beantype.toLowerCase(); - } - - public String getBeantype() { - return beantype; - } - - public void setCmp(boolean cmp) { - this.cmp = cmp; - } - - public void setCmp(String cmp) { - setCmp(cmp.equals("Container")); - } - - public boolean getCmp() { - return cmp; - } - - public void setIiop(boolean iiop) { - this.iiop = iiop; - } - - public void setIiop(String iiop) { - setIiop(iiop.equals("true")); - } - - public boolean getIiop() { - return iiop; - } - - public void setHasession(boolean hasession) { - this.hasession = hasession; - } - - public void setHasession(String hasession) { - setHasession(hasession.equals("true")); - } - - public boolean getHasession() { - return hasession; - } - - public void addCmpDescriptor(String descriptor) { - cmpDescriptors.add(descriptor); - } - - public List getCmpDescriptors() { - return cmpDescriptors; - } - - /** - * Verifies that the EJB is valid--if it is invalid, an exception is - * thrown - * - * - * @param buildDir The directory where the EJB remote interface, home - * interface, and implementation class must be found. - * @throws EjbcException If the EJB is invalid. - */ - private void checkConfiguration(File buildDir) throws EjbcException { - - /* Check that the specified instance variables are valid */ - if (home == null) { - throw new EjbcException("A home interface was not found " - + "for the " + name + " EJB."); - } - if (remote == null) { - throw new EjbcException("A remote interface was not found " - + "for the " + name + " EJB."); - } - if (implementation == null) { - throw new EjbcException("An EJB implementation class was not " - + "found for the " + name + " EJB."); - } - - if ((!beantype.equals(ENTITY_BEAN)) - && (!beantype.equals(STATELESS_SESSION)) - && (!beantype.equals(STATEFUL_SESSION))) { - throw new EjbcException("The beantype found (" + beantype + ") " - + "isn't valid in the " + name + " EJB."); - } - - if (cmp && (!beantype.equals(ENTITY_BEAN))) { - System.out.println("CMP stubs and skeletons may not be generated" - + " for a Session Bean -- the \"cmp\" attribute will be" - + " ignoredfor the " + name + " EJB."); - } - - if (hasession && (!beantype.equals(STATEFUL_SESSION))) { - System.out.println("Highly available stubs and skeletons may " - + "only be generated for a Stateful Session Bean -- the " - + "\"hasession\" attribute will be ignored for the " - + name + " EJB."); - } - - /* Check that the EJB "source" classes all exist */ - if (!remote.getClassFile(buildDir).exists()) { - throw new EjbcException("The remote interface " - + remote.getQualifiedClassName() + " could not be " - + "found."); - } - if (!home.getClassFile(buildDir).exists()) { - throw new EjbcException("The home interface " - + home.getQualifiedClassName() + " could not be " - + "found."); - } - if (!implementation.getClassFile(buildDir).exists()) { - throw new EjbcException("The EJB implementation class " - + implementation.getQualifiedClassName() + " could " - + "not be found."); - } - } - - /** - * Determines if the ejbc utility needs to be run or not. If the stubs - * and skeletons can all be found in the destination directory AND all - * of their timestamps are more recent than the EJB source classes - * (home, remote, and implementation classes), the method returns - * <code>false</code>. Otherwise, the method returns <code>true</code>. - * - * @param destDir The directory where the EJB source classes, stubs and - * skeletons are located. - * @return A boolean indicating whether or not the ejbc utility needs to - * be run to bring the stubs and skeletons up to date. - */ - public boolean mustBeRecompiled(File destDir) { - - long sourceModified = sourceClassesModified(destDir); - - long destModified = destClassesModified(destDir); - - return (destModified < sourceModified); - } - - /** - * Examines each of the EJB source classes (home, remote, and - * implementation) and returns the modification timestamp for the - * "oldest" class. - * - * @param classpath The classpath to be used to find the source EJB - * classes. If <code>null</code>, the system classpath - * is used. - * @return The modification timestamp for the "oldest" EJB source class. - * @throws BuildException If one of the EJB source classes cannot be - * found on the classpath. - */ - private long sourceClassesModified(File buildDir) { - long latestModified; // The timestamp of the "newest" class - long modified; // Timestamp for a given class - File remoteFile; // File for the remote interface class - File homeFile; // File for the home interface class - File implFile; // File for the EJB implementation class - File pkFile; // File for the EJB primary key class - - /* Check the timestamp on the remote interface */ - remoteFile = remote.getClassFile(buildDir); - modified = remoteFile.lastModified(); - if (modified == -1) { - System.out.println("The class " - + remote.getQualifiedClassName() + " couldn't " - + "be found on the classpath"); - return -1; - } - latestModified = modified; - - /* Check the timestamp on the home interface */ - homeFile = home.getClassFile(buildDir); - modified = homeFile.lastModified(); - if (modified == -1) { - System.out.println("The class " - + home.getQualifiedClassName() + " couldn't be " - + "found on the classpath"); - return -1; - } - latestModified = Math.max(latestModified, modified); - - /* Check the timestamp of the primary key class */ - if (primaryKey != null) { - pkFile = primaryKey.getClassFile(buildDir); - modified = pkFile.lastModified(); - if (modified == -1) { - System.out.println("The class " - + primaryKey.getQualifiedClassName() + "couldn't be " - + "found on the classpath"); - return -1; - } - latestModified = Math.max(latestModified, modified); - } else { - pkFile = null; - } - - /* Check the timestamp on the EJB implementation class. - * - * Note that if ONLY the implementation class has changed, it's not - * necessary to rebuild the EJB stubs and skeletons. For this - * reason, we ensure the file exists (using lastModified above), but - * we DON'T compare it's timestamp with the timestamps of the home - * and remote interfaces (because it's irrelevant in determining if - * ejbc must be run) - */ - implFile = implementation.getClassFile(buildDir); - modified = implFile.lastModified(); - if (modified == -1) { - System.out.println("The class " - + implementation.getQualifiedClassName() - + " couldn't be found on the classpath"); - return -1; - } - - String pathToFile = remote.getQualifiedClassName(); - pathToFile = pathToFile.replace('.', File.separatorChar) + ".class"; - ejbFiles.put(pathToFile, remoteFile); - - pathToFile = home.getQualifiedClassName(); - pathToFile = pathToFile.replace('.', File.separatorChar) + ".class"; - ejbFiles.put(pathToFile, homeFile); - - pathToFile = implementation.getQualifiedClassName(); - pathToFile = pathToFile.replace('.', File.separatorChar) + ".class"; - ejbFiles.put(pathToFile, implFile); - - if (pkFile != null) { - pathToFile = primaryKey.getQualifiedClassName(); - pathToFile = pathToFile.replace('.', File.separatorChar) + ".class"; - ejbFiles.put(pathToFile, pkFile); - } - - return latestModified; - } - - /** - * Examines each of the EJB stubs and skeletons in the destination - * directory and returns the modification timestamp for the "oldest" - * class. If one of the stubs or skeletons cannot be found, <code>-1 - * </code> is returned. - * - * @param dest The directory in which the EJB stubs and skeletons are - * stored. - * @return The modification timestamp for the "oldest" EJB stub or - * skeleton. If one of the classes cannot be found, <code>-1 - * </code> is returned. - * @throws BuildException If the canonical path of the destination - * directory cannot be found. - */ - private long destClassesModified(File destDir) { - String[] classnames = classesToGenerate(); // List of all stubs & skels - long destClassesModified = new Date().getTime(); // Earliest mod time - boolean allClassesFound = true; // Has each been found? - - /* - * Loop through each stub/skeleton class that must be generated, and - * determine (if all exist) which file has the most recent timestamp - */ - for (int i = 0; i < classnames.length; i++) { - - String pathToClass = - classnames[i].replace('.', File.separatorChar) + ".class"; - File classFile = new File(destDir, pathToClass); - - /* - * Add each stub/skeleton class to the list of EJB files. Note - * that each class is added even if it doesn't exist now. - */ - ejbFiles.put(pathToClass, classFile); - - allClassesFound = allClassesFound && classFile.exists(); - - if (allClassesFound) { - long fileMod = classFile.lastModified(); - - /* Keep track of the oldest modification timestamp */ - destClassesModified = Math.min(destClassesModified, fileMod); - } - } - - return (allClassesFound) ? destClassesModified : -1; - } - - /** - * Builds an array of class names which represent the stubs and - * skeletons which need to be generated for a given EJB. The class - * names are fully qualified. Nine classes are generated for all EJBs - * while an additional six classes are generated for beans requiring - * RMI/IIOP access. - * - * @return An array of Strings representing the fully-qualified class - * names for the stubs and skeletons to be generated. - */ - private String[] classesToGenerate() { - String[] classnames = (iiop) - ? new String[NUM_CLASSES_WITH_IIOP] - : new String[NUM_CLASSES_WITHOUT_IIOP]; - - final String remotePkg = remote.getPackageName() + "."; - final String remoteClass = remote.getClassName(); - final String homePkg = home.getPackageName() + "."; - final String homeClass = home.getClassName(); - final String implPkg = implementation.getPackageName() + "."; - final String implFullClass = implementation.getQualifiedWithUnderscores(); - int index = 0; - - classnames[index++] = implPkg + "ejb_fac_" + implFullClass; - classnames[index++] = implPkg + "ejb_home_" + implFullClass; - classnames[index++] = implPkg + "ejb_skel_" + implFullClass; - classnames[index++] = remotePkg + "ejb_kcp_skel_" + remoteClass; - classnames[index++] = homePkg + "ejb_kcp_skel_" + homeClass; - classnames[index++] = remotePkg + "ejb_kcp_stub_" + remoteClass; - classnames[index++] = homePkg + "ejb_kcp_stub_" + homeClass; - classnames[index++] = remotePkg + "ejb_stub_" + remoteClass; - classnames[index++] = homePkg + "ejb_stub_" + homeClass; - - if (!iiop) { - return classnames; - } - - classnames[index++] = "org.omg.stub." + remotePkg + "_" - + remoteClass + "_Stub"; - classnames[index++] = "org.omg.stub." + homePkg + "_" - + homeClass + "_Stub"; - classnames[index++] = "org.omg.stub." + remotePkg - + "_ejb_RmiCorbaBridge_" - + remoteClass + "_Tie"; - classnames[index++] = "org.omg.stub." + homePkg - + "_ejb_RmiCorbaBridge_" - + homeClass + "_Tie"; - - classnames[index++] = remotePkg + "ejb_RmiCorbaBridge_" - + remoteClass; - classnames[index++] = homePkg + "ejb_RmiCorbaBridge_" + homeClass; - - return classnames; - } - - /** - * Convenience method which creates a String representation of all the - * instance variables of an EjbInfo object. - * - * @return A String representing the EjbInfo instance. - */ - public String toString() { - String s = "EJB name: " + name - + "\n\r home: " + home - + "\n\r remote: " + remote - + "\n\r impl: " + implementation - + "\n\r primaryKey: " + primaryKey - + "\n\r beantype: " + beantype - + "\n\r cmp: " + cmp - + "\n\r iiop: " + iiop - + "\n\r hasession: " + hasession; - - Iterator i = cmpDescriptors.iterator(); - while (i.hasNext()) { - s += "\n\r CMP Descriptor: " + i.next(); - } - - return s; - } - - } // End of EjbInfo inner class - - /** - * Convenience class used to represent the fully qualified name of a Java - * class. It provides an easy way to retrieve components of the class name - * in a format that is convenient for building iAS stubs and skeletons. - * - */ - private static class Classname { - private String qualifiedName; // Fully qualified name of the Java class - private String packageName; // Name of the package for this class - private String className; // Name of the class without the package - - /** - * This constructor builds an object which represents the name of a Java - * class. - * - * @param qualifiedName String representing the fully qualified class - * name of the Java class. - */ - public Classname(String qualifiedName) { - if (qualifiedName == null) { - return; - } - - this.qualifiedName = qualifiedName; - - int index = qualifiedName.lastIndexOf('.'); - if (index == -1) { - className = qualifiedName; - packageName = ""; - } else { - packageName = qualifiedName.substring(0, index); - className = qualifiedName.substring(index + 1); - } - } - - /** - * Gets the fully qualified name of the Java class. - * - * @return String representing the fully qualified class name. - */ - public String getQualifiedClassName() { - return qualifiedName; - } - - /** - * Gets the package name for the Java class. - * - * @return String representing the package name for the class. - */ - public String getPackageName() { - return packageName; - } - - /** - * Gets the Java class name without the package structure. - * - * @return String representing the name for the class. - */ - public String getClassName() { - return className; - } - - /** - * Gets the fully qualified name of the Java class with underscores - * separating the components of the class name rather than periods. - * This format is used in naming some of the stub and skeleton classes - * for the iPlanet Application Server. - * - * @return String representing the fully qualified class name using - * underscores instead of periods. - */ - public String getQualifiedWithUnderscores() { - return qualifiedName.replace('.', '_'); - } - - /** - * Returns a File which references the class relative to the specified - * directory. Note that the class file may or may not exist. - * - * @param directory A File referencing the base directory containing - * class files. - * @return File referencing this class. - */ - public File getClassFile(File directory) { - String pathToFile = qualifiedName.replace('.', File.separatorChar) - + ".class"; - return new File(directory, pathToFile); - } - - /** - * String representation of this class name. It returns the fully - * qualified class name. - * - * @return String representing the fully qualified class name. - */ - public String toString() { - return getQualifiedClassName(); - } - } // End of Classname inner class - - - /** - * Thread class used to redirect output from an <code>InputStream</code> to - * the JRE standard output. This class may be used to redirect output from - * an external process to the standard output. - * - */ - private static class RedirectOutput extends Thread { - - private InputStream stream; // Stream to read and redirect to standard output - - /** - * Constructs a new instance that will redirect output from the - * specified stream to the standard output. - * - * @param stream InputStream which will be read and redirected to the - * standard output. - */ - public RedirectOutput(InputStream stream) { - this.stream = stream; - } - - /** - * Reads text from the input stream and redirects it to standard output - * using a separate thread. - */ - public void run() { - BufferedReader reader = new BufferedReader( - new InputStreamReader(stream)); - String text; - try { - while ((text = reader.readLine()) != null) { - System.out.println(text); - } - } catch (IOException e) { - e.printStackTrace(); - } finally { - try { - reader.close(); - } catch (IOException e) { - // Do nothing - } - } - } - } // End of RedirectOutput inner class - -} |