| /* |
| * The Apache Software License, Version 1.1 |
| * |
| * Copyright (c) 2002 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 org.apache.tools.ant.BuildException; |
| import org.apache.tools.ant.Project; |
| import org.apache.tools.ant.types.Path; |
| import org.apache.tools.ant.taskdefs.Java; |
| import org.apache.tools.ant.util.FileUtils; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.util.Hashtable; |
| |
| |
| /** |
| * The deployment tool to add the jonas specific deployment descriptors to |
| * the ejb jar file. JONAS only requires one additional file jonas-ejb-jar.xml. |
| * |
| * @author <a href="cmorvan@ingenosya.com">Cyrille Morvan</a>, |
| * <a href="http://www.ingenosya.com">Ingenosya France</a> |
| * @version 1.0 |
| * @see EjbJar#createJonas |
| */ |
| public class JonasDeploymentTool extends GenericDeploymentTool { |
| |
| protected static final String JONAS_DD = "jonas-ejb-jar.xml"; |
| |
| protected static final String GENIC_CLASS = |
| "org.objectweb.jonas_ejb.tools.GenWholeIC"; |
| |
| protected static final String OLD_GENIC_CLASS = |
| "org.objectweb.jonas_ejb.tools.GenIC"; |
| |
| protected static final String DEFAULT_ORB = "RMI"; |
| |
| /** Instance variable that stores the suffix for the jonas jarfile. */ |
| private String jarSuffix = ".jar"; |
| |
| /** |
| * Instance variable that stores the fully qualified classname |
| * of the JOnAS GenIC compiler. |
| **/ |
| private String genicClass; |
| |
| private String additionalArgs = ""; |
| |
| /** Instance variable that determines do not delete intermediate generated source files */ |
| private boolean keepgenerated = false; |
| |
| /** as websphere and WebLogic taskes */ |
| private boolean keepGeneric = false; |
| |
| /** Instance variable that determines the JOnAS Root directory */ |
| private File jonasroot; |
| |
| /** Instance variable that determines if we could -secpropag */ |
| private boolean secpropag = false; |
| |
| /** Instance variable that determines the ouput directory */ |
| private File ouputdirectory; |
| |
| /** Instance variable that determines the path to the compiler to use */ |
| private String compiler; |
| |
| /** Instance variable that determines if GenIC is verbose */ |
| private boolean verbose; |
| |
| /** Instance variable that determines the ORB to use (RMI, JEREMIE, DAVID)*/ |
| private String orb; |
| |
| /** clean the working directory after work **/ |
| private boolean cleanWorkDir = false; |
| |
| private boolean noGENIC = false; |
| |
| /** |
| * set the name of the GenIC compiler class. |
| **/ |
| public void setGenicClass(final String inGenicClass) { |
| genicClass = inGenicClass; |
| } |
| |
| |
| /** |
| * Set the ORB to construct classpath. |
| * @param inValue RMI, JEREMIE, DAVID,... |
| **/ |
| public void setOrb(final String inValue) { |
| orb = inValue; |
| } |
| |
| /** |
| * The compiler (switch <code>-javac</code>) to use. |
| **/ |
| public void setCompiler(final String inCompiler) { |
| compiler = inCompiler; |
| } |
| |
| /** |
| * Setter used to store the value of keepGeneric |
| * @param inValue a string, either 'true' or 'false'. |
| */ |
| public void setKeepgeneric(boolean inValue) { |
| this.keepGeneric = inValue; |
| } |
| |
| /** |
| * GenIC verbose or not |
| * @param inValue either 'true' or 'false' |
| **/ |
| public void setVerbose(final boolean inValue) { |
| verbose = inValue; |
| } |
| |
| /** |
| * GenIC run or not. |
| * @param inValue run or not |
| **/ |
| public void setNoGENIC(final boolean inValue) { |
| noGENIC = inValue; |
| } |
| |
| /** |
| * Sets whether -keepgenerated is passed to GenIC (that is, |
| * the .java source files are kept). |
| * @param inValue either 'true' or 'false' |
| **/ |
| public void setKeepgenerated(final boolean inValue) { |
| keepgenerated = inValue; |
| } |
| |
| /** |
| * set the jonas root directory (-Dinstall.root=). |
| * |
| * @throws BuildException if the file doesn't exist. |
| **/ |
| public void setJonasroot(final File inValue) { |
| jonasroot = inValue; |
| } |
| |
| /** |
| * Modify the RMI Skeleton and Stub to implement |
| * the implicit propagation of the transactionnal |
| * context and security context. |
| * For JOnAS 2.4 and next. |
| */ |
| public void setSecpropag(final boolean inValue) { |
| secpropag = inValue; |
| } |
| |
| /** |
| * set the output directory (-d ...). |
| * <br> |
| * |
| * It's the GenIC working directory. It's not the |
| * DestDir, which is the 'jar' destination directory. |
| * |
| * @param inValue a file |
| **/ |
| public void setOuputdir(final File inValue) { |
| ouputdirectory = inValue; |
| } |
| |
| |
| /** |
| * set the output directory (-d ...). |
| * Same as setOuputdir(). |
| * <br> |
| * But do not override setDestDir() |
| **/ |
| public void setWorkdir(final File inValue) { |
| setOuputdir(inValue); |
| } |
| |
| /** |
| * Clean the specified Work dir after work. |
| * @param inValue true : clean ; false : not clean |
| **/ |
| public void setCleanworkdir(final boolean inValue) { |
| cleanWorkDir = inValue; |
| } |
| |
| /** |
| * Setter used to store the suffix for the generated JOnAS jar file. |
| * @param inString the string to use as the suffix. |
| **/ |
| public void setSuffix(String inString) { |
| this.jarSuffix = inString; |
| } |
| |
| /** |
| * sets some additional args to send to GenIC. |
| **/ |
| public void setArgs(final String inArgs) { |
| additionalArgs = inArgs; |
| } |
| |
| /** |
| * Add any vendor specific files which should be included in the |
| * EJB Jar. |
| * @param aDdPrefix MyDirectories/MyEjb- or MyDirectories/ |
| **/ |
| protected void addVendorFiles(final Hashtable someEjbFiles,final String aDdPrefix) { |
| // Use Ant Naming convention |
| File aJonasDD = new File(getConfig().descriptorDir,aDdPrefix + JONAS_DD); |
| if ( aJonasDD.exists() ) { |
| someEjbFiles.put(META_DIR + JONAS_DD, aJonasDD); |
| } else { |
| // try with JOnAS Naming convention |
| if( ! addJonasVendorFiles(someEjbFiles,aDdPrefix) ) { |
| log("Unable to locate JOnAS deployment descriptor. It was expected to be in " |
| + aJonasDD.getPath() + ". Or please use JOnAS naming convention.", |
| Project.MSG_WARN); |
| } |
| } |
| } |
| |
| /** |
| * try to add JOnAS specific file, using JOnAS naming convention. |
| * For example : jonas-Account.xml or jonas-ejb-jar.xml |
| * @param aDdPrefix MyDirectories/MyEjb- or MyDirectories/ |
| * @return true if Ok |
| */ |
| private boolean addJonasVendorFiles(final Hashtable someEjbFiles,final String aDdPrefix) { |
| // replace \ by /, remove the last letter ( a dash - ) |
| final String aCanonicalDD = aDdPrefix.replace('\\', '/').substring(0,aDdPrefix.length()-1); |
| final int index = aCanonicalDD.lastIndexOf('/') + 1; |
| String anEjbJarName = aCanonicalDD.substring(index); |
| if( "ejb".equals( anEjbJarName ) ) { |
| anEjbJarName = "ejb-jar"; |
| } |
| final String aNewDdPrefix = |
| aDdPrefix.substring(0,index) + "jonas-" + anEjbJarName + ".xml"; |
| File aConventionNamingJonasDD = new File(getConfig().descriptorDir,aNewDdPrefix); |
| |
| log("look for jonas specific file using jonas naming convention " + aConventionNamingJonasDD, |
| Project.MSG_VERBOSE); |
| |
| if( aConventionNamingJonasDD.exists() ) { |
| someEjbFiles.put(META_DIR + JONAS_DD,aConventionNamingJonasDD); |
| return true; |
| } else { |
| return false; |
| } |
| } |
| |
| // include javadoc |
| // Determine the JAR filename (without filename extension) |
| protected String getJarBaseName(String aDescriptorFileName) { |
| String aBaseName = null; |
| EjbJar.Config aConfig = super.getConfig(); |
| if (aConfig.namingScheme.getValue().equals(EjbJar.NamingScheme.DESCRIPTOR)) { |
| // try to find JOnAS specific convention name |
| // ??/MyEJB.xml ( I will find later the ??/jonas-MyEJB.xml file ) |
| if( aDescriptorFileName.indexOf(aConfig.baseNameTerminator) == -1 ) { |
| String aCanonicalDescriptor = aDescriptorFileName.replace('\\','/'); |
| int lastSeparatorIndex = aCanonicalDescriptor.lastIndexOf('/'); |
| int endBaseName; |
| if (lastSeparatorIndex != -1) { |
| endBaseName = aDescriptorFileName.indexOf(".xml", lastSeparatorIndex); |
| } else { |
| endBaseName = aDescriptorFileName.indexOf(".xml"); |
| } |
| |
| if (endBaseName != -1) { |
| aBaseName = aDescriptorFileName.substring(0, endBaseName); |
| } |
| } |
| } |
| |
| if( aBaseName == null ) { |
| // else get standard BaseName |
| aBaseName = super.getJarBaseName(aDescriptorFileName); |
| } |
| return aBaseName; |
| } |
| |
| /** |
| * Method used to encapsulate the writing of the JAR file. Iterates over the |
| * filenames/java.io.Files in the Hashtable stored on the instance variable |
| * ejbFiles. |
| **/ |
| protected void writeJar(String baseName, File jarFile, Hashtable files, |
| String publicId) throws BuildException { |
| // need to create a generic jar first. |
| File genericJarFile = super.getVendorOutputJarFile(baseName); |
| super.writeJar(baseName, genericJarFile, files, publicId); |
| |
| // todo ? if (alwaysRebuild || isRebuildRequired(genericJarFile, jarFile)) |
| buildJOnASJar(baseName,genericJarFile, jarFile,files,publicId); |
| |
| if (!keepGeneric) { |
| log("deleting generic jar " + genericJarFile.toString(), |
| Project.MSG_VERBOSE); |
| genericJarFile.delete(); |
| } |
| } |
| |
| /** |
| * Helper method invoked by execute() for each JOnAS jar to be built. |
| * Encapsulates the logic of constructing a java task for calling |
| * GenIC and executing it. |
| * @param inBaseName the base name of the jar |
| * @param inSourceJar java.io.File representing the source (EJB1.1) jarfile. |
| * @param someFiles list of files in the jar. Add all the new genererated |
| * files. |
| * @param inPublicId the link to DTD (to rewrite JAR). |
| **/ |
| private void buildJOnASJar(final String inBaseName, |
| final File inSourceJar,final File inDestJar, |
| final Hashtable someFiles,String inPublicId) { |
| org.apache.tools.ant.taskdefs.Java aJavaTask = null; |
| String aGenIcClassName = genicClass; |
| boolean isOldGenIC = false; |
| boolean isTempDirectory = false; |
| File anOutputDirectoryFile = null; |
| |
| // do not call GenIC |
| // only copy file |
| if (noGENIC) { |
| try { |
| FileUtils.newFileUtils().copyFile(inSourceJar, inDestJar); |
| return; |
| } catch (IOException anIOException) { |
| throw new BuildException("Unable to write EJB jar", anIOException); |
| } |
| } |
| |
| // call GenIC |
| try { |
| aJavaTask = (Java) getTask().getProject().createTask("java"); |
| aJavaTask.setTaskName("genic"); |
| if(aGenIcClassName == null) { |
| aGenIcClassName = GENIC_CLASS; |
| } else if( OLD_GENIC_CLASS.equals(aGenIcClassName) ){ |
| isOldGenIC = true; |
| } |
| // ClassName |
| aJavaTask.setClassname(aGenIcClassName); |
| |
| // JVM Args |
| if( jonasroot == null ) { |
| throw new BuildException("Error : set the jonasroot parameter"); |
| } else if ( ! jonasroot.isDirectory() ) { |
| log("jonasroot attribut '" + jonasroot + "' is not a valid directory", |
| Project.MSG_ERR); |
| } |
| aJavaTask.createJvmarg().setValue("-Dinstall.root=" + jonasroot); |
| File aJavaPolicyFile = new File(jonasroot,"config/java.policy"); |
| if( aJavaPolicyFile.exists() ) { |
| aJavaTask.createJvmarg().setValue("-Djava.security.policy=" |
| + aJavaPolicyFile.toString() ); |
| } |
| |
| // Find output directory |
| if( ouputdirectory == null ) { |
| anOutputDirectoryFile = createTempDir(); |
| isTempDirectory = true; |
| log("Use temporary output directory : " + |
| anOutputDirectoryFile, Project.MSG_VERBOSE); |
| } else { |
| anOutputDirectoryFile = ouputdirectory; |
| log("Use temporary specific output directory : " + |
| anOutputDirectoryFile, Project.MSG_VERBOSE); |
| } |
| aJavaTask.createArg().setValue("-d"); |
| aJavaTask.createArg().setFile(anOutputDirectoryFile); |
| |
| // Additionnal args |
| aJavaTask.createArg().setLine(additionalArgs); |
| // KeepGenerated |
| if (keepgenerated) { |
| aJavaTask.createArg().setValue("-keepgenerated"); |
| } |
| |
| // Verbose |
| if( verbose ) { |
| aJavaTask.createArg().setValue("-verbose"); |
| } |
| |
| // -secpropag |
| if( secpropag ) { |
| aJavaTask.createArg().setValue("-secpropag"); |
| } |
| |
| // The compiler |
| if (compiler == null) { |
| // try to use the compiler specified by build.compiler. Right now we are just going |
| // to allow Jikes |
| String aBuildCompiler = getTask().getProject().getProperty("build.compiler"); |
| if ("jikes".equals(aBuildCompiler) ) { |
| aJavaTask.createArg().setValue("-javac"); |
| aJavaTask.createArg().setValue("jikes"); |
| } |
| } else { |
| if( ! "default".equals( compiler ) ) { |
| aJavaTask.createArg().setValue("-javac"); |
| aJavaTask.createArg().setLine(compiler); |
| } |
| } |
| |
| if( ! isOldGenIC ) { |
| // the add in jar features is buggy... |
| aJavaTask.createArg().setValue("-noaddinjar"); |
| } |
| |
| aJavaTask.createArg().setValue(inSourceJar.getPath()); |
| |
| // try to create the classpath for the correct ORB |
| Path aClasspath = getCombinedClasspath(); |
| if( aClasspath == null ) { |
| aClasspath = new Path(getTask().getProject()); |
| } |
| if( orb != null ) { |
| String aOrbJar = new File(jonasroot,"lib/" + orb + "_jonas.jar").toString(); |
| String aConfigDir = new File(jonasroot,"config/").toString(); |
| Path aJOnASOrbPath = new Path(aClasspath.getProject(), |
| aOrbJar + File.pathSeparator + aConfigDir ); |
| aClasspath.append( aJOnASOrbPath ); |
| } else { |
| log("No ORB propertie setup (RMI, JEREMIE, DAVID).", Project.MSG_WARN); |
| } |
| |
| // append the output directory |
| aClasspath.append( new Path(aClasspath.getProject(), anOutputDirectoryFile.getPath())); |
| aJavaTask.setClasspath(aClasspath); |
| |
| |
| aJavaTask.setFork(true); |
| |
| log("Calling " + aGenIcClassName + " for " + inSourceJar.toString(), |
| Project.MSG_VERBOSE); |
| |
| if (aJavaTask.executeJava() != 0) { |
| throw new BuildException("GenIC reported an error"); |
| } |
| // Update the list of files. |
| addAllFiles(anOutputDirectoryFile,"",someFiles); |
| |
| // rewrite the jar with the new files |
| super.writeJar(inBaseName, inDestJar, someFiles, inPublicId); |
| } catch(BuildException aBuildException) { |
| throw aBuildException; |
| } catch (Exception e) { |
| // Have to catch this because of the semantics of calling main() |
| String msg = "Exception while calling " + aGenIcClassName + ". Details: " + e.toString(); |
| throw new BuildException(msg, e); |
| } finally { |
| if( isTempDirectory && anOutputDirectoryFile != null) { |
| dellAllFiles(anOutputDirectoryFile); |
| } else if( cleanWorkDir && anOutputDirectoryFile != null) { |
| dellAllFilesInside(anOutputDirectoryFile); |
| } |
| } |
| } |
| |
| /** |
| * Get the vendor specific name of the Jar that will be output. The |
| * modification date of this jar will be checked against the dependent |
| * bean classes. |
| **/ |
| File getVendorOutputJarFile(final String aBaseName) { |
| return new File(getDestDir(), aBaseName + jarSuffix); |
| } |
| |
| /** |
| * Create a free tempory directory for GenIC output. |
| * @return directory file |
| * @throws BuildException if impossible to find a tempory directory |
| **/ |
| private File createTempDir() { |
| String theTempDir = System.getProperty("java.io.tmpdir"); |
| int anIndice = 0; |
| File aFile = null; |
| // try 50 times to find a free tempory directory |
| while( anIndice < 50 && aFile == null) { |
| aFile = new File(theTempDir,"GenicTemp" + anIndice); |
| if(aFile.exists()) { |
| anIndice++; |
| aFile = null; |
| } |
| } |
| |
| if( aFile == null ) { |
| // problem in temp directory |
| throw new BuildException("Impossible to find a free temp directory for output."); |
| } else { |
| aFile.mkdirs(); |
| return(aFile); |
| } |
| } |
| |
| |
| /** |
| * add all files in anOutputDir + ' / ' + aRootDir to the HashTable someFiles. |
| * |
| * @param anOutputDir - start directory |
| * @param aCurrentDirOrFile - a sub-directory to scan or a file to add. |
| * @param someFiles - where to add the files |
| **/ |
| private void addAllFiles(final File anOutputDir, String aCurrentDirOrFile, Hashtable someFiles) { |
| File aFile = new File(anOutputDir,aCurrentDirOrFile); |
| if( aFile.isDirectory() ) { |
| String aCurrentDir = ""; |
| if( aCurrentDirOrFile.length() > 0 ) { |
| aCurrentDir = aCurrentDirOrFile + '/'; |
| } |
| File theFiles[] = aFile.listFiles(); |
| for(int i=0;i<theFiles.length;i++) { |
| addAllFiles(anOutputDir,aCurrentDir + theFiles[i].getName(),someFiles); |
| } |
| } else { |
| // is a file |
| someFiles.put(aCurrentDirOrFile,aFile); |
| } |
| } |
| |
| /** |
| * Delete all the files in a directory |
| * @param aFile file to delete recursivly |
| **/ |
| private void dellAllFiles(File aFile) { |
| if(aFile.isDirectory()) { |
| File someFiles[] = aFile.listFiles(); |
| for(int i=0;i<someFiles.length;i++) { |
| dellAllFiles(someFiles[i]); |
| } |
| } |
| aFile.delete(); |
| } |
| |
| /** |
| * Delete all the files in a directory, but don't delete |
| * the directory |
| * @param aFile file to delete recursivly |
| **/ |
| private void dellAllFilesInside(File aFile) { |
| if(aFile.isDirectory()) { |
| File someFiles[] = aFile.listFiles(); |
| for(int i=0;i<someFiles.length;i++) { |
| dellAllFiles(someFiles[i]); |
| } |
| } |
| } |
| |
| } |
| // eof. |