FileDocCategorySizeDatePackage
UpdateTask.javaAPI DocGlassfish v2 API20073Fri May 04 22:32:42 BST 2007org.apache.tools.ant.taskdefs.optional.sun.appserv

UpdateTask

public class UpdateTask extends org.apache.tools.ant.Task
This is the implementation for the Ant task . This task updates J2EE components previously deployed in the J2EE 1.4 SDK and Sun ONE Application Server 8. The following components may be updated:
  • Enterprise application (EAR file)
  • Web application (WAR file)
  • Enterprise Java Bean (EJB-JAR file)
  • Enterprise connector (RAR file)
The name of this task as used in build.xml will be sun-appserv-update. This task uses ear/jar/war tasks from the user's Ant project to find the contents of the components to be updated.

The attributes of this task are:
file="REQUIRED"
domain="OPTIONAL" (default: "domain1")

TODO: what if ear/jar/war task is called with dynamically changing property? TODO: if XML desc changed, automatically reassemble and redeploy app ?? TODO: what if deployment changes XML descs (e.g. adds default values) ??

author
Sanjeev Krishnan sanjeev.krishnan@sun.com

Fields Summary
private static final boolean
debug
private String
file
private String
sunonehome
private String
domain
private ArrayList
fromFiles
private ArrayList
toFiles
LocalStringsManager
lsm
Constructors Summary
Methods Summary
private voidcompareAndCopy(java.io.File fromDir, java.lang.String[] srcFiles, java.io.File toDir, java.lang.String prefix, java.lang.String fullpath)
Compare last modified timestamps of srcFiles in fromDir with the timestamps in toDir, copy if fromDir file has later timestamp.

	if ( prefix != null && !prefix.equals("") ) {
	    toDir = new File(toDir, prefix);
	}

	for ( int i=0; i<srcFiles.length; i++ ) {
	    String srcFile = srcFiles[i];

	    if ( debug ) {
		System.out.println("In compareAndCopy, fromDir = " + fromDir 
		    + " srcFile = " + srcFile + " toDir = " + toDir 
		    + " prefix = " + prefix + " fullpath = " + fullpath);
	    }

	    File from = new File(fromDir, srcFile);
	    File to;
	    if ( fullpath != null && !fullpath.equals("") ) {
		to = new File(toDir, fullpath);
	    }
	    else {
		to = new File(toDir, srcFile);
	    }
	    if ( from.lastModified() > to.lastModified() ) {
		fromFiles.add(from);
		toFiles.add(to);
	    }
	}
    
private voidcopyFile(java.io.File from, java.io.File to)


	System.out.println("Copying file " + from + " to " + to);

	FileInputStream in = null;
	FileOutputStream out = null;
	try {
	    if ( !to.exists() ) {
		if ( !to.getParentFile().exists() ) {
		    // create all parent dirs
		    to.getParentFile().mkdirs();
		}
		to.createNewFile();
	    }

	    in = new FileInputStream(from);
	    out = new FileOutputStream(to);

	    byte[] buffer = new byte[8 * 1024];
	    int count = 0;
	    while ( (count = in.read(buffer, 0, buffer.length)) != -1 ) {
		out.write(buffer, 0, count);
	    } 

	} catch ( Exception ex ) {
	    throw new RuntimeException(lsm.getString("UnableToCopy", new Object[] {from}), ex);
	} finally {
	    try {
		if (out != null) {
		    out.close();
		}
		if (in != null) {
		    in.close();
		}
	    } catch ( Exception ex ) {}
	}
    
