KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tools > ant > taskdefs > optional > sun > appserv > UpdateTask


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23
24 /*
25  * The Apache Software License, Version 1.1
26  *
27  * Copyright (c) 1999 The Apache Software Foundation. All rights
28  * reserved.
29  *
30  * Redistribution and use in source and binary forms, with or without
31  * modification, are permitted provided that the following conditions
32  * are met:
33  *
34  * 1. Redistributions of source code must retain the above copyright
35  * notice, this list of conditions and the following disclaimer.
36  *
37  * 2. Redistributions in binary form must reproduce the above copyright
38  * notice, this list of conditions and the following disclaimer in
39  * the documentation and/or other materials provided with the
40  * distribution.
41  *
42  * 3. The end-user documentation included with the redistribution, if
43  * any, must include the following acknowlegement:
44  * "This product includes software developed by the
45  * Apache Software Foundation (http://www.apache.org/)."
46  * Alternately, this acknowlegement may appear in the software itself,
47  * if and wherever such third-party acknowlegements normally appear.
48  *
49  * 4. The names "The Jakarta Project", "Ant", and "Apache Software
50  * Foundation" must not be used to endorse or promote products derived
51  * from this software without prior written permission. For written
52  * permission, please contact apache@apache.org.
53  *
54  * 5. Products derived from this software may not be called "Apache"
55  * nor may "Apache" appear in their names without prior written
56  * permission of the Apache Group.
57  *
58  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
59  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
60  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
61  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
62  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
63  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
64  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
65  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
66  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
67  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
68  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69  * SUCH DAMAGE.
70  * ====================================================================
71  *
72  * This software consists of voluntary contributions made by many
73  * individuals on behalf of the Apache Software Foundation. For more
74  * information on the Apache Software Foundation, please see
75  * <http://www.apache.org/>.
76  */

77
78 package org.apache.tools.ant.taskdefs.optional.sun.appserv;
79
80 import org.apache.tools.ant.Task;
81 import org.apache.tools.ant.AntClassLoader;
82 import org.apache.tools.ant.types.Path;
83 import org.apache.tools.ant.Project;
84 import org.apache.tools.ant.Target;
85 import org.apache.tools.ant.BuildException;
86 import org.apache.tools.ant.DirectoryScanner;
87 import org.apache.tools.ant.types.FileSet;
88 import org.apache.tools.ant.types.ZipFileSet;
89 import org.apache.tools.ant.taskdefs.Jar;
90
91 import java.io.*;
92 import java.util.*;
93 import java.lang.reflect.Field JavaDoc;
94 import java.net.URL JavaDoc;
95
96 /**
97  * This is the implementation for the Ant task <sun-appserv-update>.
98  * This task updates J2EE components previously deployed in the J2EE 1.4 SDK and
99  * Sun ONE Application Server 8. The following components may be updated:
100  * <ul>
101  * <li>Enterprise application (EAR file)
102  * <li>Web application (WAR file)
103  * <li>Enterprise Java Bean (EJB-JAR file)
104  * <li>Enterprise connector (RAR file)
105  * </ul>
106  * The name of this task as used in build.xml will be sun-appserv-update.
107  * This task uses ear/jar/war tasks from the user's Ant project
108  * to find the contents of the components to be updated.
109  * <p>
110  * The attributes of this task are: <br>
111  * file="REQUIRED" <br>
112  * domain="OPTIONAL" (default: "domain1") <br>
113  * <p>
114  *
115  * TODO: what if ear/jar/war task is called with dynamically changing property?
116  * TODO: if XML desc changed, automatically reassemble and redeploy app ??
117  * TODO: what if deployment changes XML descs (e.g. adds default values) ??
118  *
119  * @author Sanjeev Krishnan <a HREF="mailto:sanjeev.krishnan@sun.com">sanjeev.krishnan@sun.com</a>
120  */

