Browse Source

iplanet-ejbc task for EJB stubs and skeletons for the iPlanet

Application Server 6.0
Nested element to support iPlanet in ejbjar task


Submitted by:	Greg Nelson <greg@netscape.com>


git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@268990 13f79535-47bb-0310-9956-ffa450edef68
master
Conor MacNeill 24 years ago
parent
commit
a80cf0dfec
7 changed files with 2480 additions and 73 deletions
  1. +1
    -0
      build.xml
  2. +1
    -0
      src/main/org/apache/tools/ant/taskdefs/defaults.properties
  3. +15
    -0
      src/main/org/apache/tools/ant/taskdefs/optional/ejb/EjbJar.java
  4. +198
    -73
      src/main/org/apache/tools/ant/taskdefs/optional/ejb/GenericDeploymentTool.java
  5. +423
    -0
      src/main/org/apache/tools/ant/taskdefs/optional/ejb/IPlanetDeploymentTool.java
  6. +1489
    -0
      src/main/org/apache/tools/ant/taskdefs/optional/ejb/IPlanetEjbc.java
  7. +353
    -0
      src/main/org/apache/tools/ant/taskdefs/optional/ejb/IPlanetEjbcTask.java

+ 1
- 0
build.xml View File

@@ -189,6 +189,7 @@
<exclude name="${optional.package}/ejb/WLStop.java" unless="ejb.wls.present" />
<exclude name="${optional.package}/ejb/EjbJar.java" unless="jdk1.2+" />
<exclude name="${optional.package}/ejb/*DeploymentTool.java" unless="jdk1.2+" />
<exclude name="${optional.package}/ejb/IPlanet*.java" unless="jdk1.2+" />
<exclude name="${optional.package}/Javah.java" unless="jdk1.2+" />
<exclude name="${optional.package}/junit/*" unless="junit.present" />
<exclude name="${optional.package}/net/*.java" unless="netcomp.present" />


+ 1
- 0
src/main/org/apache/tools/ant/taskdefs/defaults.properties View File

@@ -100,6 +100,7 @@ rpm=org.apache.tools.ant.taskdefs.optional.Rpm
xmlvalidate=org.apache.tools.ant.taskdefs.optional.XMLValidateTask
vsscheckin=org.apache.tools.ant.taskdefs.optional.vss.MSVSSCHECKIN
vsscheckout=org.apache.tools.ant.taskdefs.optional.vss.MSVSSCHECKOUT
iplanet-ejbc=org.apache.tools.ant.taskdefs.optional.ejb.IPlanetEjbcTask

# deprecated ant tasks (kept for back compatibility)
javadoc2=org.apache.tools.ant.taskdefs.Javadoc


+ 15
- 0
src/main/org/apache/tools/ant/taskdefs/optional/ejb/EjbJar.java View File

@@ -208,6 +208,21 @@ public class EjbJar extends MatchingTask {
return tool;
}

/**
* Create a nested element used to configure a deployment tool for iPlanet
* Application Server.
*
* @return the deployment tool instance to be configured.
*/
public IPlanetDeploymentTool createIplanet() {
log("iPlanet Application Server deployment tools", Project.MSG_VERBOSE);

IPlanetDeploymentTool tool = new IPlanetDeploymentTool();
tool.setTask(this);
deploymentTools.add(tool);
return tool;
}

/**
* Create a nested element for weblogic when using the Toplink
* Object- Relational mapping.


+ 198
- 73
src/main/org/apache/tools/ant/taskdefs/optional/ejb/GenericDeploymentTool.java View File

@@ -113,6 +113,11 @@ public class GenericDeploymentTool implements EJBDeploymentTool {
*/
private List addedfiles;

/**
* Handler used to parse the EJB XML descriptor
*/
private DescriptorHandler handler;