public voidexecute()
Execute the task.


	if ( file == null || file.equals("") ) {
	    throw new BuildException(lsm.getString("AttributeFileNoProvided"));
	}

	try {
	    if ( sunonehome == null ) {
		// figure out sunonehome from sun-appserv-ant.jar
		ClassLoader cl = this.getClass().getClassLoader();
		URL url = cl.getResource(
			   "org/apache/tools/ant/taskdefs/defaults.properties");
		String path = new File(url.getFile()).getPath();
		// path is like "<SUNONE_HOME>/lib/sun-appserv-ant.jar...."

		// remove any file: prefix
		if ( path.indexOf("file:") != -1 ) {
		    path = path.substring(5);
		}

		// remove the /lib/sun-appserv-ant.jar.... suffix.
		int jarIndex = path.indexOf("sun-appserv-ant.jar");
		sunonehome = path.substring(0, jarIndex - 5);
	    }

	    System.out.println(lsm.getString("UpdateMessage", new Object[] {file, sunonehome, domain}));

	    // Get the ear/jar/war task that created this app from the project
	    Jar[] creatorTasks = findCreatorTasks(file);
	    if ( creatorTasks == null ) {
		throw new BuildException(lsm.getString("UnableToCreateArchive", new Object[] {file})); 
	    }
	    if ( debug ) {
		System.out.println(lsm.getString("TaskThatCreatedArchive", new Object[] {file}));
	    }

	    // Initialize list of files to be copied
	    fromFiles = new ArrayList();
	    toFiles = new ArrayList();

	    // Phase 1: make list of files to be copied
	    String sep = File.separator;
	    String appsDirName = sunonehome + sep + "domains" + sep + 
				 domain + sep + "applications";
	    String appname = getAppNameFromFile(file);
	    String deployedDir;
	    if ( file.endsWith(".ear") ) {
		// The app directory is like
		// domains/domain1/server/applications/j2ee-apps/appname
		String j2eeAppsDir = appsDirName + sep + "j2ee-apps";
		deployedDir = j2eeAppsDir + File.separator + appname;

		// Get JAR/WAR/RAR modules in this EAR
		String[] moduleFiles = getModuleFiles(creatorTasks, file);

		// Call updateModule for each module in the EAR
		for ( int i=0; i<moduleFiles.length; i++ ) {
		    String modFile = moduleFiles[i];

		    // Get the task that created this module
		    Jar[] modCreatorTasks = findCreatorTasks(modFile);    
		    if ( modCreatorTasks == null ) {
			System.err.println(lsm.getString("UnableToFindTask", new Object[] {modFile})); 
			continue;
		    }

		    // Get the dir where module is deployed
		    String modName = getAppNameFromFile(modFile);
		    String modDeployedDir;
		    if ( modFile.endsWith(".war") ) {
			modDeployedDir = deployedDir + sep + modName + "_war";
		    }
		    else if ( modFile.endsWith(".jar") ) {
			modDeployedDir = deployedDir + sep + modName + "_jar";
		    }
		    else if ( modFile.endsWith(".rar") ) {
			modDeployedDir = deployedDir + sep + modName + "_rar";
		    }
		    else if ( modFile.equals(file) ) {
			modDeployedDir = deployedDir;
		    }
		    else {
			System.err.println(lsm.getString("InvalidModule", new Object[] {modFile}));
			continue;
		    }
	    
		    updateModule(modCreatorTasks, modDeployedDir);
		}
	    }
	    else { 
		// A standalone JAR/WAR module, the directory is 
		// domains/domain1/server/applications/j2ee-modules.
		// XXX Dir will be named j2ee-web-modules, j2ee-ejb-modules,
		// j2ee-rar-modules based on latest S1AS file layout proposal.
		String modulesDir = appsDirName + sep + "j2ee-modules";
		deployedDir = modulesDir + sep + appname;

		updateModule(creatorTasks, deployedDir);
	    }

	    // Phase 2: copy files
	    if ( fromFiles.size() > 0 ) {
		for ( int i=0; i<fromFiles.size(); i++ ) {
		    copyFile((File)fromFiles.get(i), (File)toFiles.get(i));
		}

		// Touch the .reload file in deployedDir to cause reload.
		File reload = new File(deployedDir, ".reload");
		if ( !reload.createNewFile() ) {
		    reload.setLastModified(System.currentTimeMillis());
		}

		System.out.println(lsm.getString("AplicationUpdated"));
	    }
	    else {
            System.out.println(lsm.getString("FilesUpdateToDate"));
	    }

	} catch ( Exception ex ) {
	    System.err.println(lsm.getString("UpdateError"));
	    if ( debug )
		ex.printStackTrace();
	    throw new BuildException(ex);
	}
    
