Fields Summary |
---|
public static final int | DEFAULT_BUFFER_SIZEThe default buffer byte size to use for IO |
public static final int | JAR_COMPRESS_LEVELThe level to use for compression |
protected static final String | META_DIRThe standard META-INF directory in jar files |
protected static final String | MANIFESTThe standard MANIFEST file |
protected static final String | EJB_DDName for EJB Deployment descriptor within EJB jars |
public static final String | ANALYZER_SUPERA dependency analyzer name to find ancestor classes |
public static final String | ANALYZER_FULLA dependency analyzer name to find all related classes |
public static final String | ANALYZER_NONEA dependency analyzer name for no analyzer |
public static final String | DEFAULT_ANALYZERThe default analyzer |
public static final String | ANALYZER_CLASS_SUPERThe analyzer class for the super analyzer |
public static final String | ANALYZER_CLASS_FULLThe analyzer class for the super analyzer |
private EjbJar.Config | configThe configuration from the containing task. This config combined
with the settings of the individual attributes here constitues the
complete config for this deployment tool. |
private File | destDirStores a handle to the directory to put the Jar files in |
private org.apache.tools.ant.types.Path | classpathThe classpath to use with this deployment tool. This is appended to
any paths from the ejbjar task itself. |
private String | genericJarSuffixInstance variable that stores the suffix for the generated jarfile. |
private org.apache.tools.ant.Task | taskThe task to which this tool belongs. This is used to access services
provided by the ant core, such as logging. |
private ClassLoader | classpathLoaderThe classloader generated from the given classpath to load
the super classes and super interfaces. |
private Set | addedfilesSet of files have been loaded into the EJB jar |
private DescriptorHandler | handlerHandler used to parse the EJB XML descriptor |
private org.apache.tools.ant.util.depend.DependencyAnalyzer | dependencyAnalyzerDependency analyzer used to collect class dependencies |
Methods Summary |
---|
protected void | addFileToJar(java.util.jar.JarOutputStream jStream, java.io.File inputFile, java.lang.String logicalFilename)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.
FileInputStream iStream = null;
try {
if (!addedfiles.contains(logicalFilename)) {
iStream = new FileInputStream(inputFile);
// Create the zip entry and add it to the jar file
ZipEntry zipEntry = new ZipEntry(logicalFilename.replace('\\", '/"));
jStream.putNextEntry(zipEntry);
// Create the file input stream, and buffer everything over
// to the jar output stream
byte[] byteBuffer = new byte[2 * DEFAULT_BUFFER_SIZE];
int count = 0;
do {
jStream.write(byteBuffer, 0, count);
count = iStream.read(byteBuffer, 0, byteBuffer.length);
} while (count != -1);
//add it to list of files in jar
addedfiles.add(logicalFilename);
}
} catch (IOException ioe) {
log("WARNING: IOException while adding entry "
+ logicalFilename + " to jarfile from "
+ inputFile.getPath() + " " + ioe.getClass().getName()
+ "-" + ioe.getMessage(), Project.MSG_WARN);
} finally {
// Close up the file input stream for the class file
if (iStream != null) {
try {
iStream.close();
} catch (IOException closeException) {
// ignore
}
}
}
|
protected void | addSupportClasses(java.util.Hashtable ejbFiles)Adds any classes the user specifies using support nested elements
to the ejbFiles Hashtable.
// 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]));
}
}
|
protected void | addVendorFiles(java.util.Hashtable ejbFiles, java.lang.String ddPrefix)Add any vendor specific files which should be included in the
EJB Jar.
// nothing to add for generic tool.
|
protected void | checkAndAddDependants(java.util.Hashtable checkEntries)Add all available classes, that depend on Remote, Home, Bean, PK
if (dependencyAnalyzer == null) {
return;
}
dependencyAnalyzer.reset();
Iterator i = checkEntries.keySet().iterator();
while (i.hasNext()) {
String entryName = (String) i.next();
if (entryName.endsWith(".class")) {
String className = entryName.substring(0,
entryName.length() - ".class".length());
className = className.replace(File.separatorChar, '/");
className = className.replace('/", '.");
dependencyAnalyzer.addRootClass(className);
}
}
Enumeration e = dependencyAnalyzer.getClassDependencies();
while (e.hasMoreElements()) {
String classname = (String) e.nextElement();
String location
= classname.replace('.", File.separatorChar) + ".class";
File classFile = new File(config.srcDir, location);
if (classFile.exists()) {
checkEntries.put(location, classFile);
log("dependent class: " + classname + " - " + classFile,
Project.MSG_VERBOSE);
}
}
|
protected void | checkConfiguration(java.lang.String descriptorFileName, javax.xml.parsers.SAXParser saxParser)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.
/*
* For the GenericDeploymentTool, do nothing. Vendor specific
* subclasses should throw a BuildException if the configuration is
* invalid for their server.
*/
|
public void | configure(EjbJar.Config config)Configure this tool for use in the ejbjar task.
this.config = config;
createAnalyzer();
classpathLoader = null;
|
private void | createAnalyzer()
String analyzer = config.analyzer;
if (analyzer == null) {
analyzer = DEFAULT_ANALYZER;
}
if (analyzer.equals(ANALYZER_NONE)) {
return;
}
String analyzerClassName = null;
if (analyzer.equals(ANALYZER_SUPER)) {
analyzerClassName = ANALYZER_CLASS_SUPER;
} else if (analyzer.equals(ANALYZER_FULL)) {
analyzerClassName = ANALYZER_CLASS_FULL;
} else {
analyzerClassName = analyzer;
}
try {
Class analyzerClass = Class.forName(analyzerClassName);
dependencyAnalyzer
= (DependencyAnalyzer) analyzerClass.newInstance();
dependencyAnalyzer.addClassPath(new Path(task.getProject(),
config.srcDir.getPath()));
dependencyAnalyzer.addClassPath(config.classpath);
} catch (NoClassDefFoundError e) {
dependencyAnalyzer = null;
task.log("Unable to load dependency analyzer: " + analyzerClassName
+ " - dependent class not found: " + e.getMessage(),
Project.MSG_WARN);
} catch (Exception e) {
dependencyAnalyzer = null;
task.log("Unable to load dependency analyzer: " + analyzerClassName
+ " - exception: " + e.getMessage(),
Project.MSG_WARN);
}
|
public org.apache.tools.ant.types.Path | createClasspath()Add the classpath for the user classes
if (classpath == null) {
classpath = new Path(task.getProject());
}
return classpath.createPath();
|
protected java.lang.ClassLoader | getClassLoaderForBuild()Returns a Classloader object which parses the passed in generic EjbJar classpath.
The loader is used to dynamically load classes from javax.ejb.* and the classes
being added to the jar.
if (classpathLoader != null) {
return classpathLoader;
}
Path combinedClasspath = getCombinedClasspath();
// only generate a new ClassLoader if we have a classpath
if (combinedClasspath == null) {
classpathLoader = getClass().getClassLoader();
} else {
classpathLoader
= getTask().getProject().createClassLoader(combinedClasspath);
}
return classpathLoader;
|
protected org.apache.tools.ant.types.Path | getCombinedClasspath()Get the classpath by combining the one from the surrounding task, if any
and the one from this tool.
Path combinedPath = classpath;
if (config.classpath != null) {
if (combinedPath == null) {
combinedPath = config.classpath;
} else {
combinedPath.append(config.classpath);
}
}
return combinedPath;
|
protected EjbJar.Config | getConfig()Get the basename terminator.
return config;
|
protected DescriptorHandler | getDescriptorHandler(java.io.File srcDir)Get a descriptionHandler.
DescriptorHandler h = new DescriptorHandler(getTask(), srcDir);
registerKnownDTDs(h);
// register any DTDs supplied by the user
for (Iterator i = getConfig().dtdLocations.iterator(); i.hasNext();) {
EjbJar.DTDLocation dtdLocation = (EjbJar.DTDLocation) i.next();
h.registerDTD(dtdLocation.getPublicId(), dtdLocation.getLocation());
}
return h;
|
protected java.io.File | getDestDir()Get the destination directory.
return destDir;
|
protected java.lang.String | getJarBaseName(java.lang.String descriptorFileName)Using the EJB descriptor file name passed from the ejbjar
task, this method returns the "basename" which will be used to name the
completed JAR file.
String baseName = "";
// Work out what the base name is
if (config.namingScheme.getValue().equals(EjbJar.NamingScheme.BASEJARNAME)) {
String canonicalDescriptor = descriptorFileName.replace('\\", '/");
int index = canonicalDescriptor.lastIndexOf('/");
if (index != -1) {
baseName = descriptorFileName.substring(0, index + 1);
}
baseName += config.baseJarName;
} else if (config.namingScheme.getValue().equals(EjbJar.NamingScheme.DESCRIPTOR)) {
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);
} else {
throw new BuildException("Unable to determine jar name "
+ "from descriptor \"" + descriptorFileName + "\"");
}
} else if (config.namingScheme.getValue().equals(EjbJar.NamingScheme.DIRECTORY)) {
File descriptorFile = new File(config.descriptorDir, descriptorFileName);
String path = descriptorFile.getAbsolutePath();
int lastSeparatorIndex
= path.lastIndexOf(File.separator);
if (lastSeparatorIndex == -1) {
throw new BuildException("Unable to determine directory name holding descriptor");
}
String dirName = path.substring(0, lastSeparatorIndex);
int dirSeparatorIndex = dirName.lastIndexOf(File.separator);
if (dirSeparatorIndex != -1) {
dirName = dirName.substring(dirSeparatorIndex + 1);
}
baseName = dirName;
} else if (config.namingScheme.getValue().equals(EjbJar.NamingScheme.EJB_NAME)) {
baseName = handler.getEjbName();
}
return baseName;
|
protected org.apache.tools.ant.Location | getLocation()Get the build file location associated with this element's task.
return getTask().getLocation();
|
protected java.io.File | getManifestFile(java.lang.String prefix)Get the manifets file to use for building the generic jar.
If the file does not exist the global manifest from the config is used
otherwise the default Ant manifest will be used.
File manifestFile
= new File(getConfig().descriptorDir, prefix + "manifest.mf");
if (manifestFile.exists()) {
return manifestFile;
}
if (config.manifest != null) {
return config.manifest;
}
return null;
|
protected java.lang.String | getPublicId()Returns the Public ID of the DTD specified in the EJB descriptor. Not
every vendor-specific DeploymentTool will need to reference
this value or may want to determine this value in a vendor-specific way.
return handler.getPublicId();
|
protected org.apache.tools.ant.Task | getTask()Get the task for this tool.
return task;
|
public java.lang.String | getVendorDDPrefix(java.lang.String baseName, java.lang.String descriptorFileName)Get the prefix for vendor deployment descriptors.
This will contain the path and the start of the descriptor name,
depending on the naming scheme
String ddPrefix = null;
if (config.namingScheme.getValue().equals(EjbJar.NamingScheme.DESCRIPTOR)) {
ddPrefix = baseName + config.baseNameTerminator;
} else if (config.namingScheme.getValue().equals(EjbJar.NamingScheme.BASEJARNAME)
|| config.namingScheme.getValue().equals(EjbJar.NamingScheme.EJB_NAME)
|| config.namingScheme.getValue().equals(EjbJar.NamingScheme.DIRECTORY)) {
String canonicalDescriptor = descriptorFileName.replace('\\", '/");
int index = canonicalDescriptor.lastIndexOf('/");
if (index == -1) {
ddPrefix = "";
} else {
ddPrefix = descriptorFileName.substring(0, index + 1);
}
}
return ddPrefix;
|
java.io.File | getVendorOutputJarFile(java.lang.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.
return new File(destDir, baseName + genericJarSuffix);
|
protected void | log(java.lang.String message, int level)Log a message to the Ant output.
getTask().log(message, level);
|
protected boolean | needToRebuild(java.util.Hashtable ejbFiles, java.io.File jarFile)This method checks the timestamp on each file listed in the
ejbFiles and compares them to the timestamp on the jarFile
. If the jarFile 's timestamp is more recent than
each EJB file, true is returned. Otherwise, false
is returned.
TODO: find a way to check the manifest-file, that is found by naming convention
if (jarFile.exists()) {
long lastBuild = jarFile.lastModified();
Iterator fileIter = ejbFiles.values().iterator();
// Loop through the files seeing if any has been touched
// more recently than the destination jar.
while (fileIter.hasNext()) {
File currentFile = (File) fileIter.next();
if (lastBuild < currentFile.lastModified()) {
log("Build needed because " + currentFile.getPath() + " is out of date",
Project.MSG_VERBOSE);
return true;
}
}
return false;
}
return true;
|
protected java.util.Hashtable | parseEjbFiles(java.lang.String descriptorFileName, javax.xml.parsers.SAXParser saxParser)This method returns a list of EJB files found when the specified EJB
descriptor is parsed and processed.
FileInputStream descriptorStream = null;
Hashtable ejbFiles = null;
try {
/* 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();
} catch (IOException closeException) {
// ignore
}
}
}
return ejbFiles;
|
public void | processDescriptor(java.lang.String descriptorFileName, javax.xml.parsers.SAXParser saxParser){@inheritDoc}.
checkConfiguration(descriptorFileName, saxParser);
try {
handler = getDescriptorHandler(config.srcDir);
// Retrive the files to be added to JAR from EJB descriptor
Hashtable ejbFiles = parseEjbFiles(descriptorFileName, saxParser);
// Add any support classes specified in the build file
addSupportClasses(ejbFiles);
// Determine the JAR filename (without filename extension)
String baseName = getJarBaseName(descriptorFileName);
String ddPrefix = getVendorDDPrefix(baseName, descriptorFileName);
File manifestFile = getManifestFile(ddPrefix);
if (manifestFile != null) {
ejbFiles.put(MANIFEST, manifestFile);
}
// First the regular deployment descriptor
ejbFiles.put(META_DIR + EJB_DD,
new File(config.descriptorDir, descriptorFileName));
// now the vendor specific files, if any
addVendorFiles(ejbFiles, ddPrefix);
// add any dependent files
checkAndAddDependants(ejbFiles);
// Lastly create File object for the Jar files. If we are using
// a flat destination dir, then we need to redefine baseName!
if (config.flatDestDir && baseName.length() != 0) {
int startName = baseName.lastIndexOf(File.separator);
if (startName == -1) {
startName = 0;
}
int endName = baseName.length();
baseName = baseName.substring(startName, endName);
}
File jarFile = getVendorOutputJarFile(baseName);
// 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()
+ " with "
+ String.valueOf(ejbFiles.size())
+ " files",
Project.MSG_INFO);
// Use helper method to write the jarfile
String publicId = getPublicId();
writeJar(baseName, jarFile, ejbFiles, publicId);
} else {
// Log that the file is up to date...
log(jarFile.toString() + " is up to date.",
Project.MSG_VERBOSE);
}
} catch (SAXException se) {
String msg = "SAXException while parsing '"
+ descriptorFileName
+ "'. 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);
}
|
protected void | registerKnownDTDs(DescriptorHandler handler)Register the locations of all known DTDs.
vendor-specific subclasses should override this method to define
the vendor-specific locations of the EJB DTDs
// none to register for generic
|
public void | setClasspath(org.apache.tools.ant.types.Path classpath)Set the classpath to be used for this compilation.
this.classpath = classpath;
|
public void | setDestdir(java.io.File inDir)Set the destination directory; required.
this.destDir = inDir;
|
public void | setGenericJarSuffix(java.lang.String inString)Set the suffix for the generated jar file.
this.genericJarSuffix = inString;
|
public void | setTask(org.apache.tools.ant.Task task)Set the task which owns this tool
this.task = task;
|
protected boolean | usingBaseJarName()Indicate if this build is using the base jar name.
return config.baseJarName != null;
|
public void | validateConfigured()Called to validate that the tool parameters have been configured.
if ((destDir == null) || (!destDir.isDirectory())) {
String msg = "A valid destination directory must be specified "
+ "using the \"destdir\" attribute.";
throw new BuildException(msg, getLocation());
}
|
protected void | writeJar(java.lang.String baseName, java.io.File jarfile, java.util.Hashtable files, java.lang.String publicId)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.
JarOutputStream jarStream = null;
try {
// clean the addedfiles set
if (addedfiles == null) {
addedfiles = new HashSet();
} else {
addedfiles.clear();
}
/* 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();
InputStream in = null;
Manifest manifest = null;
try {
File manifestFile = (File) files.get(MANIFEST);
if (manifestFile != null && manifestFile.exists()) {
in = new FileInputStream(manifestFile);
} else {
String defaultManifest = "/org/apache/tools/ant/defaultManifest.mf";
in = this.getClass().getResourceAsStream(defaultManifest);
if (in == null) {
throw new BuildException("Could not find "
+ "default manifest: " + defaultManifest);
}
}
manifest = new Manifest(in);
} catch (IOException e) {
throw new BuildException ("Unable to read manifest", e, getLocation());
} finally {
if (in != null) {
in.close();
}
}
// Create the streams necessary to write the jarfile
jarStream = new JarOutputStream(new FileOutputStream(jarfile), manifest);
jarStream.setMethod(JarOutputStream.DEFLATED);
// Loop through all the class files found and add them to the jar
for (Iterator entryIterator = files.keySet().iterator(); entryIterator.hasNext();) {
String entryName = (String) entryIterator.next();
if (entryName.equals(MANIFEST)) {
continue;
}
File entryFile = (File) files.get(entryName);
log("adding file '" + entryName + "'",
Project.MSG_VERBOSE);
addFileToJar(jarStream, entryFile, entryName);
// See if there are any inner classes for this class and add them in if there are
InnerClassFilenameFilter flt = new InnerClassFilenameFilter(entryFile.getName());
File entryDir = entryFile.getParentFile();
String[] innerfiles = entryDir.list(flt);
if (innerfiles != null) {
for (int i = 0, n = innerfiles.length; i < n; i++) {
//get and clean up innerclass name
int entryIndex = entryName.lastIndexOf(entryFile.getName()) - 1;
if (entryIndex < 0) {
entryName = innerfiles[i];
} else {
entryName = entryName.substring(0, entryIndex)
+ File.separatorChar + innerfiles[i];
}
// link the file
entryFile = new File(config.srcDir, entryName);
log("adding innerclass file '" + entryName + "'",
Project.MSG_VERBOSE);
addFileToJar(jarStream, entryFile, entryName);
}
}
}
} catch (IOException ioe) {
String msg = "IOException while processing ejb-jar file '"
+ jarfile.toString()
+ "'. Details: "
+ ioe.getMessage();
throw new BuildException(msg, ioe);
} finally {
if (jarStream != null) {
try {
jarStream.close();
} catch (IOException closeException) {
// ignore
}
}
}
|