|
Ant example source code file (GenericDeploymentTool.java)
The GenericDeploymentTool.java source code/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package org.apache.tools.ant.taskdefs.optional.ejb; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.Enumeration; import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; 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.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. * */ public class GenericDeploymentTool implements EJBDeploymentTool { /** The default buffer byte size to use for IO */ public static final int DEFAULT_BUFFER_SIZE = 1024; /** The level to use for compression */ public static final int JAR_COMPRESS_LEVEL = 9; /** The standard META-INF directory in jar files */ protected static final String META_DIR = "META-INF/"; /** The standard MANIFEST file */ protected static final String MANIFEST = META_DIR + "MANIFEST.MF"; /** 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 */ public static final String ANALYZER_SUPER = "super"; /** A dependency analyzer name to find all related classes */ public static final String ANALYZER_FULL = "full"; /** A dependency analyzer name for no analyzer */ public static final String ANALYZER_NONE = "none"; /** The default analyzer */ public static final String DEFAULT_ANALYZER = ANALYZER_SUPER; /** 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 */ 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. */ private EjbJar.Config config; /** 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.*/ private Path classpath; /** 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. */ private Task task; /** * 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 */ private Set addedfiles; /** * Handler used to parse the EJB XML descriptor */ private DescriptorHandler handler; /** * Dependency analyzer used to collect class dependencies */ private DependencyAnalyzer dependencyAnalyzer; /** No arg constructor */ public GenericDeploymentTool() { } /** * Set the destination directory; required. * @param inDir the destination directory. */ public void setDestdir(File inDir) { this.destDir = inDir; } /** * 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 * * @param task the Task to which this deployment tool is associated. */ public void setTask(Task task) { this.task = task; } /** * Get the task for this tool. * * @return the Task instance this tool is associated with. */ protected Task getTask() { return task; } /** * 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. * * @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. * @param inString the string to use as the suffix. */ public void setGenericJarSuffix(String inString) { this.genericJarSuffix = inString; } /** * 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. * * @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. * * @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. * * @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. * * @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; 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); } } /** * Configure this tool for use in the ejbjar task. * * @param config the configuration from the surrounding ejbjar task. */ 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. * @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 { 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 } } } } /** * 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 (Iterator i = getConfig().dtdLocations.iterator(); i.hasNext();) { EjbJar.DTDLocation dtdLocation = (EjbJar.DTDLocation) i.next(); 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 * @param handler no used in this class. */ protected void registerKnownDTDs(DescriptorHandler handler) { // none to register for generic } /** {@inheritDoc}. */ public void processDescriptor(String descriptorFileName, SAXParser saxParser) { 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); } } /** * 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. * * @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 { /* 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; } /** * Adds any classes the user specifies using <i>support nested elements * to the <code>ejbFiles 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 * 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.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; } /** * 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. * @param ejbFiles a hashtable entryname -> file. * @param ddPrefix a prefix to use. */ protected void addVendorFiles(Hashtable 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. * @param baseName the basename to use. */ File getVendorOutputJarFile(String baseName) { 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 Other Ant examples (source code examples)Here is a short list of links related to this Ant GenericDeploymentTool.java source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.