/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */
package org.apache.tools.ant.taskdefs.optional.ejb;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.Collections;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Map;
import java.util.Set;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;

import javax.xml.parsers.SAXParser;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Location;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.taskdefs.optional.ejb.EjbJar.DTDLocation;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.util.depend.DependencyAnalyzer;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;


A deployment tool which creates generic EJB jars. Generic jars contains only those classes and META-INF entries specified in the EJB 1.1 standard This class is also used as a framework for the creation of vendor specific deployment tools. A number of template methods are provided through which the vendor specific tool can hook into the EJB creation process.
/** * A deployment tool which creates generic EJB jars. Generic jars contains * only those classes and META-INF entries specified in the EJB 1.1 standard * * This class is also used as a framework for the creation of vendor specific * deployment tools. A number of template methods are provided through which the * vendor specific tool can hook into the EJB creation process. * */
public class GenericDeploymentTool implements EJBDeploymentTool {
The default buffer byte size to use for IO
/** The default buffer byte size to use for IO */
public static final int DEFAULT_BUFFER_SIZE = 1024;
The level to use for compression
/** The level to use for compression */
public static final int JAR_COMPRESS_LEVEL = 9;
The standard META-INF directory in jar files
/** The standard META-INF directory in jar files */
protected static final String META_DIR = "META-INF/";
The standard MANIFEST file
/** The standard MANIFEST file */
protected static final String MANIFEST = META_DIR + "MANIFEST.MF";
Name for EJB Deployment descriptor within EJB jars
/** Name for EJB Deployment descriptor within EJB jars */
protected static final String EJB_DD = "ejb-jar.xml";
A dependency analyzer name to find ancestor classes
/** A dependency analyzer name to find ancestor classes */
public static final String ANALYZER_SUPER = "super";
A dependency analyzer name to find all related classes
/** A dependency analyzer name to find all related classes */
public static final String ANALYZER_FULL = "full";
A dependency analyzer name for no analyzer
/** A dependency analyzer name for no analyzer */
public static final String ANALYZER_NONE = "none";
The default analyzer
/** The default analyzer */
public static final String DEFAULT_ANALYZER = ANALYZER_SUPER;
The analyzer class for the super analyzer
/** The analyzer class for the super analyzer */
public static final String ANALYZER_CLASS_SUPER = "org.apache.tools.ant.util.depend.bcel.AncestorAnalyzer";
The analyzer class for the super analyzer
/** The analyzer class for the super analyzer */
public static final String ANALYZER_CLASS_FULL = "org.apache.tools.ant.util.depend.bcel.FullAnalyzer";
The configuration from the containing task. This config combined with the settings of the individual attributes here constitues the complete config for this deployment tool.
/** * The 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 EjbJar.Config config;
Stores a handle to the directory to put the Jar files in
/** Stores a handle to the directory to put the Jar files in */
private File destDir;
The classpath to use with this deployment tool. This is appended to any paths from the ejbjar task itself.
/** The classpath to use with this deployment tool. This is appended to any paths from the ejbjar task itself.*/
private Path classpath;
Instance variable that stores the suffix for the generated jarfile.
/** Instance variable that stores the suffix for the generated jarfile. */
private String genericJarSuffix = "-generic.jar";
The task to which this tool belongs. This is used to access services provided by the ant core, such as logging.
/** * The task to which this tool belongs. This is used to access services * provided by the ant core, such as logging. */
private Task task;
The classloader generated from the given classpath to load the super classes and super interfaces.
/** * The classloader generated from the given classpath to load * the super classes and super interfaces. */
private ClassLoader classpathLoader = null;
Set of files have been loaded into the EJB jar
/** * Set of files have been loaded into the EJB jar */
private Set<String> addedfiles;
Handler used to parse the EJB XML descriptor
/** * Handler used to parse the EJB XML descriptor */
private DescriptorHandler handler;
Dependency analyzer used to collect class dependencies
/** * Dependency analyzer used to collect class dependencies */
private DependencyAnalyzer dependencyAnalyzer;
Set the destination directory; required.
Params:
  • inDir – the destination directory.
/** * Set the destination directory; required. * @param inDir the destination directory. */
public void setDestdir(File inDir) { this.destDir = inDir; }
Get the destination directory.
Returns:the destination directory into which EJB jars are to be written
/** * Get the destination directory. * * @return the destination directory into which EJB jars are to be written */
protected File getDestDir() { return destDir; }
Set the task which owns this tool
Params:
  • task – the Task to which this deployment tool is associated.
/** * Set the task which owns this tool * * @param task the Task to which this deployment tool is associated. */
@Override public void setTask(Task task) { this.task = task; }
Get the task for this tool.
Returns:the Task instance this tool is associated with.
/** * Get the task for this tool. * * @return the Task instance this tool is associated with. */
protected Task getTask() { return task; }
Get the basename terminator.
Returns:an ejbjar task configuration
/** * Get the basename terminator. * * @return an ejbjar task configuration */
protected EjbJar.Config getConfig() { return config; }
Indicate if this build is using the base jar name.
Returns:true if the name of the generated jar is coming from the basejarname attribute
/** * Indicate if this build is using the base jar name. * * @return true if the name of the generated jar is coming from the * basejarname attribute */
protected boolean usingBaseJarName() { return config.baseJarName != null; }
Set the suffix for the generated jar file.
Params:
  • inString – the string to use as the suffix.
/** * Set the suffix for the generated jar file. * @param inString the string to use as the suffix. */
public void setGenericJarSuffix(String inString) { this.genericJarSuffix = inString; }
Add the classpath for the user classes
Returns:a Path instance to be configured by Ant.
/** * Add the classpath for the user classes * * @return a Path instance to be configured by Ant. */
public Path createClasspath() { if (classpath == null) { classpath = new Path(task.getProject()); } return classpath.createPath(); }
Set the classpath to be used for this compilation.
Params:
  • classpath – the classpath to be used for this build.
/** * Set the classpath to be used for this compilation. * * @param classpath the classpath to be used for this build. */
public void setClasspath(Path classpath) { this.classpath = classpath; }
Get the classpath by combining the one from the surrounding task, if any and the one from this tool.
Returns:the combined classpath
/** * Get the classpath by combining the one from the surrounding task, if any * and the one from this tool. * * @return the combined classpath */
protected Path getCombinedClasspath() { Path combinedPath = classpath; if (config.classpath != null) { if (combinedPath == null) { combinedPath = config.classpath; } else { combinedPath.append(config.classpath); } } return combinedPath; }
Log a message to the Ant output.
Params:
  • message – the message to be logged.
  • level – the severity of this message.
/** * Log a message to the Ant output. * * @param message the message to be logged. * @param level the severity of this message. */
protected void log(String message, int level) { getTask().log(message, level); }
Get the build file location associated with this element's task.
Returns:the task's location instance.
/** * Get the build file location associated with this element's task. * * @return the task's location instance. */
protected Location getLocation() { return getTask().getLocation(); } private void createAnalyzer() { String analyzer = config.analyzer; if (analyzer == null) { analyzer = DEFAULT_ANALYZER; } if (analyzer.equals(ANALYZER_NONE)) { return; } String analyzerClassName = null; switch (analyzer) { case ANALYZER_SUPER: analyzerClassName = ANALYZER_CLASS_SUPER; break; case ANALYZER_FULL: analyzerClassName = ANALYZER_CLASS_FULL; break; default: analyzerClassName = analyzer; break; } try { Class<? extends DependencyAnalyzer> analyzerClass = Class.forName(analyzerClassName) .asSubclass(DependencyAnalyzer.class); 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); } }
Configure this tool for use in the ejbjar task.
Params:
  • config – the configuration from the surrounding ejbjar task.