/**
* Setter used to store the value of destination directory prior to execute()
* being called.
@@ -205,6 +210,10 @@ public class GenericDeploymentTool implements EJBDeploymentTool {
getTask().log(message, level);
}

protected Location getLocation() {
return getTask().getLocation();
}


/**
* Configure this tool for use in the ejbjar task.
@@ -293,54 +302,18 @@ public class GenericDeploymentTool implements EJBDeploymentTool {
}

public void processDescriptor(String descriptorFileName, SAXParser saxParser) {
FileInputStream descriptorStream = null;

try {
DescriptorHandler handler = getDescriptorHandler(config.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.
*/
descriptorStream = new FileInputStream(new File(config.descriptorDir, descriptorFileName));
saxParser.parse(new InputSource(descriptorStream), handler);
Hashtable ejbFiles = handler.getFiles();
checkConfiguration(descriptorFileName, saxParser);
// add in support classes if any
Project project = task.getProject();
for (Iterator i = config.supportFileSets.iterator(); i.hasNext();) {
FileSet supportFileSet = (FileSet)i.next();
File supportBaseDir = supportFileSet.getDir(project);
DirectoryScanner supportScanner = supportFileSet.getDirectoryScanner(project);
supportScanner.scan();
String[] supportFiles = supportScanner.getIncludedFiles();
for (int j = 0; j < supportFiles.length; ++j) {
ejbFiles.put(supportFiles[j], new File(supportBaseDir, supportFiles[j]));
}
}
try {
// Retrive the files to be added to JAR from EJB descriptor
Hashtable ejbFiles = parseEjbFiles(descriptorFileName, saxParser);

String baseName = "";
// Work out what the base name is
if (config.baseJarName != null) {
baseName = config.baseJarName;
} else {
int lastSeparatorIndex = descriptorFileName.lastIndexOf(File.separator);
int endBaseName = -1;
if (lastSeparatorIndex != -1) {
endBaseName = descriptorFileName.indexOf(config.baseNameTerminator,
lastSeparatorIndex);
}
else {
endBaseName = descriptorFileName.indexOf(config.baseNameTerminator);
}
// Add any support classes specified in the build file
addSupportClasses(ejbFiles);

if (endBaseName != -1) {
baseName = descriptorFileName.substring(0, endBaseName);
}
baseName = descriptorFileName.substring(0, endBaseName);
}
// Determine the JAR filename (without filename extension)
String baseName = getJarBaseName(descriptorFileName);

// First the regular deployment descriptor
ejbFiles.put(META_DIR + EJB_DD,
@@ -366,30 +339,9 @@ public class GenericDeploymentTool implements EJBDeploymentTool {
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() );
if (needBuild) {
log("Build needed because " + currentFile.getPath() + " is out of date",
Project.MSG_VERBOSE);
}
}
}
// Check to see if we need a build and start
// doing the work!
if (needBuild) {
// Check to see if we need a build and start doing the work!
if (needToRebuild(ejbFiles, jarFile)) {
// Log that we are going to build...
log( "building "
+ jarFile.getName()
@@ -399,7 +351,8 @@ public class GenericDeploymentTool implements EJBDeploymentTool {
Project.MSG_INFO);
// Use helper method to write the jarfile
writeJar(baseName, jarFile, ejbFiles, handler.getPublicId());
String publicId = getPublicId();
writeJar(baseName, jarFile, ejbFiles, publicId);

}
else {
@@ -425,7 +378,63 @@ public class GenericDeploymentTool implements EJBDeploymentTool {
+ ioe.getMessage();
throw new BuildException(msg, ioe);
}
finally {
}
/**
* This method is called as the first step in the processDescriptor method
* to allow vendor-specific subclasses to validate the task configuration
* prior to processing the descriptor. If the configuration is invalid,
* a BuildException should be thrown.
*
* @param descriptorFileName String representing the file name of an EJB
* descriptor to be processed
* @param saxParser SAXParser which may be used to parse the XML
* descriptor
* @thows BuildException Thrown if the configuration is invalid
*/
protected void checkConfiguration(String descriptorFileName,
SAXParser saxParser) throws BuildException {

/*
* For the GenericDeploymentTool, do nothing. Vendor specific
* subclasses should throw a BuildException if the configuration is
* invalid for their server.
*/
}

/**
* This method returns a list of EJB files found when the specified EJB
* descriptor is parsed and processed.
*
* @param descriptorFileName String representing the file name of an EJB
* descriptor to be processed
* @param saxParser SAXParser which may be used to parse the XML
* descriptor
* @return Hashtable of EJB class (and other) files to be
* added to the completed JAR file
* @throws SAXException Any SAX exception, possibly wrapping another
* exception
* @throws IOException An IOException from the parser, possibly from a
* the byte stream or character stream
*/
protected Hashtable parseEjbFiles(String descriptorFileName, SAXParser saxParser)
throws IOException, SAXException {
FileInputStream descriptorStream = null;
Hashtable ejbFiles = null;

try {
handler = getDescriptorHandler(config.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.
*/
descriptorStream = new FileInputStream(new File(config.descriptorDir, descriptorFileName));
saxParser.parse(new InputSource(descriptorStream), handler);
ejbFiles = handler.getFiles();

} finally {
if (descriptorStream != null) {
try {
descriptorStream.close();
@@ -433,8 +442,70 @@ public class GenericDeploymentTool implements EJBDeploymentTool {
catch (IOException closeException) {}
}
}
}

return ejbFiles;
}

/**
* Adds any classes the user specifies using <i>support</i> nested elements
* to the <code>ejbFiles</code> Hashtable.
*
* @param ejbFiles Hashtable of EJB classes (and other) files that will be
* added to the completed JAR file
*/
protected void addSupportClasses(Hashtable ejbFiles) {
// add in support classes if any
Project project = task.getProject();
for (Iterator i = config.supportFileSets.iterator(); i.hasNext();) {
FileSet supportFileSet = (FileSet)i.next();
File supportBaseDir = supportFileSet.getDir(project);
DirectoryScanner supportScanner = supportFileSet.getDirectoryScanner(project);
supportScanner.scan();
String[] supportFiles = supportScanner.getIncludedFiles();
for (int j = 0; j < supportFiles.length; ++j) {
ejbFiles.put(supportFiles[j], new File(supportBaseDir, supportFiles[j]));
}
}
}


/**
* Using the EJB descriptor file name passed from the <code>ejbjar</code>
* task, this method returns the "basename" which will be used to name the
* completed JAR file.
*
* @param descriptorFileName String representing the file name of an EJB
* descriptor to be processed
* @return The "basename" which will be used to name the
* completed JAR file
*/
protected String getJarBaseName(String descriptorFileName) {

String baseName = "";

// Work out what the base name is
if (config.baseJarName != null) {
baseName = config.baseJarName;
} else {
int lastSeparatorIndex = descriptorFileName.lastIndexOf(File.separator);
int endBaseName = -1;
if (lastSeparatorIndex != -1) {
endBaseName = descriptorFileName.indexOf(config.baseNameTerminator,
lastSeparatorIndex);
} else {
endBaseName = descriptorFileName.indexOf(config.baseNameTerminator);
}

if (endBaseName != -1) {
baseName = descriptorFileName.substring(0, endBaseName);
}
baseName = descriptorFileName.substring(0, endBaseName);
}

return baseName;
}


/**
* Add any vendor specific files which should be included in the
* EJB Jar.
@@ -452,6 +523,56 @@ public class GenericDeploymentTool implements EJBDeploymentTool {
return new File(destDir, baseName + genericJarSuffix);
}

/**
* This method checks the timestamp on each file listed in the <code>
* ejbFiles</code> and compares them to the timestamp on the <code>jarFile
* </code>. If the <code>jarFile</code>'s timestamp is more recent than
* each EJB file, <code>false</code> is returned. Otherwise, <code>true
* </code> is returned.
*
* @param ejbFiles Hashtable of EJB classes (and other) files that will be
* added to the completed JAR file
* @param jarFile JAR file which will contain all of the EJB classes (and
* other) files
* @return boolean indicating whether or not the <code>jarFile</code>
* is up to date
*/
protected boolean needToRebuild(Hashtable ejbFiles, File jarFile) {
// 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() );
if (needBuild) {
log("Build needed because " + currentFile.getPath() + " is out of date",
Project.MSG_VERBOSE);
}
}
}
return needBuild;
}

/**
* Returns the Public ID of the DTD specified in the EJB descriptor. Not
* every vendor-specific <code>DeploymentTool</code> will need to reference
* this value or may want to determine this value in a vendor-specific way.
*
* @return Public ID of the DTD specified in the EJB descriptor.
*/
protected String getPublicId() {
return handler.getPublicId();
}

/**
* 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
@@ -664,10 +785,14 @@ public class GenericDeploymentTool implements EJBDeploymentTool {
/**
* Called to validate that the tool parameters have been configured.
*
* @throws BuildException If the Deployment Tool's configuration isn't
* valid
*/
public void validateConfigured() throws BuildException {
if (destDir == null) {
throw new BuildException("The destdir attribute must be specified");
if ((destDir == null) || (!destDir.isDirectory())) {
String msg = "A valid destination directory must be specified "
+ "using the \"destdir\" attribute.";
throw new BuildException(msg, getLocation());
}
}
}

+ 423
- 0
src/main/org/apache/tools/ant/taskdefs/optional/ejb/IPlanetDeploymentTool.java View File

@@ -0,0 +1,423 @@
/*
* 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", "Ant", 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.File;
import java.io.IOException;
import java.util.Hashtable;

import javax.xml.parsers.SAXParser;
import org.xml.sax.SAXException;

import org.apache.tools.ant.Project;
import org.apache.tools.ant.BuildException;

/**
* This class is used to generate iPlanet Application Server (iAS) 6.0 stubs and
* skeletons and build an EJB Jar file. It is designed to be used with the Ant
* <code>ejbjar</code> task. If only stubs and skeletons need to be generated
* (in other words, if no JAR file needs to be created), refer to the
* <code>iplanet-ejbc</code> task and the <code>IPlanetEjbcTask</code> class.
* <p>
* The following attributes may be specified by the user:
* <ul>
* <li><i>destdir</i> -- The base directory into which the generated JAR
* files will be written. Each JAR file is written
* in directories which correspond to their location
* within the "descriptordir" namespace. This is a
* required attribute.
* <li><i>classpath</i> -- The classpath used when generating EJB stubs and
* skeletons. This is an optional attribute (if
* omitted, the classpath specified in the "ejbjar"
* parent task will be used). If specified, the
* classpath elements will be prepended to the
* classpath specified in the parent "ejbjar" task.
* Note that nested "classpath" elements may also be
* used.
* <li><i>keepgenerated</i> -- Indicates whether or not the Java source
* files which are generated by ejbc will be
* saved or automatically deleted. If "yes",
* the source files will be retained. This is
* an optional attribute (if omitted, it
* defaults to "no").
* <li><i>debug</i> -- Indicates whether or not the ejbc utility should
* log additional debugging statements to the standard
* output. If "yes", the additional debugging statements
* will be generated (if omitted, it defaults to "no").
* <li><i>iashome</i> -- May be used to specify the "home" directory for
* this iPlanet Application server installation. This
* is used to find the ejbc utility if it isn't
* included in the user's system path. This is an
* optional attribute (if specified, it should refer
* to the <code>[install-location]/iplanet/ias6/ias
* </code> directory). If omitted, the ejbc utility
* must be on the user's system path.
* <li><i>suffix</i> -- String value appended to the JAR filename when
* creating each JAR. This attribute is not required
* (if omitted, it defaults to ".jar").
* </ul>
* <p>
* For each EJB descriptor found in the "ejbjar" parent task, this deployment
* tool will locate the three classes that comprise the EJB. If these class
* files cannot be located in the specified <code>srcdir</code> directory, the
* task will fail. The task will also attempt to locate the EJB stubs and
* skeletons in this directory. If found, the timestamps on the stubs and
* skeletons will be checked to ensure they are up to date. Only if these files
* cannot be found or if they are out of date will ejbc be called.
*
* @see IPlanetEjbc
* @author Greg Nelson <a href="mailto:greg@netscape.com">greg@netscape.com</a>
*/
public class IPlanetDeploymentTool extends GenericDeploymentTool {

/* Attributes set by the Ant build file */
private File iashome;
private String jarSuffix = ".jar";
private boolean keepgenerated = false;
private boolean debug = false;

/*
* Filenames of the standard EJB descriptor (which is passed to this class
* from the parent "ejbjar" task) and the iAS-specific EJB descriptor
* (whose name is determined by this class). Both filenames are relative
* to the directory specified by the "srcdir" attribute in the ejbjar task.
*/
private String descriptorName;
private String iasDescriptorName;

/*
* The displayName variable stores the value of the "display-name" element
* from the standard EJB descriptor. As a future enhancement to this task,
* we may determine the name of the EJB JAR file using this display-name,
* but this has not be implemented yet.
*/
private String displayName;

/*
* Regardless of the name of the iAS-specific EJB descriptor file, it will
* written in the completed JAR file as "ias-ejb-jar.xml". This is the
* naming convention implemented by iAS.
*/
private static final String IAS_DD = "ias-ejb-jar.xml";

/**
* Setter method used to store the "home" directory of the user's iAS
* installation. The directory specified should typically be
* <code>[install-location]/iplanet/ias6/ias</code>.
*
* @param iashome The home directory for the user's iAS installation.
*/
public void setIashome(File iashome) {
this.iashome = iashome;
}

/**
* Setter method used to specify whether the Java source files generated by
* the ejbc utility should be saved or automatically deleted.
*
* @param keepgenerated boolean which, if <code>true</code>, indicates that
* Java source files generated by ejbc for the stubs
* and skeletons should be kept.
*/
public void setKeepgenerated(boolean keepgenerated) {
this.keepgenerated = keepgenerated;
}

/**
* Sets whether or not debugging output will be generated when ejbc is
* executed.
*
* @param debug A boolean indicating if debugging output should be generated
*/
public void setDebug(boolean debug) {
this.debug = debug;
}

/**
* Setter method used to specify the filename suffix (for example, ".jar")
* for the JAR files to be created.
*
* @param jarSuffix The string to use as the JAR filename suffix.
*/
public void setSuffix(String jarSuffix) {
this.jarSuffix = jarSuffix;
}

/**
* Since iAS doesn't generate a "generic" JAR as part of its processing,
* this attribute is ignored and a warning message is displayed to the user.
*
* @param inString the string to use as the suffix. This parameter is
* ignored.
*/
public void setGenericJarSuffix(String inString) {
log("Since a generic JAR file is not created during processing, the "
+ "iPlanet Deployment Tool does not support the "
+ "\"genericjarsuffix\" attribute. It will be ignored.",
Project.MSG_WARN);
}

public void processDescriptor(String descriptorName, SAXParser saxParser) {
this.descriptorName = descriptorName;

log("iPlanet Deployment Tool processing: " + descriptorName + " (and "
+ getIasDescriptorName() + ")", Project.MSG_VERBOSE);

super.processDescriptor(descriptorName, saxParser);
}

/**
* Verifies that the user selections are valid.
*
* @param descriptorFileName String representing the file name of an EJB
* descriptor to be processed
* @param saxParser SAXParser which may be used to parse the XML
* descriptor
* @throws BuildException If the user selections are invalid.
*/
protected void checkConfiguration(String descriptorFileName,
SAXParser saxParser) throws BuildException {

int startOfName = descriptorFileName.lastIndexOf(File.separatorChar) + 1;
String stdXml = descriptorFileName.substring(startOfName);
if (stdXml.equals(EJB_DD) && (getConfig().baseJarName == null)) {
String msg = "No name specified for the completed JAR file. The EJB"
+ " descriptor should be prepended with the JAR "
+ "name or it should be specified using the "
+ "attribute \"basejarname\" in the \"ejbjar\" task.";
throw new BuildException(msg, getLocation());
}

File iasDescriptor = new File(getConfig().descriptorDir,
getIasDescriptorName());
if ((!iasDescriptor.exists()) || (!iasDescriptor.isFile())) {
String msg = "The iAS-specific EJB descriptor ("
+ iasDescriptor + ") was not found.";
throw new BuildException(msg, getLocation());
}

if ((iashome != null) && (!iashome.isDirectory())) {
String msg = "If \"iashome\" is specified, it must be a valid "
+ "directory (it was set to " + iashome + ").";
throw new BuildException(msg, getLocation());
}
}

/**
* This method returns a list of EJB files found when the specified EJB
* descriptor is parsed and processed.
*
* @param descriptorFileName String representing the file name of an EJB
* descriptor to be processed
* @param saxParser SAXParser which may be used to parse the XML
* descriptor
* @return Hashtable of EJB class (and other) files to be
* added to the completed JAR file
* @throws IOException An IOException from the parser, possibly from
* the byte stream or character stream
* @throws SAXException Any SAX exception, possibly wrapping another
* exception
*/
protected Hashtable parseEjbFiles(String descriptorFileName,
SAXParser saxParser) throws IOException, SAXException {

Hashtable files;

/* Build and populate an instance of the ejbc utility */
IPlanetEjbc ejbc = new IPlanetEjbc(
new File(getConfig().descriptorDir,
descriptorFileName),
new File(getConfig().descriptorDir,
getIasDescriptorName()),
getConfig().srcDir,
getCombinedClasspath().toString(),
saxParser);
ejbc.setRetainSource(keepgenerated);
ejbc.setDebugOutput(debug);
if (iashome != null) {
ejbc.setIasHomeDir(iashome);
}

/* Execute the ejbc utility -- stubs/skeletons are rebuilt, if needed */
try {
ejbc.execute();
} catch (IPlanetEjbc.EjbcException e) {
throw new BuildException("An error has occurred while trying to "
+ "execute the iAS ejbc utility", e, getLocation());
}

displayName = ejbc.getDisplayName();
files = ejbc.getEjbFiles();

/* Add CMP descriptors to the list of EJB files */
String[] cmpDescriptors = ejbc.getCmpDescriptors();
if (cmpDescriptors.length > 0) {
File baseDir = getConfig().descriptorDir;

int endOfPath = descriptorFileName.lastIndexOf(File.separator);
String relativePath = descriptorFileName.substring(0, endOfPath + 1);

for (int i = 0; i < cmpDescriptors.length; i++) {
int endOfCmp = cmpDescriptors[i].lastIndexOf('/');
String cmpDescriptor = cmpDescriptors[i].substring(endOfCmp + 1);

File cmpFile = new File(baseDir, relativePath + cmpDescriptor);
if (!cmpFile.exists()) {
throw new BuildException("The CMP descriptor file ("
+ cmpFile + ") could not be found.", getLocation());
}
files.put(cmpDescriptors[i], cmpFile);
}
}

return files;
}

/**
* Add the iAS-specific EJB descriptor to the list of files which will be
* written to the JAR file.
*
* @param ejbFiles Hashtable of EJB class (and other) files to be added to
* the completed JAR file.
* @param baseName String name of the EJB JAR file to be written (without
* a filename extension).
*/
protected void addVendorFiles(Hashtable ejbFiles, String baseName) {
ejbFiles.put(META_DIR + IAS_DD, new File(getConfig().descriptorDir,
getIasDescriptorName()));
}

/**
* Get the name of the Jar that will be written. The modification date
* of this jar will be checked against the dependent bean classes.
*
* @param baseName String name of the EJB JAR file to be written (without
* a filename extension).
*
* @return File representing the JAR file which will be written.
*/
File getVendorOutputJarFile(String baseName) {
File jarFile = new File(getDestDir(), baseName + jarSuffix);
log("JAR file name: " + jarFile.toString(), Project.MSG_VERBOSE);
return jarFile;
}

/**
* The iAS ejbc utility doesn't require the Public ID of the descriptor's
* DTD for it to process correctly--this method always returns <code>null
* </code>.
*
* @return <code>null</code>.
*/
protected String getPublicId() {
return null;
}

/**
* Determines the name of the iAS-specific EJB descriptor using the
* specified standard EJB descriptor name. In general, the standard
* descriptor will be named "[basename]-ejb-jar.xml", and this method will
* return "[basename]-ias-ejb-jar.xml".
*
* @return The name of the iAS-specific EJB descriptor file.
*/
private String getIasDescriptorName() {
/* Only calculate the descriptor name once */
if (iasDescriptorName != null) {
return iasDescriptorName;
}

String path = ""; // Directory path of the EJB descriptor
String basename; // Filename appearing before name terminator
String remainder; // Filename appearing after the name terminator

/* Find the end of the standard descriptor's relative path */
int startOfFileName = descriptorName.lastIndexOf(File.separatorChar);
if (startOfFileName != -1) {
path = descriptorName.substring(0, startOfFileName + 1);
}

/* Check to see if the standard name is used (there's no basename) */
if (descriptorName.substring(startOfFileName + 1).equals(EJB_DD)) {
basename = "";
remainder = EJB_DD;

} else {
int endOfBaseName = descriptorName.indexOf(
getConfig().baseNameTerminator,
startOfFileName);
/*
* Check for the odd case where the terminator and/or filename
* extension aren't found. These will ensure "ias-" appears at the
* end of the name and before the '.' (if present).
*/
if (endOfBaseName < 0) {
endOfBaseName = descriptorName.lastIndexOf('.') - 1;
if (endOfBaseName < 0) {
endOfBaseName = descriptorName.length() - 1;
}
}

basename = descriptorName.substring(startOfFileName + 1,
endOfBaseName + 1);
remainder = descriptorName.substring(endOfBaseName + 1);
}

iasDescriptorName = path + basename + "ias-" + remainder;
return iasDescriptorName;
}
}

+ 1489
- 0
src/main/org/apache/tools/ant/taskdefs/optional/ejb/IPlanetEjbc.java
File diff suppressed because it is too large
View File


+ 353
- 0
src/main/org/apache/tools/ant/taskdefs/optional/ejb/IPlanetEjbcTask.java View File

@@ -0,0 +1,353 @@
/*
* 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", "Ant", 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.File;
import java.io.IOException;

import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.SAXException;

import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.BuildException;

/**
* Task to compile EJB stubs and skeletons for the iPlanet Application Server.
* The EJBs to be processed are specified by the EJB 1.1 standard XML
* descriptor, and additional attributes are obtained from the iPlanet Application
* Server-specific XML descriptor. Since the XML descriptors can include
* multiple EJBs, this is a convenient way of specifying many EJBs in a single
* Ant task. The following attributes are allowed:
* <ul>
* <li><i>ejbdescriptor</i> -- Standard EJB 1.1 XML descriptor (typically
* titled "ejb-jar.xml"). This attribute is
* required.
* <li><i>iasdescriptor</i> -- EJB XML descriptor for iPlanet Application
* Server (typically titled "ias-ejb-jar.xml).
* This attribute is required.
* <li><i>dest</i> -- The is the base directory where the RMI stubs and
* skeletons are written. In addition, the class files
* for each bean (home interface, remote interface, and
* EJB implementation) must be found in this directory.
* This attribute is required.
* <li><i>classpath</i> -- The classpath used when generating EJB stubs and
* skeletons. This is an optional attribute (if
* omitted, the classpath specified when Ant was
* started will be used). Nested "classpath"
* elements may also be used.
* <li><i>keepgenerated</i> -- Indicates whether or not the Java source
* files which are generated by ejbc will be
* saved or automatically deleted. If "yes",
* the source files will be retained. This is
* an optional attribute (if omitted, it
* defaults to "no").
* <li><i>debug</i> -- Indicates whether or not the ejbc utility should
* log additional debugging statements to the standard
* output. If "yes", the additional debugging statements
* will be generated (if omitted, it defaults to "no").
* <li><i>iashome</i> -- May be used to specify the "home" directory for
* this iPlanet Application Server installation. This
* is used to find the ejbc utility if it isn't
* included in the user's system path. This is an
* optional attribute (if specified, it should refer
* to the <code>[install-location]/iplanet/ias6/ias
* </code> directory). If omitted, the ejbc utility
* must be on the user's system path.
* </ul>
* <p>
* For each EJB specified, this task will locate the three classes that comprise
* the EJB. If these class files cannot be located in the <code>dest</code>
* directory, the task will fail. The task will also attempt to locate the EJB
* stubs and skeletons in this directory. If found, the timestamps on the
* stubs and skeletons will be checked to ensure they are up to date. Only if
* these files cannot be found or if they are out of date will ejbc be called
* to generate new stubs and skeletons.
*
* @see IPlanetEjbc
* @author Greg Nelson <a href="mailto:greg@netscape.com">greg@netscape.com</a>
*/
public class IPlanetEjbcTask extends Task {

/* Attributes set by the Ant build file */
private File ejbdescriptor;
private File iasdescriptor;
private File dest;
private Path classpath;
private boolean keepgenerated = false;
private boolean debug = false;
private File iashome;

/**
* Sets the location of the standard XML EJB descriptor. Typically, this
* file is named "ejb-jar.xml".
*
* @param ejbdescriptor The name and location of the EJB descriptor.
*/
public void setEjbdescriptor(File ejbdescriptor) {
this.ejbdescriptor = ejbdescriptor;
}

/**
* Sets the location of the iAS-specific XML EJB descriptor. Typically,
* this file is named "ias-ejb-jar.xml".
*
* @param iasdescriptor The name and location of the iAS-specific EJB
* descriptor.
*/
public void setIasdescriptor (File iasdescriptor) {
this.iasdescriptor = iasdescriptor;
}

/**
* Sets the destination directory where the EJB "source" classes must exist
* and where the stubs and skeletons will be written. The destination
* directory must exist before this task is executed.
*
* @param dest The directory where the compiled classes will be written.
*/
public void setDest(File dest) {
this.dest = dest;
}

/**
* Sets the classpath to be used when compiling the EJB stubs and skeletons.
*
* @param classpath The classpath to be used.
*/
public void setClasspath(Path classpath) {
if (this.classpath == null) {
this.classpath = classpath;
} else {
this.classpath.append(classpath);
}
}

/**
* Creates a nested classpath element.
*/
public Path createClasspath() {
if (classpath == null) {
classpath = new Path(project);
}
return classpath.createPath();
}

/**
* Sets whether or not the Java source files which are generated by the
* ejbc process should be retained or automatically deleted.
*
* @param keepgenerated A boolean indicating if the Java source files for
* the stubs and skeletons should be retained.
*/
public void setKeepgenerated(boolean keepgenerated) {
this.keepgenerated = keepgenerated;
}

/**
* Sets whether or not debugging output will be generated when ejbc is
* executed.
*
* @param debug A boolean indicating if debugging output should be generated
*/
public void setDebug(boolean debug) {
this.debug = debug;
}
/**
* Setter method used to store the "home" directory of the user's iAS
* installation. The directory specified should typically be
* <code>[install-location]/iplanet/ias6/ias</code>.
*
* @param iashome The home directory for the user's iAS installation.
*/
public void setIashome(File iashome) {
this.iashome = iashome;
}

/**
* Does the work.
*/
public void execute() throws BuildException {
checkConfiguration();

executeEjbc(getParser());
}
/**
* Verifies that the user selections are valid.
*
* @throws BuildException If the user selections are invalid.
*/
private void checkConfiguration() throws BuildException {

if (ejbdescriptor == null) {
String msg = "The standard EJB descriptor must be specified using "
+ "the \"ejbdescriptor\" attribute.";
throw new BuildException(msg, location);
}
if ((!ejbdescriptor.exists()) || (!ejbdescriptor.isFile())) {
String msg = "The standard EJB descriptor (" + ejbdescriptor
+ ") was not found or isn't a file.";
throw new BuildException(msg, location);
}

if (iasdescriptor == null) {
String msg = "The iAS-speific XML descriptor must be specified using"
+ " the \"iasdescriptor\" attribute.";
throw new BuildException(msg, location);
}
if ((!iasdescriptor.exists()) || (!iasdescriptor.isFile())) {
String msg = "The iAS-specific XML descriptor (" + iasdescriptor
+ ") was not found or isn't a file.";
throw new BuildException(msg, location);
}

if (dest == null) {
String msg = "The destination directory must be specified using "
+ "the \"dest\" attribute.";
throw new BuildException(msg, location);
}
if ((!dest.exists()) || (!dest.isDirectory())) {
String msg = "The destination directory (" + dest + ") was not "
+ "found or isn't a directory.";
throw new BuildException(msg, location);
}

if ((iashome != null) && (!iashome.isDirectory())) {
String msg = "If \"iashome\" is specified, it must be a valid "
+ "directory (it was set to " + iashome + ").";
throw new BuildException(msg, getLocation());
}
}

/**
* Returns a SAXParser that may be used to process the XML descriptors.
*
* @return Parser which may be used to process the EJB descriptors.
* @throws BuildException If the parser cannot be created or configured.
*/
private SAXParser getParser() throws BuildException {

SAXParser saxParser = null;
try {
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
saxParserFactory.setValidating(true);
saxParser = saxParserFactory.newSAXParser();
} catch (SAXException e) {
String msg = "Unable to create a SAXParser: " + e.getMessage();
throw new BuildException(msg, e, location);
}
catch (ParserConfigurationException e) {
String msg = "Unable to create a SAXParser: " + e.getMessage();
throw new BuildException(msg, e, location);
}

return saxParser;
}

/**
* Executes the EJBc utility using the SAXParser provided.
*
* @param saxParser SAXParser that may be used to process the EJB
* descriptors
* @throws BuildException If there is an error reading or parsing the XML
* descriptors
*/
private void executeEjbc(SAXParser saxParser) throws BuildException {
IPlanetEjbc ejbc = new IPlanetEjbc(ejbdescriptor,
iasdescriptor,
dest,
getClasspath().toString(),
saxParser);
ejbc.setRetainSource(keepgenerated);
ejbc.setDebugOutput(debug);
if (iashome != null) {
ejbc.setIasHomeDir(iashome);
}

try {
ejbc.execute();
} catch (IOException e) {
String msg = "An IOException occurred while trying to read the XML "
+ "descriptor file: " + e.getMessage();
throw new BuildException(msg, e, location);
} catch (SAXException e) {
String msg = "A SAXException occurred while trying to read the XML "
+ "descriptor file: " + e.getMessage();
throw new BuildException(msg, e, location);
} catch (IPlanetEjbc.EjbcException e) {
String msg = "An exception occurred while trying to run the ejbc "
+ "utility: " + e.getMessage();
throw new BuildException(msg, e, location);
}
}

/**
* Returns the CLASSPATH to be used when calling EJBc. If no user CLASSPATH
* is specified, the System classpath is returned instead.
*
* @return Path The classpath to be used for EJBc.
*/
private Path getClasspath() {
if (classpath == null) {
classpath = Path.systemClasspath;
}

return classpath;
}
}

Loading…
Cancel
Save