tool classes.
Split the Descriptor handler to a separate class
Allow local DTDs to be loaded to resolve the external entities
Moved all Weblogic specific code into a separate deployment tool object.
Usage for generic jars is now
<ejbjar srcdir="${descriptor.dir}" destdir="${deploymentjar.dir}">
<include name="**/*-ejb-jar.xml"/>
</ejbjar>
For a weblogic deployment you now add a nested element with the weblogic specific
configs
<ejbjar srcdir="${descriptor.dir}">
<weblogic destdir="${deploymentjar.dir}"
classpath="${descriptorbuild.classpath}"
keepgeneric="false"
suffix=".jar"/>
<include name="**/*-ejb-jar.xml"/>
<exclude name="**/*-weblogic-ejb-jar.xml"/>
</ejbjar>
git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@267868 13f79535-47bb-0310-9956-ffa450edef68
master
| @@ -0,0 +1,239 @@ | |||
| /* | |||
| * The Apache Software License, Version 1.1 | |||
| * | |||
| * Copyright (c) 2000 The Apache Software Foundation. All rights | |||
| * reserved. | |||
| * | |||
| * Redistribution and use in source and binary forms, with or without | |||
| * modification, are permitted provided that the following conditions | |||
| * are met: | |||
| * | |||
| * 1. Redistributions of source code must retain the above copyright | |||
| * notice, this list of conditions and the following disclaimer. | |||
| * | |||
| * 2. Redistributions in binary form must reproduce the above copyright | |||
| * notice, this list of conditions and the following disclaimer in | |||
| * the documentation and/or other materials provided with the | |||
| * distribution. | |||
| * | |||
| * 3. The end-user documentation included with the redistribution, if | |||
| * any, must include the following acknowlegement: | |||
| * "This product includes software developed by the | |||
| * Apache Software Foundation (http://www.apache.org/)." | |||
| * Alternately, this acknowlegement may appear in the software itself, | |||
| * if and wherever such third-party acknowlegements normally appear. | |||
| * | |||
| * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software | |||
| * Foundation" must not be used to endorse or promote products derived | |||
| * from this software without prior written permission. For written | |||
| * permission, please contact apache@apache.org. | |||
| * | |||
| * 5. Products derived from this software may not be called "Apache" | |||
| * nor may "Apache" appear in their names without prior written | |||
| * permission of the Apache Group. | |||
| * | |||
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED | |||
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||
| * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR | |||
| * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |||
| * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |||
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |||
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
| * SUCH DAMAGE. | |||
| * ==================================================================== | |||
| * | |||
| * This software consists of voluntary contributions made by many | |||
| * individuals on behalf of the Apache Software Foundation. For more | |||
| * information on the Apache Software Foundation, please see | |||
| * <http://www.apache.org/>. | |||
| */ | |||
| package org.apache.tools.ant.taskdefs.optional.ejb; | |||
| import java.util.*; | |||
| import java.io.*; | |||
| import org.xml.sax.InputSource; | |||
| import org.xml.sax.SAXException; | |||
| import org.xml.sax.AttributeList; | |||
| /** | |||
| * Inner class used by EjbJar to facilitate the parsing of deployment | |||
| * descriptors and the capture of appropriate information. Extends | |||
| * HandlerBase so it only implements the methods needed. During parsing | |||
| * creates a hashtable consisting of entries mapping the name it should be | |||
| * inserted into an EJB jar as to a File representing the file on disk. This | |||
| * list can then be accessed through the getFiles() method. | |||
| */ | |||
| public class DescriptorHandler extends org.xml.sax.HandlerBase { | |||
| /** | |||
| * Bunch of constants used for storing entries in a hashtable, and for | |||
| * constructing the filenames of various parts of the ejb jar. | |||
| */ | |||
| private static final String HOME_INTERFACE = "home"; | |||
| private static final String REMOTE_INTERFACE = "remote"; | |||
| private static final String BEAN_CLASS = "ejb-class"; | |||
| private static final String PK_CLASS = "prim-key-class"; | |||
| /** | |||
| * Instance variable used to store the name of the current element being | |||
| * processed by the SAX parser. Accessed by the SAX parser call-back methods | |||
| * startElement() and endElement(). | |||
| */ | |||
| private String currentElement = null; | |||
| /** | |||
| * The text of the current element | |||
| */ | |||
| private String currentText = null; | |||
| /** | |||
| * Instance variable that stores the names of the files as they will be | |||
| * put into the jar file, mapped to File objects Accessed by the SAX | |||
| * parser call-back method characters(). | |||
| */ | |||
| private Hashtable ejbFiles = null; | |||
| private Hashtable fileDTDs = new Hashtable(); | |||
| private Hashtable resourceDTDs = new Hashtable(); | |||
| /** | |||
| * The directory containing the bean classes and interfaces. This is | |||
| * used for performing dependency file lookups. | |||
| */ | |||
| private File srcDir; | |||
| public DescriptorHandler(File srcDir) { | |||
| this.srcDir = srcDir; | |||
| } | |||
| public void registerFileDTD(String publicId, File dtdFile) { | |||
| fileDTDs.put(publicId, dtdFile); | |||
| } | |||
| public void registerResourceDTD(String publicId, String resourceName) { | |||
| resourceDTDs.put(publicId, resourceName); | |||
| } | |||
| public InputSource resolveEntity(String publicId, String systemId) | |||
| throws SAXException | |||
| { | |||
| File dtdFile = (File) fileDTDs.get(publicId); | |||
| if (dtdFile != null && dtdFile.exists()) { | |||
| try { | |||
| return new InputSource(new FileInputStream(dtdFile)); | |||
| } catch( FileNotFoundException ex ) { | |||
| // ignore | |||
| } | |||
| } | |||
| String dtdResourceName = (String)resourceDTDs.get(publicId); | |||
| if (dtdResourceName != null) { | |||
| InputStream is = this.getClass().getResourceAsStream(dtdResourceName); | |||
| if( is != null ) { | |||
| return new InputSource(is); | |||
| } | |||
| } | |||
| return null; | |||
| } | |||
| /** | |||
| * Getter method that returns the set of files to include in the EJB jar. | |||
| */ | |||
| public Hashtable getFiles() { | |||
| return (ejbFiles == null) ? new Hashtable() : ejbFiles; | |||
| } | |||
| /** | |||
| * SAX parser call-back method that is used to initialize the values of some | |||
| * instance variables to ensure safe operation. | |||
| */ | |||
| public void startDocument() throws SAXException { | |||
| this.ejbFiles = new Hashtable(10, 1); | |||
| this.currentElement = null; | |||
| } | |||
| /** | |||
| * SAX parser call-back method that is invoked when a new element is entered | |||
| * into. Used to store the context (attribute name) in the currentAttribute | |||
| * instance variable. | |||
| * @param name The name of the element being entered. | |||
| * @param attrs Attributes associated to the element. | |||
| */ | |||
| public void startElement(String name, AttributeList attrs) | |||
| throws SAXException { | |||
| this.currentElement = name; | |||
| currentText = ""; | |||
| } | |||
| /** | |||
| * SAX parser call-back method that is invoked when an element is exited. | |||
| * Used to blank out (set to the empty string, not nullify) the name of | |||
| * the currentAttribute. A better method would be to use a stack as an | |||
| * instance variable, however since we are only interested in leaf-node | |||
| * data this is a simpler and workable solution. | |||
| * @param name The name of the attribute being exited. Ignored | |||
| * in this implementation. | |||
| */ | |||
| public void endElement(String name) throws SAXException { | |||
| processElement(); | |||
| currentText = ""; | |||
| this.currentElement = ""; | |||
| } | |||
| /** | |||
| * SAX parser call-back method invoked whenever characters are located within | |||
| * an element. currentAttribute (modified by startElement and endElement) | |||
| * tells us whether we are in an interesting element (one of the up to four | |||
| * classes of an EJB). If so then converts the classname from the format | |||
| * org.apache.tools.ant.Parser to the convention for storing such a class, | |||
| * org/apache/tools/ant/Parser.class. This is then resolved into a file | |||
| * object under the srcdir which is stored in a Hashtable. | |||
| * @param ch A character array containing all the characters in | |||
| * the element, and maybe others that should be ignored. | |||
| * @param start An integer marking the position in the char | |||
| * array to start reading from. | |||
| * @param length An integer representing an offset into the | |||
| * char array where the current data terminates. | |||
| */ | |||
| public void characters(char[] ch, int start, int length) | |||
| throws SAXException { | |||
| currentText += new String(ch, start, length); | |||
| } | |||
| private void processElement() { | |||
| if (currentElement.equals(HOME_INTERFACE) || | |||
| currentElement.equals(REMOTE_INTERFACE) || | |||
| currentElement.equals(BEAN_CLASS) || | |||
| currentElement.equals(PK_CLASS)) { | |||
| // Get the filename into a String object | |||
| File classFile = null; | |||
| String className = currentText; | |||
| // If it's a primitive wrapper then we shouldn't try and put | |||
| // it into the jar, so ignore it. | |||
| if (!className.startsWith("java.lang")) { | |||
| // Translate periods into path separators, add .class to the | |||
| // name, create the File object and add it to the Hashtable. | |||
| className = className.replace('.', File.separatorChar); | |||
| className += ".class"; | |||
| classFile = new File(srcDir, className); | |||
| ejbFiles.put(className, classFile); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,90 @@ | |||
| /* | |||
| * The Apache Software License, Version 1.1 | |||
| * | |||
| * Copyright (c) 2000 The Apache Software Foundation. All rights | |||
| * reserved. | |||
| * | |||
| * Redistribution and use in source and binary forms, with or without | |||
| * modification, are permitted provided that the following conditions | |||
| * are met: | |||
| * | |||
| * 1. Redistributions of source code must retain the above copyright | |||
| * notice, this list of conditions and the following disclaimer. | |||
| * | |||
| * 2. Redistributions in binary form must reproduce the above copyright | |||
| * notice, this list of conditions and the following disclaimer in | |||
| * the documentation and/or other materials provided with the | |||
| * distribution. | |||
| * | |||
| * 3. The end-user documentation included with the redistribution, if | |||
| * any, must include the following acknowlegement: | |||
| * "This product includes software developed by the | |||
| * Apache Software Foundation (http://www.apache.org/)." | |||
| * Alternately, this acknowlegement may appear in the software itself, | |||
| * if and wherever such third-party acknowlegements normally appear. | |||
| * | |||
| * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software | |||
| * Foundation" must not be used to endorse or promote products derived | |||
| * from this software without prior written permission. For written | |||
| * permission, please contact apache@apache.org. | |||
| * | |||
| * 5. Products derived from this software may not be called "Apache" | |||
| * nor may "Apache" appear in their names without prior written | |||
| * permission of the Apache Group. | |||
| * | |||
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED | |||
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||
| * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR | |||
| * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |||
| * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |||
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |||
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
| * SUCH DAMAGE. | |||
| * ==================================================================== | |||
| * | |||
| * This software consists of voluntary contributions made by many | |||
| * individuals on behalf of the Apache Software Foundation. For more | |||
| * information on the Apache Software Foundation, please see | |||
| * <http://www.apache.org/>. | |||
| */ | |||
| package org.apache.tools.ant.taskdefs.optional.ejb; | |||
| import java.io.*; | |||
| import javax.xml.parsers.SAXParser; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.Task; | |||
| public interface EJBDeploymentTool { | |||
| /** | |||
| * Process a deployment descriptor, generating the necessary vendor specifi | |||
| * deployment files. | |||
| * | |||
| * @param descriptorFilename the name of the deployment descriptor | |||
| * @param saxParser a SAX parser which can be used to parse the deployment descriptor. | |||
| */ | |||
| public void processDescriptor(File srcDir, String descriptorFilename, SAXParser saxParser) | |||
| throws BuildException; | |||
| /** | |||
| * Called to validate that the tool parameters have been configured. | |||
| * | |||
| */ | |||
| public void validateConfigured() throws BuildException; | |||
| /** | |||
| * Set the task which owns this tool | |||
| */ | |||
| public void setTask(Task task); | |||
| /** | |||
| * Configure this tool for use in the ejbjar task. | |||
| */ | |||
| public void configure(String basenameTerminator, boolean flatDestDir); | |||
| } | |||
| @@ -1,7 +1,7 @@ | |||
| /* | |||
| * The Apache Software License, Version 1.1 | |||
| * | |||
| * Copyright (c) 1999 The Apache Software Foundation. All rights | |||
| * Copyright (c) 2000 The Apache Software Foundation. All rights | |||
| * reserved. | |||
| * | |||
| * Redistribution and use in source and binary forms, with or without | |||
| @@ -55,37 +55,20 @@ | |||
| package org.apache.tools.ant.taskdefs.optional.ejb; | |||
| // Standard java imports | |||
| import java.io.FileInputStream; | |||
| import java.io.FileOutputStream; | |||
| import java.io.PrintWriter; | |||
| import java.io.File; | |||
| import java.io.IOException; | |||
| import java.util.jar.*; | |||
| import java.util.zip.*; | |||
| import java.util.ArrayList; | |||
| import java.util.Hashtable; | |||
| import java.util.Iterator; | |||
| import java.io.*; | |||
| import java.util.*; | |||
| // XML imports | |||
| import javax.xml.parsers.SAXParser; | |||
| import javax.xml.parsers.SAXParserFactory; | |||
| import javax.xml.parsers.ParserConfigurationException; | |||
| import org.xml.sax.Parser; | |||
| import org.xml.sax.Locator; | |||
| import org.xml.sax.InputSource; | |||
| import org.xml.sax.AttributeList; | |||
| import org.xml.sax.DocumentHandler; | |||
| import org.xml.sax.SAXException; | |||
| import org.xml.sax.SAXParseException; | |||
| import org.xml.sax.helpers.ParserFactory; | |||
| // Apache/Ant imports | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.Task; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.DirectoryScanner; | |||
| import org.apache.tools.ant.taskdefs.MatchingTask; | |||
| import org.apache.tools.ant.taskdefs.Java; | |||
| /** | |||
| * <p>Provides automated ejb jar file creation for ant. Extends the MatchingTask | |||
| @@ -104,146 +87,21 @@ import org.apache.tools.ant.taskdefs.Java; | |||
| * 5.1 jars. The weblogic deployment descriptors, used in constructing the | |||
| * Weblogic jar, are located based on a simple naming convention. The name of the | |||
| * standard deployment descriptor is taken upto the first instance of a String, | |||
| * specified by the attribute basenameterminator, and then the regular Weblogic | |||
| * descriptor name is appended. For example if basenameterminator is set to '-', | |||
| * specified by the attribute basenameTerminator, and then the regular Weblogic | |||
| * descriptor name is appended. For example if basenameTerminator is set to '-', | |||
| * its default value, and a standard descriptor is called Foo-ejb-jar.xml then | |||
| * the files Foo-weblogic-ejb-jar.xml and Foo-weblogic-cmp-rdbms-jar.xml will be | |||
| * looked for, and if found, included in the jarfile.</p> | |||
| * | |||
| * <p>Attributes and setter methods are provided to support optional generation | |||
| * of Weblogic5.1 jars, optional deletion of generic jar files, setting alternate | |||
| * values for basenameterminator, and setting the strings to append to the names | |||
| * values for basenameTerminator, and setting the strings to append to the names | |||
| * of the generated jarfiles.</p> | |||
| * | |||
| * @author <a href="mailto:tfennell@sapient.com">Tim Fennell</a> | |||
| */ | |||
| public class EjbJar extends MatchingTask { | |||
| /** | |||
| * Inner class used by EjbJar to facilitate the parsing of deployment | |||
| * descriptors and the capture of appropriate information. Extends | |||
| * HandlerBase so it only implements the methods needed. During parsing | |||
| * creates a hashtable consisting of entries mapping the name it should be | |||
| * inserted into an EJB jar as to a File representing the file on disk. This | |||
| * list can then be accessed through the getFiles() method. | |||
| */ | |||
| protected class DescriptorHandler extends org.xml.sax.HandlerBase { | |||
| /** | |||
| * Bunch of constants used for storing entries in a hashtable, and for | |||
| * constructing the filenames of various parts of the ejb jar. | |||
| */ | |||
| private static final String HOME_INTERFACE = "home"; | |||
| private static final String REMOTE_INTERFACE = "remote"; | |||
| private static final String BEAN_CLASS = "ejb-class"; | |||
| private static final String PK_CLASS = "prim-key-class"; | |||
| /** | |||
| * Instance variable used to store the name of the current attribute being | |||
| * processed by the SAX parser. Accessed by the SAX parser call-back methods | |||
| * startElement() and endElement(). | |||
| */ | |||
| private String currentAttribute = null; | |||
| /** | |||
| * Instance variable that stores the names of the files as they will be | |||
| * put into the jar file, mapped to File objects Accessed by the SAX | |||
| * parser call-back method characters(). | |||
| */ | |||
| private Hashtable ejbFiles = null; | |||
| /** Instance variable to store the source directory of the task */ | |||
| /** | |||
| * Getter method that returns the set of files to include in the EJB jar. | |||
| */ | |||
| public Hashtable getFiles() { | |||
| return (ejbFiles == null) ? new Hashtable() : ejbFiles; | |||
| } | |||
| /** | |||
| * SAX parser call-back method that is used to initialize the values of some | |||
| * instance variables to ensure safe operation. | |||
| */ | |||
| public void startDocument() throws SAXException { | |||
| this.ejbFiles = new Hashtable(10, 1); | |||
| this.currentAttribute = null; | |||
| } | |||
| /** | |||
| * SAX parser call-back method that is invoked when a new element is entered | |||
| * into. Used to store the context (attribute name) in the currentAttribute | |||
| * instance variable. | |||
| * @param name The name of the element being entered. | |||
| * @param attrs Attributes associated to the element. | |||
| */ | |||
| public void startElement(String name, AttributeList attrs) | |||
| throws SAXException { | |||
| this.currentAttribute = name; | |||
| } | |||
| /** | |||
| * SAX parser call-back method that is invoked when an element is exited. | |||
| * Used to blank out (set to the empty string, not nullify) the name of | |||
| * the currentAttribute. A better method would be to use a stack as an | |||
| * instance variable, however since we are only interested in leaf-node | |||
| * data this is a simpler and workable solution. | |||
| * @param name The name of the attribute being exited. Ignored | |||
| * in this implementation. | |||
| */ | |||
| public void endElement(String name) throws SAXException { | |||
| this.currentAttribute = ""; | |||
| } | |||
| /** | |||
| * SAX parser call-back method invoked whenever characters are located within | |||
| * an element. currentAttribute (modified by startElement and endElement) | |||
| * tells us whether we are in an interesting element (one of the up to four | |||
| * classes of an EJB). If so then converts the classname from the format | |||
| * org.apache.tools.ant.Parser to the convention for storing such a class, | |||
| * org/apache/tools/ant/Parser.class. This is then resolved into a file | |||
| * object under the srcdir which is stored in a Hashtable. | |||
| * @param ch A character array containing all the characters in | |||
| * the element, and maybe others that should be ignored. | |||
| * @param start An integer marking the position in the char | |||
| * array to start reading from. | |||
| * @param length An integer representing an offset into the | |||
| * char array where the current data terminates. | |||
| */ | |||
| public void characters(char[] ch, int start, int length) | |||
| throws SAXException { | |||
| if (currentAttribute.equals(DescriptorHandler.HOME_INTERFACE) || | |||
| currentAttribute.equals(DescriptorHandler.REMOTE_INTERFACE) || | |||
| currentAttribute.equals(DescriptorHandler.BEAN_CLASS) || | |||
| currentAttribute.equals(DescriptorHandler.PK_CLASS)) { | |||
| // Get the filename into a String object | |||
| File classFile = null; | |||
| String className = new String(ch, start, length); | |||
| // If it's a primitive wrapper then we shouldn't try and put | |||
| // it into the jar, so ignore it. | |||
| if (!className.startsWith("java.lang")) { | |||
| // Translate periods into path separators, add .class to the | |||
| // name, create the File object and add it to the Hashtable. | |||
| className = className.replace('.', File.separatorChar); | |||
| className += ".class"; | |||
| classFile = new File(srcdir, className); | |||
| ejbFiles.put(className, classFile); | |||
| } | |||
| } | |||
| } | |||
| } // End of DescriptorHandler | |||
| /** Private constants that are used when constructing the standard jarfile */ | |||
| private static final String META_DIR = "META-INF/"; | |||
| private static final String EJB_DD = "ejb-jar.xml"; | |||
| private static final String WL_DD = "weblogic-ejb-jar.xml"; | |||
| private static final String WL_CMP_DD = "weblogic-cmp-rdbms-jar.xml"; | |||
| /** Stores a handle to the directory under which to search for files */ | |||
| private File srcdir = null; | |||
| @@ -255,47 +113,50 @@ public class EjbJar extends MatchingTask { | |||
| * of a flat directory as the destination for the jar files. | |||
| */ | |||
| private boolean flatdestdir = false; | |||
| /** Instance variable that determines whether to generate weblogic jars. */ | |||
| private boolean generateweblogic = false; | |||
| /** Instance variable that determines whether generic ejb jars are kept. */ | |||
| private boolean keepgeneric = true; | |||
| /** Instance variable that marks the end of the 'basename' */ | |||
| private String basenameterminator = "-"; | |||
| private String basenameTerminator = "-"; | |||
| /** Instance variable that stores the suffix for the generated jarfile. */ | |||
| private String genericjarsuffix = "-generic.jar"; | |||
| /** Instance variable that stores the suffix for the weblogic jarfile. */ | |||
| private String weblogicjarsuffix = "-wl.jar"; | |||
| /** | |||
| * The list of deployment tools we are going to run. | |||
| */ | |||
| private ArrayList deploymentTools = new ArrayList(); | |||
| public EJBDeploymentTool createWeblogic() { | |||
| EJBDeploymentTool tool = new WeblogicDeploymentTool(); | |||
| tool.setTask(this); | |||
| deploymentTools.add(tool); | |||
| return tool; | |||
| } | |||
| /** | |||
| * Setter used to store the value of srcdir prior to execute() being called. | |||
| * @param inDir The string indicating the source directory. | |||
| * @param inDir the source directory. | |||
| */ | |||
| public void setSrcdir(String inDir) { | |||
| this.srcdir = this.project.resolveFile(inDir); | |||
| public void setSrcdir(File inDir) { | |||
| this.srcdir = inDir; | |||
| } | |||
| /** | |||
| * Setter used to store the value of destination directory prior to execute() | |||
| * being called. | |||
| * @param inFile The string indicating the source directory. | |||
| * @param inFile the destination directory. | |||
| */ | |||
| public void setDestdir(String inDir) { | |||
| this.destdir = this.project.resolveFile(inDir); | |||
| public void setDestdir(File inDir) { | |||
| this.destdir = inDir; | |||
| } | |||
| /** | |||
| * Setter used to store the value of flatdestdir. | |||
| * @param inValue a string, either 'true' or 'false'. | |||
| */ | |||
| public void setFlatdestdir(String inValue) { | |||
| this.flatdestdir = Boolean.valueOf(inValue).booleanValue(); | |||
| public void setFlatdestdir(boolean inValue) { | |||
| this.flatdestdir = inValue; | |||
| } | |||
| /** | |||
| * Setter used to store the suffix for the generated jar file. | |||
| * @param inString the string to use as the suffix. | |||
| @@ -305,164 +166,13 @@ public class EjbJar extends MatchingTask { | |||
| } | |||
| /** | |||
| * Setter used to store the suffix for the generated weblogic jar file. | |||
| * @param inString the string to use as the suffix. | |||
| */ | |||
| public void setWeblogicjarsuffix(String inString) { | |||
| this.weblogicjarsuffix = inString; | |||
| } | |||
| /** | |||
| * Setter used to store the value of generateweblogic. | |||
| * @param inValue a string, either 'true' or 'false'. | |||
| */ | |||
| public void setGenerateweblogic(String inValue) { | |||
| this.generateweblogic = Boolean.valueOf(inValue).booleanValue(); | |||
| } | |||
| /** | |||
| * Setter used to store the value of keepgeneric | |||
| * @param inValue a string, either 'true' or 'false'. | |||
| */ | |||
| public void setKeepgeneric(String inValue) { | |||
| this.keepgeneric = Boolean.valueOf(inValue).booleanValue(); | |||
| } | |||
| /** | |||
| * Setter used to store the value of basenameterminator | |||
| * Setter used to store the value of basenameTerminator | |||
| * @param inValue a string which marks the end of the basename. | |||
| */ | |||
| public void setBasenameterminator(String inValue) { | |||
| if (inValue != null) this.basenameterminator = inValue; | |||
| } | |||
| /** | |||
| * Utility method that encapsulates the logic of adding a file entry to | |||
| * a .jar file. Used by execute() to add entries to the jar file as it is | |||
| * constructed. | |||
| * @param jStream A JarOutputStream into which to write the | |||
| * jar entry. | |||
| * @param iStream A FileInputStream from which to read the | |||
| * contents the file being added. | |||
| * @param filename A String representing the name, including | |||
| * all relevant path information, that should be stored for the entry | |||
| * being added. | |||
| */ | |||
| protected void addFileToJar(JarOutputStream jStream, | |||
| FileInputStream iStream, | |||
| String filename) | |||
| throws BuildException { | |||
| try { | |||
| // Create the zip entry and add it to the jar file | |||
| ZipEntry zipEntry = new ZipEntry(filename); | |||
| jStream.putNextEntry(zipEntry); | |||
| // Create the file input stream, and buffer everything over | |||
| // to the jar output stream | |||
| byte[] byteBuffer = new byte[2 * 1024]; | |||
| int count = 0; | |||
| do { | |||
| jStream.write(byteBuffer, 0, count); | |||
| count = iStream.read(byteBuffer, 0, byteBuffer.length); | |||
| } while (count != -1); | |||
| // Close up the file input stream for the class file | |||
| iStream.close(); | |||
| } | |||
| catch (IOException ioe) { | |||
| String msg = "IOException while adding entry " | |||
| + filename + "to jarfile." | |||
| + ioe.getMessage(); | |||
| throw new BuildException(msg, ioe); | |||
| } | |||
| } | |||
| /** | |||
| * Method used to encapsulate the writing of the JAR file. Iterates over the | |||
| * filenames/java.io.Files in the Hashtable stored on the instance variable | |||
| * ejbFiles. | |||
| */ | |||
| public void writeJar(File jarfile, Hashtable files) throws BuildException{ | |||
| JarOutputStream jarStream = null; | |||
| Iterator entryIterator = null; | |||
| String entryName = null; | |||
| File entryFile = null; | |||
| try { | |||
| /* If the jarfile already exists then whack it and recreate it. | |||
| * Should probably think of a more elegant way to handle this | |||
| * so that in case of errors we don't leave people worse off | |||
| * than when we started =) | |||
| */ | |||
| if (jarfile.exists()) jarfile.delete(); | |||
| jarfile.getParentFile().mkdirs(); | |||
| jarfile.createNewFile(); | |||
| // Create the streams necessary to write the jarfile | |||
| jarStream = new JarOutputStream(new FileOutputStream(jarfile)); | |||
| jarStream.setMethod(JarOutputStream.DEFLATED); | |||
| // Loop through all the class files found and add them to the jar | |||
| entryIterator = files.keySet().iterator(); | |||
| while (entryIterator.hasNext()) { | |||
| entryName = (String) entryIterator.next(); | |||
| entryFile = (File) files.get(entryName); | |||
| this.log("adding file '" + entryName + "'", | |||
| Project.MSG_VERBOSE); | |||
| addFileToJar(jarStream, | |||
| new FileInputStream(entryFile), | |||
| entryName); | |||
| } | |||
| // All done. Close the jar stream. | |||
| jarStream.close(); | |||
| } | |||
| catch(IOException ioe) { | |||
| String msg = "IOException while processing ejb-jar file '" | |||
| + jarfile.toString() | |||
| + "'. Details: " | |||
| + ioe.getMessage(); | |||
| throw new BuildException(msg, ioe); | |||
| } | |||
| } // end of writeJar | |||
| /** | |||
| * Helper method invoked by execute() for each WebLogic jar to be built. | |||
| * Encapsulates the logic of constructing a java task for calling | |||
| * weblogic.ejbc and executing it. | |||
| * @param sourceJar java.io.File representing the source (EJB1.1) jarfile. | |||
| * @param destJar java.io.File representing the destination, WebLogic | |||
| * jarfile. | |||
| */ | |||
| public void buildWeblogicJar(File sourceJar, File destJar) { | |||
| org.apache.tools.ant.taskdefs.Java javaTask = null; | |||
| try { | |||
| // Unfortunately, because weblogic.ejbc calls system.exit(), we | |||
| // cannot do it 'in-process'. If they ever fix this, we should | |||
| // change this code - it would be much quicker! | |||
| String args = "-noexit " + sourceJar + " " + destJar; | |||
| javaTask = (Java) this.project.createTask("java"); | |||
| javaTask.setClassname("weblogic.ejbc"); | |||
| javaTask.setArgs(args); | |||
| javaTask.setFork(false); | |||
| this.log("Calling weblogic.ejbc for " + sourceJar.toString(), | |||
| Project.MSG_INFO); | |||
| javaTask.execute(); | |||
| } | |||
| catch (Exception e) { | |||
| // Have to catch this because of the semantics of calling main() | |||
| String msg = "Exception while calling ejbc. Details: " + e.toString(); | |||
| throw new BuildException(msg, e); | |||
| } | |||
| public void setBasenameTerminator(String inValue) { | |||
| if (inValue != null) this.basenameTerminator = inValue; | |||
| } | |||
| /** | |||
| * Invoked by Ant after the task is prepared, when it is ready to execute | |||
| * this task. Parses the XML deployment descriptor to acquire the list of | |||
| @@ -475,173 +185,51 @@ public class EjbJar extends MatchingTask { | |||
| * that a major problem occurred within this task. | |||
| */ | |||
| public void execute() throws BuildException { | |||
| boolean needBuild = true; | |||
| DirectoryScanner ds = null; | |||
| String[] files = null; | |||
| int index = 0; | |||
| File weblogicDD = null; | |||
| File jarfile = null; | |||
| File wlJarfile = null; | |||
| File jarToCheck = null; | |||
| DescriptorHandler handler = null; | |||
| Hashtable ejbFiles = null; | |||
| String baseName = null; | |||
| // Lets do a little asserting to make sure we have all the | |||
| // required attributes from the task processor | |||
| StringBuffer sb = new StringBuffer(); | |||
| boolean die = false; | |||
| sb.append("Processing ejbjar - the following attributes "); | |||
| sb.append("must be specified: "); | |||
| if (this.srcdir == null) { sb.append("srcdir "); die = true; } | |||
| if (this.destdir == null) { sb.append("destdir"); die = true; } | |||
| if ( die ) throw new BuildException(sb.toString()); | |||
| if (srcdir == null) { | |||
| throw new BuildException("The srcdir attribute must be specified"); | |||
| } | |||
| if (deploymentTools.size() == 0) { | |||
| GenericDeploymentTool genericTool = new GenericDeploymentTool(); | |||
| genericTool.setDestdir(destdir); | |||
| genericTool.setTask(this); | |||
| genericTool.setGenericjarsuffix(genericjarsuffix); | |||
| deploymentTools.add(genericTool); | |||
| } | |||
| for (Iterator i = deploymentTools.iterator(); i.hasNext(); ) { | |||
| EJBDeploymentTool tool = (EJBDeploymentTool)i.next(); | |||
| tool.configure(basenameTerminator, flatdestdir); | |||
| tool.validateConfigured(); | |||
| } | |||
| try { | |||
| // Create the parser using whatever parser the system dictates | |||
| SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); | |||
| saxParserFactory.setValidating(false); | |||
| saxParserFactory.setValidating(true); | |||
| SAXParser saxParser = saxParserFactory.newSAXParser(); | |||
| ds = this.getDirectoryScanner(this.srcdir); | |||
| DirectoryScanner ds = getDirectoryScanner(srcdir); | |||
| ds.scan(); | |||
| files = ds.getIncludedFiles(); | |||
| this.log(files.length + " deployment descriptors located.", | |||
| Project.MSG_VERBOSE); | |||
| String[] files = ds.getIncludedFiles(); | |||
| log(files.length + " deployment descriptors located.", | |||
| Project.MSG_VERBOSE); | |||
| // Loop through the files. Each file represents one deployment | |||
| // descriptor, and hence one bean in our model. | |||
| for (index=0; index < files.length; ++index) { | |||
| // By default we assume we need to build. | |||
| needBuild = true; | |||
| // Work out what the base name is | |||
| int endBaseName = | |||
| files[index].indexOf(basenameterminator, | |||
| files[index].lastIndexOf(File.separator)); | |||
| baseName = files[index].substring(0, endBaseName); | |||
| /* Parse the ejb deployment descriptor. While it may not | |||
| * look like much, we use a SAXParser and an inner class to | |||
| * get hold of all the classfile names for the descriptor. | |||
| */ | |||
| handler = new DescriptorHandler(); | |||
| saxParser.parse(new InputSource | |||
| (new FileInputStream | |||
| (new File(this.srcdir, files[index]))), | |||
| handler); | |||
| ejbFiles = handler.getFiles(); | |||
| /* Now try to locate all of the deployment descriptors for the | |||
| * jar, and if they exist, add them to the list of files. | |||
| */ | |||
| // First the regular deployment descriptor | |||
| ejbFiles.put(EjbJar.META_DIR + EjbJar.EJB_DD, | |||
| new File(this.srcdir, files[index])); | |||
| // Then the weblogic deployment descriptor | |||
| weblogicDD = new File(this.srcdir, | |||
| baseName | |||
| + this.basenameterminator | |||
| + EjbJar.WL_DD); | |||
| if (weblogicDD.exists()) { | |||
| ejbFiles.put(EjbJar.META_DIR + EjbJar.WL_DD, | |||
| weblogicDD); | |||
| for (int index = 0; index < files.length; ++index) { | |||
| // process the deployment descriptor in each tool | |||
| for (Iterator i = deploymentTools.iterator(); i.hasNext(); ) { | |||
| EJBDeploymentTool tool = (EJBDeploymentTool)i.next(); | |||
| processDescriptor(files[index], saxParser, tool); | |||
| } | |||
| // The the weblogic cmp deployment descriptor | |||
| weblogicDD = new File(this.srcdir, | |||
| baseName | |||
| + this.basenameterminator | |||
| + EjbJar.WL_CMP_DD); | |||
| if (weblogicDD.exists()) { | |||
| ejbFiles.put(EjbJar.META_DIR + EjbJar.WL_CMP_DD, | |||
| weblogicDD); | |||
| } | |||
| // Lastly create File object for the Jar files. If we are using | |||
| // a flat destination dir, then we need to redefine baseName! | |||
| if (this.flatdestdir) { | |||
| int startName = baseName.lastIndexOf(File.separator); | |||
| int endName = baseName.length(); | |||
| baseName = baseName.substring(startName, endName); | |||
| } | |||
| jarfile = new File(this.destdir, | |||
| baseName | |||
| + this.genericjarsuffix); | |||
| wlJarfile = new File(this.destdir, | |||
| baseName | |||
| + this.weblogicjarsuffix); | |||
| /* Check to see if the jar file is already up to date. | |||
| * Unfortunately we have to parse the descriptor just to do | |||
| * that, but it's still a saving over re-constructing the jar | |||
| * file each time. Tertiary is used to determine which jarfile | |||
| * we should check times against...think about it. | |||
| */ | |||
| jarToCheck = this.generateweblogic ? wlJarfile : jarfile; | |||
| if (jarToCheck.exists()) { | |||
| long lastBuild = jarToCheck.lastModified(); | |||
| Iterator fileIter = ejbFiles.values().iterator(); | |||
| File currentFile = null; | |||
| // Set the need build to false until we find out otherwise. | |||
| needBuild = false; | |||
| // Loop through the files seeing if any has been touched | |||
| // more recently than the destination jar. | |||
| while( (needBuild == false) && (fileIter.hasNext()) ) { | |||
| currentFile = (File) fileIter.next(); | |||
| needBuild = ( lastBuild < currentFile.lastModified() ); | |||
| } | |||
| } | |||
| // Check to see if we need a build and start | |||
| // doing the work! | |||
| if (needBuild) { | |||
| // Log that we are going to build... | |||
| this.log( "building " | |||
| + jarfile.getName() | |||
| + " with " | |||
| + String.valueOf(ejbFiles.size()) | |||
| + " total files", | |||
| Project.MSG_INFO); | |||
| // Use helper method to write the jarfile | |||
| this.writeJar(jarfile, ejbFiles); | |||
| // Generate weblogic jar if requested | |||
| if (this.generateweblogic) { | |||
| this.buildWeblogicJar(jarfile, wlJarfile); | |||
| } | |||
| // Delete the original jar if we weren't asked to keep it. | |||
| if (!this.keepgeneric) { | |||
| this.log("deleting jar " + jarfile.toString(), | |||
| Project.MSG_INFO); | |||
| jarfile.delete(); | |||
| } | |||
| } | |||
| else { | |||
| // Log that the file is up to date... | |||
| this.log(jarfile.toString() + " is up to date.", | |||
| Project.MSG_INFO); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| catch (SAXException se) { | |||
| String msg = "SAXException while parsing '" | |||
| + files[index].toString() | |||
| + "'. This probably indicates badly-formed XML." | |||
| String msg = "SAXException while creating parser." | |||
| + " Details: " | |||
| + se.getMessage(); | |||
| throw new BuildException(msg, se); | |||
| @@ -651,15 +239,14 @@ public class EjbJar extends MatchingTask { | |||
| + "Details: " + pce.getMessage(); | |||
| throw new BuildException(msg, pce); | |||
| } | |||
| catch (IOException ioe) { | |||
| String msg = "IOException while parsing'" | |||
| + files[index].toString() | |||
| + "'. This probably indicates that the descriptor" | |||
| + " doesn't exist. Details:" | |||
| + ioe.getMessage(); | |||
| throw new BuildException(msg, ioe); | |||
| } | |||
| } // end of execute() | |||
| private void processDescriptor(String descriptorFilename, SAXParser saxParser, | |||
| EJBDeploymentTool tool) { | |||
| tool.processDescriptor(srcdir, descriptorFilename, saxParser); | |||
| } | |||
| } | |||
| @@ -0,0 +1,377 @@ | |||
| /* | |||
| * The Apache Software License, Version 1.1 | |||
| * | |||
| * Copyright (c) 2000 The Apache Software Foundation. All rights | |||
| * reserved. | |||
| * | |||
| * Redistribution and use in source and binary forms, with or without | |||
| * modification, are permitted provided that the following conditions | |||
| * are met: | |||
| * | |||
| * 1. Redistributions of source code must retain the above copyright | |||
| * notice, this list of conditions and the following disclaimer. | |||
| * | |||
| * 2. Redistributions in binary form must reproduce the above copyright | |||
| * notice, this list of conditions and the following disclaimer in | |||
| * the documentation and/or other materials provided with the | |||
| * distribution. | |||
| * | |||
| * 3. The end-user documentation included with the redistribution, if | |||
| * any, must include the following acknowlegement: | |||
| * "This product includes software developed by the | |||
| * Apache Software Foundation (http://www.apache.org/)." | |||
| * Alternately, this acknowlegement may appear in the software itself, | |||
| * if and wherever such third-party acknowlegements normally appear. | |||
| * | |||
| * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software | |||
| * Foundation" must not be used to endorse or promote products derived | |||
| * from this software without prior written permission. For written | |||
| * permission, please contact apache@apache.org. | |||
| * | |||
| * 5. Products derived from this software may not be called "Apache" | |||
| * nor may "Apache" appear in their names without prior written | |||
| * permission of the Apache Group. | |||
| * | |||
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED | |||
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||
| * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR | |||
| * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |||
| * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |||
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |||
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
| * SUCH DAMAGE. | |||
| * ==================================================================== | |||
| * | |||
| * This software consists of voluntary contributions made by many | |||
| * individuals on behalf of the Apache Software Foundation. For more | |||
| * information on the Apache Software Foundation, please see | |||
| * <http://www.apache.org/>. | |||
| */ | |||
| package org.apache.tools.ant.taskdefs.optional.ejb; | |||
| import java.io.*; | |||
| import java.util.*; | |||
| import java.util.jar.*; | |||
| import java.util.zip.*; | |||
| import javax.xml.parsers.SAXParser; | |||
| import org.xml.sax.InputSource; | |||
| import org.xml.sax.SAXException; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.Task; | |||
| public class GenericDeploymentTool implements EJBDeploymentTool { | |||
| /** Private constants that are used when constructing the standard jarfile */ | |||
| protected static final String META_DIR = "META-INF/"; | |||
| protected static final String EJB_DD = "ejb-jar.xml"; | |||
| /** Stores a handle to the directory to put the Jar files in */ | |||
| private File destDir = null; | |||
| /** | |||
| * Instance variable that determines whether to use a package structure | |||
| * of a flat directory as the destination for the jar files. | |||
| */ | |||
| private boolean flatDestDir = false; | |||
| /** Instance variable that marks the end of the 'basename' */ | |||
| private String basenameTerminator = "-"; | |||
| /** Instance variable that stores the suffix for the generated jarfile. */ | |||
| private String genericjarsuffix = "-generic.jar"; | |||
| /** | |||
| * The task to which this tool belongs. | |||
| */ | |||
| private Task task; | |||
| /** | |||
| * Setter used to store the value of destination directory prior to execute() | |||
| * being called. | |||
| * @param inDir the destination directory. | |||
| */ | |||
| public void setDestdir(File inDir) { | |||
| this.destDir = inDir; | |||
| } | |||
| /** | |||
| * Get the desitination directory. | |||
| */ | |||
| protected File getDestDir() { | |||
| return destDir; | |||
| } | |||
| /** | |||
| * Set the task which owns this tool | |||
| */ | |||
| public void setTask(Task task) { | |||
| this.task = task; | |||
| } | |||
| /** | |||
| * Get the task for this tool. | |||
| */ | |||
| protected Task getTask() { | |||
| return task; | |||
| } | |||
| /** | |||
| * Get the basename terminator. | |||
| */ | |||
| protected String getBasenameTerminator() { | |||
| return basenameTerminator; | |||
| } | |||
| /** | |||
| * Setter used to store the suffix for the generated jar file. | |||
| * @param inString the string to use as the suffix. | |||
| */ | |||
| public void setGenericjarsuffix(String inString) { | |||
| this.genericjarsuffix = inString; | |||
| } | |||
| /** | |||
| * Configure this tool for use in the ejbjar task. | |||
| */ | |||
| public void configure(String basenameTerminator, boolean flatDestDir) { | |||
| this.basenameTerminator = basenameTerminator; | |||
| this.flatDestDir = flatDestDir; | |||
| } | |||
| /** | |||
| * Utility method that encapsulates the logic of adding a file entry to | |||
| * a .jar file. Used by execute() to add entries to the jar file as it is | |||
| * constructed. | |||
| * @param jStream A JarOutputStream into which to write the | |||
| * jar entry. | |||
| * @param iStream A FileInputStream from which to read the | |||
| * contents the file being added. | |||
| * @param filename A String representing the name, including | |||
| * all relevant path information, that should be stored for the entry | |||
| * being added. | |||
| */ | |||
| protected void addFileToJar(JarOutputStream jStream, | |||
| FileInputStream iStream, | |||
| String filename) | |||
| throws BuildException { | |||
| try { | |||
| // Create the zip entry and add it to the jar file | |||
| ZipEntry zipEntry = new ZipEntry(filename); | |||
| jStream.putNextEntry(zipEntry); | |||
| // Create the file input stream, and buffer everything over | |||
| // to the jar output stream | |||
| byte[] byteBuffer = new byte[2 * 1024]; | |||
| int count = 0; | |||
| do { | |||
| jStream.write(byteBuffer, 0, count); | |||
| count = iStream.read(byteBuffer, 0, byteBuffer.length); | |||
| } while (count != -1); | |||
| // Close up the file input stream for the class file | |||
| iStream.close(); | |||
| } | |||
| catch (IOException ioe) { | |||
| String msg = "IOException while adding entry " | |||
| + filename + "to jarfile." | |||
| + ioe.getMessage(); | |||
| throw new BuildException(msg, ioe); | |||
| } | |||
| } | |||
| protected DescriptorHandler getDescriptorHandler(File srcDir) { | |||
| return new DescriptorHandler(srcDir); | |||
| } | |||
| public void processDescriptor(File srcDir, String descriptorFilename, SAXParser saxParser) { | |||
| try { | |||
| DescriptorHandler handler = getDescriptorHandler(srcDir); | |||
| /* Parse the ejb deployment descriptor. While it may not | |||
| * look like much, we use a SAXParser and an inner class to | |||
| * get hold of all the classfile names for the descriptor. | |||
| */ | |||
| saxParser.parse(new InputSource | |||
| (new FileInputStream | |||
| (new File(srcDir, descriptorFilename))), | |||
| handler); | |||
| Hashtable ejbFiles = handler.getFiles(); | |||
| String baseName = ""; | |||
| // Work out what the base name is | |||
| int lastSeparatorIndex = descriptorFilename.lastIndexOf(File.separator); | |||
| int endBaseName = -1; | |||
| if (lastSeparatorIndex != -1) { | |||
| endBaseName = descriptorFilename.indexOf(basenameTerminator, | |||
| lastSeparatorIndex); | |||
| } | |||
| else { | |||
| endBaseName = descriptorFilename.indexOf(basenameTerminator); | |||
| } | |||
| if (endBaseName != -1) { | |||
| baseName = descriptorFilename.substring(0, endBaseName); | |||
| } | |||
| // First the regular deployment descriptor | |||
| ejbFiles.put(META_DIR + EJB_DD, | |||
| new File(srcDir, descriptorFilename)); | |||
| addVendorFiles(ejbFiles, srcDir, baseName); | |||
| // Lastly create File object for the Jar files. If we are using | |||
| // a flat destination dir, then we need to redefine baseName! | |||
| if (flatDestDir && baseName.length() != 0) { | |||
| int startName = baseName.lastIndexOf(File.separator); | |||
| int endName = baseName.length(); | |||
| baseName = baseName.substring(startName, endName); | |||
| } | |||
| File jarFile = getVendorOutputJarFile(baseName); | |||
| // By default we assume we need to build. | |||
| boolean needBuild = true; | |||
| if (jarFile.exists()) { | |||
| long lastBuild = jarFile.lastModified(); | |||
| Iterator fileIter = ejbFiles.values().iterator(); | |||
| // Set the need build to false until we find out otherwise. | |||
| needBuild = false; | |||
| // Loop through the files seeing if any has been touched | |||
| // more recently than the destination jar. | |||
| while( (needBuild == false) && (fileIter.hasNext()) ) { | |||
| File currentFile = (File) fileIter.next(); | |||
| needBuild = ( lastBuild < currentFile.lastModified() ); | |||
| } | |||
| } | |||
| // Check to see if we need a build and start | |||
| // doing the work! | |||
| if (needBuild) { | |||
| // Log that we are going to build... | |||
| getTask().log( "building " | |||
| + jarFile.getName() | |||
| + " with " | |||
| + String.valueOf(ejbFiles.size()) | |||
| + " files", | |||
| Project.MSG_INFO); | |||
| // Use helper method to write the jarfile | |||
| writeJar(baseName, jarFile, ejbFiles); | |||
| } | |||
| else { | |||
| // Log that the file is up to date... | |||
| getTask().log(jarFile.toString() + " is up to date.", | |||
| Project.MSG_INFO); | |||
| } | |||
| } | |||
| catch (SAXException se) { | |||
| String msg = "SAXException while parsing '" | |||
| + descriptorFilename.toString() | |||
| + "'. This probably indicates badly-formed XML." | |||
| + " Details: " | |||
| + se.getMessage(); | |||
| throw new BuildException(msg, se); | |||
| } | |||
| catch (IOException ioe) { | |||
| String msg = "IOException while parsing'" | |||
| + descriptorFilename.toString() | |||
| + "'. This probably indicates that the descriptor" | |||
| + " doesn't exist. Details:" | |||
| + ioe.getMessage(); | |||
| throw new BuildException(msg, ioe); | |||
| } | |||
| } | |||
| /** | |||
| * Add any vendor specific files which should be included in the | |||
| * EJB Jar. | |||
| */ | |||
| protected void addVendorFiles(Hashtable ejbFiles, File srcDir, String baseName) { | |||
| } | |||
| /** | |||
| * Get the vendor specific name of the Jar that will be output. The modification date | |||
| * of this jar will be checked against the dependent bean classes. | |||
| */ | |||
| File getVendorOutputJarFile(String baseName) { | |||
| return new File(destDir, baseName + genericjarsuffix); | |||
| } | |||
| /** | |||
| * Method used to encapsulate the writing of the JAR file. Iterates over the | |||
| * filenames/java.io.Files in the Hashtable stored on the instance variable | |||
| * ejbFiles. | |||
| */ | |||
| protected void writeJar(String baseName, File jarfile, Hashtable files) throws BuildException{ | |||
| JarOutputStream jarStream = null; | |||
| Iterator entryIterator = null; | |||
| String entryName = null; | |||
| File entryFile = null; | |||
| try { | |||
| /* If the jarfile already exists then whack it and recreate it. | |||
| * Should probably think of a more elegant way to handle this | |||
| * so that in case of errors we don't leave people worse off | |||
| * than when we started =) | |||
| */ | |||
| if (jarfile.exists()) { | |||
| jarfile.delete(); | |||
| } | |||
| jarfile.getParentFile().mkdirs(); | |||
| jarfile.createNewFile(); | |||
| // Create the streams necessary to write the jarfile | |||
| jarStream = new JarOutputStream(new FileOutputStream(jarfile)); | |||
| jarStream.setMethod(JarOutputStream.DEFLATED); | |||
| // Loop through all the class files found and add them to the jar | |||
| entryIterator = files.keySet().iterator(); | |||
| while (entryIterator.hasNext()) { | |||
| entryName = (String) entryIterator.next(); | |||
| entryFile = (File) files.get(entryName); | |||
| getTask().log("adding file '" + entryName + "'", | |||
| Project.MSG_VERBOSE); | |||
| addFileToJar(jarStream, | |||
| new FileInputStream(entryFile), | |||
| entryName); | |||
| } | |||
| // All done. Close the jar stream. | |||
| jarStream.close(); | |||
| } | |||
| catch(IOException ioe) { | |||
| String msg = "IOException while processing ejb-jar file '" | |||
| + jarfile.toString() | |||
| + "'. Details: " | |||
| + ioe.getMessage(); | |||
| throw new BuildException(msg, ioe); | |||
| } | |||
| } // end of writeJar | |||
| /** | |||
| * Called to validate that the tool parameters have been configured. | |||
| * | |||
| */ | |||
| public void validateConfigured() throws BuildException { | |||
| if (destDir == null) { | |||
| throw new BuildException("The destdir attribute must be specified"); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,203 @@ | |||
| /* | |||
| * The Apache Software License, Version 1.1 | |||
| * | |||
| * Copyright (c) 2000 The Apache Software Foundation. All rights | |||
| * reserved. | |||
| * | |||
| * Redistribution and use in source and binary forms, with or without | |||
| * modification, are permitted provided that the following conditions | |||
| * are met: | |||
| * | |||
| * 1. Redistributions of source code must retain the above copyright | |||
| * notice, this list of conditions and the following disclaimer. | |||
| * | |||
| * 2. Redistributions in binary form must reproduce the above copyright | |||
| * notice, this list of conditions and the following disclaimer in | |||
| * the documentation and/or other materials provided with the | |||
| * distribution. | |||
| * | |||
| * 3. The end-user documentation included with the redistribution, if | |||
| * any, must include the following acknowlegement: | |||
| * "This product includes software developed by the | |||
| * Apache Software Foundation (http://www.apache.org/)." | |||
| * Alternately, this acknowlegement may appear in the software itself, | |||
| * if and wherever such third-party acknowlegements normally appear. | |||
| * | |||
| * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software | |||
| * Foundation" must not be used to endorse or promote products derived | |||
| * from this software without prior written permission. For written | |||
| * permission, please contact apache@apache.org. | |||
| * | |||
| * 5. Products derived from this software may not be called "Apache" | |||
| * nor may "Apache" appear in their names without prior written | |||
| * permission of the Apache Group. | |||
| * | |||
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED | |||
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||
| * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR | |||
| * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |||
| * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |||
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |||
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
| * SUCH DAMAGE. | |||
| * ==================================================================== | |||
| * | |||
| * This software consists of voluntary contributions made by many | |||
| * individuals on behalf of the Apache Software Foundation. For more | |||
| * information on the Apache Software Foundation, please see | |||
| * <http://www.apache.org/>. | |||
| */ | |||
| package org.apache.tools.ant.taskdefs.optional.ejb; | |||
| import java.io.*; | |||
| import java.util.*; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.Task; | |||
| import org.apache.tools.ant.types.Path; | |||
| import org.apache.tools.ant.taskdefs.Java; | |||
| public class WeblogicDeploymentTool extends GenericDeploymentTool { | |||
| protected static final String WL_DD = "weblogic-ejb-jar.xml"; | |||
| protected static final String WL_CMP_DD = "weblogic-cmp-rdbms-jar.xml"; | |||
| /** Instance variable that stores the suffix for the weblogic jarfile. */ | |||
| private String jarSuffix = "-wl.jar"; | |||
| private Path classpath; | |||
| /** Instance variable that determines whether generic ejb jars are kept. */ | |||
| private boolean keepgeneric = true; | |||
| /** | |||
| * Set the classpath to be used for this compilation. | |||
| */ | |||
| public void setClasspath(Path classpath) { | |||
| this.classpath = classpath; | |||
| } | |||
| /** | |||
| * Setter used to store the suffix for the generated weblogic jar file. | |||
| * @param inString the string to use as the suffix. | |||
| */ | |||
| public void setSuffix(String inString) { | |||
| this.jarSuffix = inString; | |||
| } | |||
| /** | |||
| * Setter used to store the value of keepgeneric | |||
| * @param inValue a string, either 'true' or 'false'. | |||
| */ | |||
| public void setKeepgeneric(String inValue) { | |||
| this.keepgeneric = Boolean.valueOf(inValue).booleanValue(); | |||
| } | |||
| protected DescriptorHandler getDescriptorHandler(File srcDir) { | |||
| DescriptorHandler handler = new DescriptorHandler(srcDir); | |||
| handler.registerResourceDTD("-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 1.1//EN", | |||
| "/weblogic/ejb/deployment/xml/ejb-jar.dtd"); | |||
| return handler; | |||
| } | |||
| /** | |||
| * Add any vendor specific files which should be included in the | |||
| * EJB Jar. | |||
| */ | |||
| protected void addVendorFiles(Hashtable ejbFiles, File srcdir, String baseName) { | |||
| // Then the weblogic deployment descriptor | |||
| File weblogicDD = new File(srcdir, | |||
| baseName + getBasenameTerminator() + WL_DD); | |||
| if (weblogicDD.exists()) { | |||
| ejbFiles.put(META_DIR + WL_DD, | |||
| weblogicDD); | |||
| } | |||
| // The the weblogic cmp deployment descriptor | |||
| File weblogicCMPDD = new File(srcdir, | |||
| baseName + getBasenameTerminator() + WL_CMP_DD); | |||
| if (weblogicCMPDD.exists()) { | |||
| ejbFiles.put(META_DIR + WL_CMP_DD, | |||
| weblogicCMPDD); | |||
| } | |||
| } | |||
| /** | |||
| * Get the vendor specific name of the Jar that will be output. The modification date | |||
| * of this jar will be checked against the dependent bean classes. | |||
| */ | |||
| File getVendorOutputJarFile(String baseName) { | |||
| return new File(getDestDir(), baseName + jarSuffix); | |||
| } | |||
| /** | |||
| * Helper method invoked by execute() for each WebLogic jar to be built. | |||
| * Encapsulates the logic of constructing a java task for calling | |||
| * weblogic.ejbc and executing it. | |||
| * @param sourceJar java.io.File representing the source (EJB1.1) jarfile. | |||
| * @param destJar java.io.File representing the destination, WebLogic | |||
| * jarfile. | |||
| */ | |||
| private void buildWeblogicJar(File sourceJar, File destJar) { | |||
| org.apache.tools.ant.taskdefs.Java javaTask = null; | |||
| try { | |||
| String args = "-noexit " + sourceJar.getPath().replace('\\', '/') + " " + destJar.getPath().replace('\\', '/'); | |||
| javaTask = (Java) getTask().getProject().createTask("java"); | |||
| javaTask.setClassname("weblogic.ejbc"); | |||
| javaTask.setArgs(args); | |||
| if (classpath != null) { | |||
| javaTask.setClasspath(classpath); | |||
| javaTask.setFork(true); | |||
| } | |||
| else { | |||
| javaTask.setFork(false); | |||
| } | |||
| getTask().log("Calling weblogic.ejbc for " + sourceJar.toString(), | |||
| Project.MSG_VERBOSE); | |||
| javaTask.execute(); | |||
| } | |||
| catch (Exception e) { | |||
| // Have to catch this because of the semantics of calling main() | |||
| String msg = "Exception while calling ejbc. Details: " + e.toString(); | |||
| throw new BuildException(msg, e); | |||
| } | |||
| } | |||
| /** | |||
| * Method used to encapsulate the writing of the JAR file. Iterates over the | |||
| * filenames/java.io.Files in the Hashtable stored on the instance variable | |||
| * ejbFiles. | |||
| */ | |||
| protected void writeJar(String baseName, File jarFile, Hashtable files) throws BuildException { | |||
| // need to create a generic jar first. | |||
| File genericJarFile = super.getVendorOutputJarFile(baseName); | |||
| super.writeJar(baseName, genericJarFile, files); | |||
| buildWeblogicJar(genericJarFile, jarFile); | |||
| if (!keepgeneric) { | |||
| getTask().log("deleting generic jar " + genericJarFile.toString(), | |||
| Project.MSG_VERBOSE); | |||
| genericJarFile.delete(); | |||
| } | |||
| } | |||
| /** | |||
| * Called to validate that the tool parameters have been configured. | |||
| * | |||
| */ | |||
| public void validateConfigured() throws BuildException { | |||
| super.validateConfigured(); | |||
| } | |||
| } | |||