private org.apache.tools.ant.taskdefs.Jar[]findCreatorTasks(java.lang.String file)
Search all Ant targets in this project for the ear/jar/war tasks that created the given archive file.

return
null if no task could be found


	if ( debug ) {
	    System.err.println("In findCreatorTasks for file " + file 
		+ " canonical path is " + new File(file).getCanonicalPath());
	}

	Hashtable targets = project.getTargets();
	Enumeration e = targets.elements();
	ArrayList creators = new ArrayList();
	while ( e.hasMoreElements() ) {
	    Target t = (Target)e.nextElement();
	    Task[] tasks = t.getTasks();

	    // For Ant 1.6.2: initialize UnknownElements so that the
	    // actual Jar tasks are created.
	    for ( int i=0; i<tasks.length; i++ ) {
		if ( tasks[i] instanceof org.apache.tools.ant.UnknownElement ) {
                    try {
                        tasks[i].maybeConfigure();
                    } catch ( Exception ex ) {
                        // Ignore.
                    }
		}
	    }

	    tasks = t.getTasks();
	    for ( int i=0; i<tasks.length; i++ ) {
		// Note: Ear and War are subclasses of Jar
		if ( tasks[i] instanceof org.apache.tools.ant.taskdefs.Jar ) {

		    Jar task = (Jar)tasks[i];

		    // make sure that attributes are set on the task
		    try {
			task.maybeConfigure(); 
		    } catch ( Exception ex ) {
			// Ignore.
		    }

		    //if ( debug ) {
		    //	System.err.println("Checking task that created " 
		    //			    + task.getDestFile());
		    //}

		    // check if this task created our archive file.
		    if ( task.getDestFile() != null 
			 && task.getDestFile().getCanonicalPath().equals(
				    new File(file).getCanonicalPath()) ) {
			creators.add(task);
		    }
		}
	    }
	}

	if ( creators.size() == 0 ) {
	    return null;
	}
	else {
	    return (Jar[])creators.toArray(new Jar[creators.size()]);
	}
    
private java.lang.StringgetAppNameFromFile(java.lang.String file)
Get the name of the J2EE application from the archive file.

	String appname = file.substring(0, file.length()-4); // remove .ext
	if ( appname.lastIndexOf(File.separator) != -1 ) {
	    appname = appname.substring(appname.lastIndexOf(File.separator)+1);
	}
	return appname;
    
private java.util.ArrayListgetFilesets(org.apache.tools.ant.taskdefs.Jar[] tasks)
Get the list of filesets that describe the contents of the archive created by the task.


	try {
	    // The Zip class has a private filesets field, and the
	    // MatchingTask class has a protected field fileset. Get them using 
	    // reflection because theres no getter methods for them :-(
	    // No problems till the current Ant 1.6.1.

	    Class zipClass = Class.forName("org.apache.tools.ant.taskdefs.Zip");
	    Field filesetsField = zipClass.getDeclaredField("filesets");
	    filesetsField.setAccessible(true);
	    Field basedirField = zipClass.getDeclaredField("baseDir");
	    basedirField.setAccessible(true);

	    Class mtClass = Class.forName(
				"org.apache.tools.ant.taskdefs.MatchingTask");
	    Field filesetField = mtClass.getDeclaredField("fileset");
	    filesetField.setAccessible(true);

	    ArrayList filesets = new ArrayList();

	    for ( int i=0; i<tasks.length; i++ ) {

		// get the nested fileset elements of the task
		Vector fs = (Vector)filesetsField.get(tasks[i]);
		filesets.addAll(fs);

		// get the implicit fileset of the task
		FileSet implFileset = (FileSet)filesetField.get(tasks[i]);
		File baseDir = (File)basedirField.get(tasks[i]);
		if ( implFileset != null && baseDir != null ) {
		    FileSet fileset = (FileSet)implFileset.clone();
		    fileset.setDir(baseDir);
		    filesets.add(fileset);
		}
	    }

	    return filesets;

	} catch ( Exception ex ) {
	    throw (BuildException)(new BuildException().initCause(ex));
	}
    