/** * Configure this tool for use in the ejbjar task. * * @param config the configuration from the surrounding ejbjar task. */
@Override public void configure(EjbJar.Config config) { this.config = config; createAnalyzer(); classpathLoader = null; }
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.
Params:
  • jStream – A JarOutputStream into which to write the jar entry.
  • inputFile – A File from which to read the contents the file being added.
  • logicalFilename – A String representing the name, including all relevant path information, that should be stored for the entry being added.
Throws:
/** * 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 inputFile A File from which to read the * contents the file being added. * @param logicalFilename A String representing the name, including * all relevant path information, that should be stored for the entry * being added. * @throws BuildException if there is a problem. */
protected void addFileToJar(JarOutputStream jStream, File inputFile, String logicalFilename) throws BuildException { if (!addedfiles.contains(logicalFilename)) { try (InputStream iStream = Files.newInputStream(inputFile.toPath())) { // 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); } } }
Get a descriptionHandler.
Params:
  • srcDir – the source directory.
Returns:a handler.
/** * Get a descriptionHandler. * @param srcDir the source directory. * @return a handler. */
protected DescriptorHandler getDescriptorHandler(File srcDir) { DescriptorHandler h = new DescriptorHandler(getTask(), srcDir); registerKnownDTDs(h); // register any DTDs supplied by the user for (DTDLocation dtdLocation : getConfig().dtdLocations) { h.registerDTD(dtdLocation.getPublicId(), dtdLocation.getLocation()); } return h; }
Register the locations of all known DTDs. vendor-specific subclasses should override this method to define the vendor-specific locations of the EJB DTDs
Params:
  • handler – no used in this class.
/** * Register the locations of all known DTDs. * * vendor-specific subclasses should override this method to define * the vendor-specific locations of the EJB DTDs * @param handler no used in this class. */
protected void registerKnownDTDs(DescriptorHandler handler) { // none to register for generic }
{@inheritDoc}.
/** {@inheritDoc}. */
@Override public void processDescriptor(String descriptorFileName, SAXParser saxParser) { checkConfiguration(descriptorFileName, saxParser); try { handler = getDescriptorHandler(config.srcDir); // Retreive the files to be added to JAR from EJB descriptor Hashtable<String, File> 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.isEmpty()) { 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) { throw new BuildException( "SAXException while parsing '" + descriptorFileName + "'. This probably indicates badly-formed XML." + " Details: " + se.getMessage(), se); } catch (IOException ioe) { throw new BuildException( "IOException while parsing'" + descriptorFileName + "'. This probably indicates that the descriptor" + " doesn't exist. Details: " + ioe.getMessage(), ioe); } }
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.
Params:
  • descriptorFileName – String representing the file name of an EJB descriptor to be processed
  • saxParser – SAXParser which may be used to parse the XML descriptor
Throws:
/** * 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 * @throws BuildException if there is a problem. */
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.
Params:
  • descriptorFileName – String representing the file name of an EJB descriptor to be processed
  • saxParser – SAXParser which may be used to parse the XML descriptor
Throws:
  • SAXException – Any SAX exception, possibly wrapping another exception
  • IOException – An IOException from the parser, possibly from a the byte stream or character stream
Returns: Hashtable of EJB class (and other) files to be added to the completed JAR file
/** * 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<String, File> parseEjbFiles(String descriptorFileName, SAXParser saxParser) throws IOException, SAXException { /* 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. */ try (InputStream descriptorStream = Files.newInputStream( new File(config.descriptorDir, descriptorFileName).toPath())) { saxParser.parse(new InputSource(descriptorStream), handler); return handler.getFiles(); } }
Adds any classes the user specifies using support nested elements to the ejbFiles Hashtable.
Params:
  • ejbFiles – Hashtable of EJB classes (and other) files that will be added to the completed JAR file
/** * 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<String, File> ejbFiles) { // add in support classes if any Project project = task.getProject(); for (FileSet supportFileSet : config.supportFileSets) { File supportBaseDir = supportFileSet.getDir(project); DirectoryScanner supportScanner = supportFileSet.getDirectoryScanner(project); for (String supportFile : supportScanner.getIncludedFiles()) { ejbFiles.put(supportFile, new File(supportBaseDir, supportFile)); } } }
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.
Params:
  • descriptorFileName – String representing the file name of an EJB descriptor to be processed
Returns: The "basename" which will be used to name the completed JAR file
/** * 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 (EjbJar.NamingScheme.BASEJARNAME.equals(config.namingScheme.getValue())) { String canonicalDescriptor = descriptorFileName.replace('\\', '/'); int index = canonicalDescriptor.lastIndexOf('/'); if (index != -1) { baseName = descriptorFileName.substring(0, index + 1); } baseName += config.baseJarName; } else if (EjbJar.NamingScheme.DESCRIPTOR.equals(config.namingScheme.getValue())) { 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 \"%s\"", descriptorFileName); } } else if (EjbJar.NamingScheme.DIRECTORY.equals(config.namingScheme.getValue())) { 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 (EjbJar.NamingScheme.EJB_NAME.equals(config.namingScheme.getValue())) { baseName = handler.getEjbName(); } return baseName; }
Get the prefix for vendor deployment descriptors. This will contain the path and the start of the descriptor name, depending on the naming scheme
Params:
  • baseName – the base name to use.
  • descriptorFileName – the file name to use.
Returns:the prefix.
/** * Get the prefix for vendor deployment descriptors. * * This will contain the path and the start of the descriptor name, * depending on the naming scheme * @param baseName the base name to use. * @param descriptorFileName the file name to use. * @return the prefix. */
public String getVendorDDPrefix(String baseName, String descriptorFileName) { 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; }
Add any vendor specific files which should be included in the EJB Jar.
Params:
  • ejbFiles – a hashtable entryname -> file.
  • ddPrefix – a prefix to use.
/** * Add any vendor specific files which should be included in the * EJB Jar. * @param ejbFiles a hashtable entryname -&gt; file. * @param ddPrefix a prefix to use. */
protected void addVendorFiles(Hashtable<String, File> ejbFiles, String ddPrefix) { // nothing to add for generic tool. }
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.
Params:
  • baseName – the basename to use.
Returns:File
/** * 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. * * @param baseName the basename to use. * @return File */
File getVendorOutputJarFile(String baseName) { return new File(destDir, baseName + genericJarSuffix); }
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
Params:
  • ejbFiles – Hashtable of EJB classes (and other) files that will be added to the completed JAR file
  • jarFile – JAR file which will contain all of the EJB classes (and other) files
Returns: boolean indicating whether or not the jarFile is up to date
/** * 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>true</code> is returned. Otherwise, <code>false * </code> is returned. * TODO: find a way to check the manifest-file, that is found by naming convention * * @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<String, File> ejbFiles, File jarFile) { if (jarFile.exists()) { long lastBuild = jarFile.lastModified(); // Loop through the files seeing if any has been touched // more recently than the destination jar. for (File currentFile : ejbFiles.values()) { if (lastBuild < currentFile.lastModified()) { log("Build needed because " + currentFile.getPath() + " is out of date", Project.MSG_VERBOSE); return true; } } return false; } return true; }
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.
Returns:Public ID of the DTD specified in the EJB descriptor.
/** * 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(); }
Get the manifest 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.
Params:
  • prefix – the prefix where to llook for the manifest file based on the naming convention.
Returns:the manifest file or null if the manifest file does not exist
/** * Get the manifest 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. * * @param prefix the prefix where to llook for the manifest file based on * the naming convention. * * @return the manifest file or null if the manifest file does not exist */
protected File getManifestFile(String prefix) { File manifestFile = new File(getConfig().descriptorDir, prefix + "manifest.mf"); if (manifestFile.exists()) { return manifestFile; } if (config.manifest != null) { return config.manifest; } return null; }
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.
Params:
  • baseName – the base name to use.
  • jarfile – the jar file to write to.
  • files – the files to write to the jar.
  • publicId – the id to use.
Throws:
/** * 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. * @param baseName the base name to use. * @param jarfile the jar file to write to. * @param files the files to write to the jar. * @param publicId the id to use. * @throws BuildException if there is a problem. */
protected void writeJar(String baseName, File jarfile, Hashtable<String, File> files, String publicId) throws BuildException { // clean the addedfiles set if (addedfiles == null) { addedfiles = new HashSet<>(); } else { addedfiles.clear(); } 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(); InputStream in = null; Manifest manifest = null; try { File manifestFile = files.get(MANIFEST); if (manifestFile != null && manifestFile.exists()) { in = Files.newInputStream(manifestFile.toPath()); } 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: %s", 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 try (JarOutputStream jarStream = new JarOutputStream( Files.newOutputStream(jarfile.toPath()), manifest)) { jarStream.setMethod(JarOutputStream.DEFLATED); // Loop through all the class files found and add them to the jar for (Map.Entry<String, File> entryFiles : files.entrySet()) { String entryName = entryFiles.getKey(); if (entryName.equals(MANIFEST)) { continue; } File entryFile = entryFiles.getValue(); 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 (String innerfile : innerfiles) { //get and clean up innerclass name int entryIndex = entryName.lastIndexOf(entryFile.getName()) - 1; if (entryIndex < 0) { entryName = innerfile; } else { entryName = entryName.substring(0, entryIndex) + File.separatorChar + innerfile; } // 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); } } // end of writeJar
Add all available classes, that depend on Remote, Home, Bean, PK
Params:
  • checkEntries – files, that are extracted from the deployment descriptor
Throws:
/** * Add all available classes, that depend on Remote, Home, Bean, PK * @param checkEntries files, that are extracted from the deployment descriptor * @throws BuildException if there is a problem. */
protected void checkAndAddDependants(Hashtable<String, File> checkEntries) throws BuildException { if (dependencyAnalyzer == null) { return; } dependencyAnalyzer.reset(); for (String entryName : checkEntries.keySet()) { if (entryName.endsWith(".class")) { String className = entryName.substring(0, entryName.length() - ".class".length()); className = className.replace(File.separatorChar, '/'); className = className.replace('/', '.'); dependencyAnalyzer.addRootClass(className); } } for (String classname : Collections.list(dependencyAnalyzer.getClassDependencies())) { 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); } } }
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.
Returns:a classloader.
/** * 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. * @return a classloader. */
protected ClassLoader getClassLoaderForBuild() { 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 { // Memory leak in line below classpathLoader = getTask().getProject().createClassLoader(combinedClasspath); } return classpathLoader; }
Called to validate that the tool parameters have been configured.
Throws:
  • BuildException – If the Deployment Tool's configuration isn't valid
/** * Called to validate that the tool parameters have been configured. * * @throws BuildException If the Deployment Tool's configuration isn't * valid */
@Override public void validateConfigured() throws BuildException { if (destDir == null || !destDir.isDirectory()) { throw new BuildException( "A valid destination directory must be specified using the \"destdir\" attribute.", getLocation()); } } }