121 public class UpdateTask extends Task {
122
123     private static final boolean debug = false;
124
125     private String JavaDoc file;
126     private String JavaDoc sunonehome = null;
127     private String JavaDoc domain = "domain1";
128
129     private ArrayList fromFiles;
130     private ArrayList toFiles;;
131
132     LocalStringsManager lsm = new LocalStringsManager();
133
134     /**
135      * Set the application/module name.
136      */

137     public void setFile(String JavaDoc file) {
138         // file may have the wrong separator char, "new File(..)" fixes it
139
this.file = new File(file).getPath();
140     }
141
142     /**
143      * Set the name of the domain where this app is deployed (default: domain1).
144      */

145     public void setDomain(String JavaDoc domain) {
146     this.domain = domain;
147     }
148
149     /**
150      * Execute the task.
151      */

152     public void execute() throws BuildException {
153
154     if ( file == null || file.equals("") ) {
155         throw new BuildException(lsm.getString("AttributeFileNoProvided"));
156     }
157
158     try {
159         if ( sunonehome == null ) {
160         // figure out sunonehome from sun-appserv-ant.jar
161
ClassLoader JavaDoc cl = this.getClass().getClassLoader();
162         URL JavaDoc url = cl.getResource(
163                "org/apache/tools/ant/taskdefs/defaults.properties");
164         String JavaDoc path = new File(url.getFile()).getPath();
165         // path is like "<SUNONE_HOME>/lib/sun-appserv-ant.jar...."
166

167         // remove any file: prefix
168
if ( path.indexOf("file:") != -1 ) {
169             path = path.substring(5);
170         }
171
172         // remove the /lib/sun-appserv-ant.jar.... suffix.
173
int jarIndex = path.indexOf("sun-appserv-ant.jar");
174         sunonehome = path.substring(0, jarIndex - 5);
175         }
176
177         System.out.println(lsm.getString("UpdateMessage", new Object JavaDoc[] {file, sunonehome, domain}));
178
179         // Get the ear/jar/war task that created this app from the project
180
Jar[] creatorTasks = findCreatorTasks(file);
181         if ( creatorTasks == null ) {
182         throw new BuildException(lsm.getString("UnableToCreateArchive", new Object JavaDoc[] {file}));
183         }
184         if ( debug ) {
185         System.out.println(lsm.getString("TaskThatCreatedArchive", new Object JavaDoc[] {file}));
186         }
187
188         // Initialize list of files to be copied
189
fromFiles = new ArrayList();
190         toFiles = new ArrayList();
191
192         // Phase 1: make list of files to be copied
193
String JavaDoc sep = File.separator;
194         String JavaDoc appsDirName = sunonehome + sep + "domains" + sep +
195                  domain + sep + "applications";
196         String JavaDoc appname = getAppNameFromFile(file);
197         String JavaDoc deployedDir;
198         if ( file.endsWith(".ear") ) {
199         // The app directory is like
200
// domains/domain1/server/applications/j2ee-apps/appname
201
String JavaDoc j2eeAppsDir = appsDirName + sep + "j2ee-apps";
202         deployedDir = j2eeAppsDir + File.separator + appname;
203
204         // Get JAR/WAR/RAR modules in this EAR
205
String JavaDoc[] moduleFiles = getModuleFiles(creatorTasks, file);
206
207         // Call updateModule for each module in the EAR
208
for ( int i=0; i<moduleFiles.length; i++ ) {
209             String JavaDoc modFile = moduleFiles[i];
210
211             // Get the task that created this module
212
Jar[] modCreatorTasks = findCreatorTasks(modFile);
213             if ( modCreatorTasks == null ) {
214             System.err.println(lsm.getString("UnableToFindTask", new Object JavaDoc[] {modFile}));
215             continue;
216             }
217
218             // Get the dir where module is deployed
219
String JavaDoc modName = getAppNameFromFile(modFile);
220             String JavaDoc modDeployedDir;
221             if ( modFile.endsWith(".war") ) {
222             modDeployedDir = deployedDir + sep + modName + "_war";
223             }
224             else if ( modFile.endsWith(".jar") ) {
225             modDeployedDir = deployedDir + sep + modName + "_jar";
226             }
227             else if ( modFile.endsWith(".rar") ) {
228             modDeployedDir = deployedDir + sep + modName + "_rar";
229             }
230             else if ( modFile.equals(file) ) {
231             modDeployedDir = deployedDir;
232             }
233             else {
234             System.err.println(lsm.getString("InvalidModule", new Object JavaDoc[] {modFile}));
235             continue;
236             }
237         
238             updateModule(modCreatorTasks, modDeployedDir);
239         }
240         }
241         else {
242         // A standalone JAR/WAR module, the directory is
243
// domains/domain1/server/applications/j2ee-modules.
244
// XXX Dir will be named j2ee-web-modules, j2ee-ejb-modules,
245
// j2ee-rar-modules based on latest S1AS file layout proposal.
246
String JavaDoc modulesDir = appsDirName + sep + "j2ee-modules";
247         deployedDir = modulesDir + sep + appname;
248
249         updateModule(creatorTasks, deployedDir);
250         }
251
252         // Phase 2: copy files
253
if ( fromFiles.size() > 0 ) {
254         for ( int i=0; i<fromFiles.size(); i++ ) {
255             copyFile((File)fromFiles.get(i), (File)toFiles.get(i));
256         }
257
258         // Touch the .reload file in deployedDir to cause reload.
259
File reload = new File(deployedDir, ".reload");
260         if ( !reload.createNewFile() ) {
261             reload.setLastModified(System.currentTimeMillis());
262         }
263
264         System.out.println(lsm.getString("AplicationUpdated"));
265         }
266         else {
267             System.out.println(lsm.getString("FilesUpdateToDate"));
268         }
269
270     } catch ( Exception JavaDoc ex ) {
271         System.err.println(lsm.getString("UpdateError"));
272         if ( debug )
273         ex.printStackTrace();
274         throw new BuildException(ex);
275     }
276     }
277
278
279     /**
280      * Return an array of JAR/WAR/RAR modules in the earFile.
281      */

282     private String JavaDoc[] getModuleFiles(Jar[] earTasks, String JavaDoc earFile)
283                         throws BuildException {
284     // Get the filesets of the EAR
285
ArrayList filesets = getFilesets(earTasks);
286
287     // Iterate over each fileset
288
ArrayList modules = new ArrayList();
289     for ( int i=0; i<filesets.size(); i++ ) {
290         FileSet fs = (FileSet)filesets.get(i);
291
292         // If an invalid fileset, ignore it
293
if ( !fs.getDir(getProject()).exists() )
294         continue;
295
296         // get list of files from FileSet
297
DirectoryScanner ds = fs.getDirectoryScanner(getProject());
298         File fromDir = fs.getDir(getProject());
299
300         String JavaDoc[] files = ds.getIncludedFiles();
301         for ( int j=0; j<files.length; j++ ) {
302         String JavaDoc f = files[j];
303         if ( f.endsWith(".jar") || f.endsWith(".war")
304                     || f.endsWith(".rar") ) {
305             modules.add(new File(fromDir, f).toString());
306         }
307         }
308     }
309     modules.add(earFile);
310     
311     return (String JavaDoc[])modules.toArray(new String JavaDoc[modules.size()]);
312     }
313
314
315     /**
316      * Update contents of the module in the appserver's repository.
317      */

318     private void updateModule(Jar[] creatorTasks, String JavaDoc deployedDir)
319                         throws BuildException {
320
321     try {
322         File deployedDirFile = new File(deployedDir);
323         if ( !deployedDirFile.exists() ) {
324         System.err.println(lsm.getString("ModuleDoesNotExist", new Object JavaDoc[] {file}));
325         return;
326         }
327
328         // Get the filesets of the archive from the jar/war Task.
329
ArrayList filesets = getFilesets(creatorTasks);
330
331         // Iterate over each fileset
332
for ( int i=0; i<filesets.size(); i++ ) {
333         FileSet fs = (FileSet)filesets.get(i);
334
335                 // If an invalid fileset, ignore it
336
if ( !fs.getDir(getProject()).exists() )
337                     continue;
338
339         // get list of files from FileSet
340
DirectoryScanner ds = fs.getDirectoryScanner(getProject());
341                 File fromDir = fs.getDir(getProject());
342                 String JavaDoc[] srcFiles = ds.getIncludedFiles();
343
344         String JavaDoc prefix = "";
345         String JavaDoc fullpath = "";
346         if ( fs instanceof ZipFileSet ) {
347             ZipFileSet zfs = (ZipFileSet)fs;
348             // Below calls to getPrefix and getFullpath work only
349
// on Ant 1.6.2 and higher.
350
String JavaDoc tmpPrefix = zfs.getPrefix(getProject());
351             String JavaDoc tmpFullpath = zfs.getFullpath(getProject());
352             if ( tmpPrefix != null && !tmpPrefix.equals("") ) {
353             prefix = tmpPrefix;
354             }
355             else if ( tmpFullpath != null && !tmpFullpath.equals("") ) {
356             // This means the fileset contains a single file
357
// which is at the exact location of fullpath.
358
fullpath = tmpFullpath;
359             }
360
361             // XXX support src attr of ZipFileSet
362
// XXX support zipgroupfileset.
363
}
364
365         // For EAR files, only update stuff in META-INF
366
if ( file.endsWith(".ear") ) {
367             if ( fullpath.equals("META-INF/application.xml")
368                 || prefix.startsWith("META-INF") ) {
369             compareAndCopy(fromDir, srcFiles,
370                        deployedDirFile, prefix, fullpath);
371             }
372         }
373         else {
374             compareAndCopy(fromDir, srcFiles,
375                    deployedDirFile, prefix, fullpath);
376         }
377         }
378
379     } catch ( Exception JavaDoc ex ) {
380         System.err.println(lsm.getString("UpdateError"));
381         if ( debug )
382         ex.printStackTrace();
383         throw new BuildException(ex);
384     }
385     }
386
387
388     /**
389      * Get the name of the J2EE application from the archive file.
390      */

391     private String JavaDoc getAppNameFromFile(String JavaDoc file) {
392     String JavaDoc appname = file.substring(0, file.length()-4); // remove .ext
393
if ( appname.lastIndexOf(File.separator) != -1 ) {
394         appname = appname.substring(appname.lastIndexOf(File.separator)+1);
395     }
396     return appname;
397     }
398
399
400     /**
401      * Search all Ant targets in this project for the ear/jar/war tasks
402      * that created the given archive file.
403      * @return null if no task could be found
404      */

405     private Jar[] findCreatorTasks(String JavaDoc file) throws IOException {
406
407     if ( debug ) {
408         System.err.println("In findCreatorTasks for file " + file
409         + " canonical path is " + new File(file).getCanonicalPath());
410     }
411
412     Hashtable targets = project.getTargets();
413     Enumeration e = targets.elements();
414     ArrayList creators = new ArrayList();
415     while ( e.hasMoreElements() ) {
416         Target t = (Target)e.nextElement();
417         Task[] tasks = t.getTasks();
418
419         // For Ant 1.6.2: initialize UnknownElements so that the
420
// actual Jar tasks are created.
421
for ( int i=0; i<tasks.length; i++ ) {
422         if ( tasks[i] instanceof org.apache.tools.ant.UnknownElement ) {
423                     try {
424                         tasks[i].maybeConfigure();
425                     } catch ( Exception JavaDoc ex ) {
426                         // Ignore.
427
}
428         }
429         }
430
431         tasks = t.getTasks();
432         for ( int i=0; i<tasks.length; i++ ) {
433         // Note: Ear and War are subclasses of Jar
434
if ( tasks[i] instanceof org.apache.tools.ant.taskdefs.Jar ) {
435
436             Jar task = (Jar)tasks[i];
437
438             // make sure that attributes are set on the task
439
try {
440             task.maybeConfigure();
441             } catch ( Exception JavaDoc ex ) {
442             // Ignore.
443
}
444
445             //if ( debug ) {
446
// System.err.println("Checking task that created "
447
// + task.getDestFile());
448
//}
449

450             // check if this task created our archive file.
451
if ( task.getDestFile() != null
452              && task.getDestFile().getCanonicalPath().equals(
453                     new File(file).getCanonicalPath()) ) {
454             creators.add(task);
455             }
456         }
457         }
458     }
459
460     if ( creators.size() == 0 ) {
461         return null;
462     }
463     else {
464         return (Jar[])creators.toArray(new Jar[creators.size()]);
465     }
466     }
467
468
469     /**
470      * Get the list of filesets that describe the contents of the archive
471      * created by the task.
472      */

473     private ArrayList getFilesets(Jar[] tasks) throws BuildException {
474
475     try {
476         // The Zip class has a private filesets field, and the
477
// MatchingTask class has a protected field fileset. Get them using
478
// reflection because theres no getter methods for them :-(
479
// No problems till the current Ant 1.6.1.
480

481         Class JavaDoc zipClass = Class.forName("org.apache.tools.ant.taskdefs.Zip");
482         Field JavaDoc filesetsField = zipClass.getDeclaredField("filesets");
483         filesetsField.setAccessible(true);
484         Field JavaDoc basedirField = zipClass.getDeclaredField("baseDir");
485         basedirField.setAccessible(true);
486
487         Class JavaDoc mtClass = Class.forName(
488                 "org.apache.tools.ant.taskdefs.MatchingTask");
489         Field JavaDoc filesetField = mtClass.getDeclaredField("fileset");
490         filesetField.setAccessible(true);
491
492         ArrayList filesets = new ArrayList();
493
494         for ( int i=0; i<tasks.length; i++ ) {
495
496         // get the nested fileset elements of the task
497
Vector fs = (Vector)filesetsField.get(tasks[i]);
498         filesets.addAll(fs);
499
500         // get the implicit fileset of the task
501
FileSet implFileset = (FileSet)filesetField.get(tasks[i]);
502         File baseDir = (File)basedirField.get(tasks[i]);
503         if ( implFileset != null && baseDir != null ) {
504             FileSet fileset = (FileSet)implFileset.clone();
505             fileset.setDir(baseDir);
506             filesets.add(fileset);
507         }
508         }
509
510         return filesets;
511
512     } catch ( Exception JavaDoc ex ) {
513         throw (BuildException)(new BuildException().initCause(ex));
514     }
515     }
516
517
518     /**
519      * Compare last modified timestamps of srcFiles in fromDir with the
520      * timestamps in toDir, copy if fromDir file has later timestamp.
521      */

522     private void compareAndCopy(File fromDir, String JavaDoc[] srcFiles, File toDir,
523                    String JavaDoc prefix, String JavaDoc fullpath)
524     {
525     if ( prefix != null && !prefix.equals("") ) {
526         toDir = new File(toDir, prefix);
527     }
528
529     for ( int i=0; i<srcFiles.length; i++ ) {
530         String JavaDoc srcFile = srcFiles[i];
531
532         if ( debug ) {
533         System.out.println("In compareAndCopy, fromDir = " + fromDir
534             + " srcFile = " + srcFile + " toDir = " + toDir
535             + " prefix = " + prefix + " fullpath = " + fullpath);
536         }
537
538         File from = new File(fromDir, srcFile);
539         File to;
540         if ( fullpath != null && !fullpath.equals("") ) {
541         to = new File(toDir, fullpath);
542         }
543         else {
544         to = new File(toDir, srcFile);
545         }
546         if ( from.lastModified() > to.lastModified() ) {
547         fromFiles.add(from);
548         toFiles.add(to);
549         }
550     }
551     }
552
553     private void copyFile(File from, File to) throws BuildException {
554
555     System.out.println("Copying file " + from + " to " + to);
556
557     FileInputStream in = null;
558     FileOutputStream out = null;
559     try {
560         if ( !to.exists() ) {
561         if ( !to.getParentFile().exists() ) {
562             // create all parent dirs
563
to.getParentFile().mkdirs();
564         }
565         to.createNewFile();
566         }
567
568         in = new FileInputStream(from);
569         out = new FileOutputStream(to);
570
571         byte[] buffer = new byte[8 * 1024];
572         int count = 0;
573         while ( (count = in.read(buffer, 0, buffer.length)) != -1 ) {
574         out.write(buffer, 0, count);
575         }
576
577     } catch ( Exception JavaDoc ex ) {
578         throw new RuntimeException JavaDoc(lsm.getString("UnableToCopy", new Object JavaDoc[] {from}), ex);
579     } finally {
580         try {
581         if (out != null) {
582             out.close();
583         }
584         if (in != null) {
585             in.close();
586         }
587         } catch ( Exception JavaDoc ex ) {}
588     }
589     }
590 }
591
Popular Tags