private java.lang.String[]getModuleFiles(org.apache.tools.ant.taskdefs.Jar[] earTasks, java.lang.String earFile)
Return an array of JAR/WAR/RAR modules in the earFile.

	// Get the filesets of the EAR 
	ArrayList filesets = getFilesets(earTasks);

	// Iterate over each fileset
	ArrayList modules = new ArrayList();
	for ( int i=0; i<filesets.size(); i++ ) {
	    FileSet fs = (FileSet)filesets.get(i);

	    // If an invalid fileset, ignore it
	    if ( !fs.getDir(getProject()).exists() )
		continue;

	    // get list of files from FileSet
	    DirectoryScanner ds = fs.getDirectoryScanner(getProject());
	    File fromDir = fs.getDir(getProject());

	    String[] files = ds.getIncludedFiles();
	    for ( int j=0; j<files.length; j++ ) {
		String f = files[j];
		if ( f.endsWith(".jar") || f.endsWith(".war") 
					|| f.endsWith(".rar") ) {
		    modules.add(new File(fromDir, f).toString());
		}
	    }
	}
	modules.add(earFile);
	
	return (String[])modules.toArray(new String[modules.size()]);
    
public voidsetDomain(java.lang.String domain)
Set the name of the domain where this app is deployed (default: domain1).

	this.domain = domain;
    
public voidsetFile(java.lang.String file)
Set the application/module name.


             
        
        // file may have the wrong separator char, "new File(..)" fixes it
        this.file = new File(file).getPath();
    
private voidupdateModule(org.apache.tools.ant.taskdefs.Jar[] creatorTasks, java.lang.String deployedDir)
Update contents of the module in the appserver's repository.


	try {
	    File deployedDirFile = new File(deployedDir);
	    if ( !deployedDirFile.exists() ) {
		System.err.println(lsm.getString("ModuleDoesNotExist", new Object[] {file})); 
		return;
	    }

	    // Get the filesets of the archive from the jar/war Task.
	    ArrayList filesets = getFilesets(creatorTasks);

	    // Iterate over each fileset
	    for ( int i=0; i<filesets.size(); i++ ) {
		FileSet fs = (FileSet)filesets.get(i);

                // If an invalid fileset, ignore it
                if ( !fs.getDir(getProject()).exists() )
                    continue;

		// get list of files from FileSet
                DirectoryScanner ds = fs.getDirectoryScanner(getProject());
                File fromDir = fs.getDir(getProject());
                String[] srcFiles = ds.getIncludedFiles();

		String prefix = "";
		String fullpath = "";
		if ( fs instanceof ZipFileSet ) {
		    ZipFileSet zfs = (ZipFileSet)fs;
		    // Below calls to getPrefix and getFullpath work only
		    // on Ant 1.6.2 and higher.
		    String tmpPrefix = zfs.getPrefix(getProject());
		    String tmpFullpath = zfs.getFullpath(getProject());
		    if ( tmpPrefix != null && !tmpPrefix.equals("") ) {
			prefix = tmpPrefix;
		    }
		    else if ( tmpFullpath != null && !tmpFullpath.equals("") ) {
			// This means the fileset contains a single file
			// which is at the exact location of fullpath.
			fullpath = tmpFullpath;
		    }

		    // XXX support src attr of ZipFileSet
		    // XXX support zipgroupfileset.
		}

		// For EAR files, only update stuff in META-INF
		if ( file.endsWith(".ear") ) {
		    if ( fullpath.equals("META-INF/application.xml") 
			    || prefix.startsWith("META-INF") ) {
			compareAndCopy(fromDir, srcFiles, 
				       deployedDirFile, prefix, fullpath);
		    }
		}
		else {
		    compareAndCopy(fromDir, srcFiles, 
				   deployedDirFile, prefix, fullpath);
		}
	    }

	} catch ( Exception ex ) {
	    System.err.println(lsm.getString("UpdateError"));
	    if ( debug )
		ex.printStackTrace();
	    throw new BuildException(ex);
	}