Package org.apache.tools.ant.taskdefs.optional.sun.appserv

Source Code of org.apache.tools.ant.taskdefs.optional.sun.appserv.UpdateTask

/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License").  You
* may not use this file except in compliance with the License. You can obtain
* a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
* or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code.  If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: "Portions Copyrighted [year]
* [name of copyright owner]"
*
* Contributor(s):
*
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license."  If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above.  However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/

/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999 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.sun.appserv;

import org.apache.tools.ant.Task;
import org.apache.tools.ant.AntClassLoader;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Target;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.ZipFileSet;
import org.apache.tools.ant.taskdefs.Jar;

import java.io.*;
import java.util.*;
import java.lang.reflect.Field;
import java.net.URL;

/**
* This is the implementation for the Ant task <sun-appserv-update>.
* 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:
*   <ul>
*     <li>Enterprise application (EAR file)
*     <li>Web application (WAR file)
*     <li>Enterprise Java Bean (EJB-JAR file)
*     <li>Enterprise connector (RAR file)
*   </ul>
* 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.
* <p>
* The attributes of this task are: <br>
*    file="REQUIRED"  <br>
*    domain="OPTIONAL" (default: "domain1")   <br>
* <p>
*
* 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 <a href="mailto:sanjeev.krishnan@sun.com">sanjeev.krishnan@sun.com</a>
*/
public class UpdateTask extends Task {

    private static final boolean debug = false;

    private String file;
    private String sunonehome = null;
    private String domain = "domain1";

    private ArrayList fromFiles;
    private ArrayList toFiles;;

    LocalStringsManager lsm = new LocalStringsManager();

    /**
     * Set the application/module name.
     */
    public void setFile(String file) {
        // file may have the wrong separator char, "new File(..)" fixes it
        this.file = new File(file).getPath();
    }

    /**
     * Set the name of the domain where this app is deployed (default: domain1).
     */
    public void setDomain(String domain) {
  this.domain = domain;
    }

    /**
     * Execute the task.
     */
    public void execute() throws BuildException {

  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);
  }
    }


    /**
     * Return an array of JAR/WAR/RAR modules in the earFile.
     */
    private String[] getModuleFiles(Jar[] earTasks, String earFile)
            throws BuildException {
  // 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()]);
    }


    /**
     * Update contents of the module in the appserver's repository.
     */
    private void updateModule(Jar[] creatorTasks, String deployedDir)
            throws BuildException {

  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);
  }
    }


    /**
     * Get the name of the J2EE application from the archive file.
     */
    private String getAppNameFromFile(String 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;
    }


    /**
     * 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
     */
    private Jar[] findCreatorTasks(String file) throws IOException {

  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()]);
  }
    }


    /**
     * Get the list of filesets that describe the contents of the archive
     * created by the task.
     */
    private ArrayList getFilesets(Jar[] tasks) throws BuildException {

  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));
  }
    }


    /**
     * Compare last modified timestamps of srcFiles in fromDir with the
     * timestamps in toDir, copy if fromDir file has later timestamp.
     */
    private void compareAndCopy(File fromDir, String[] srcFiles, File toDir,
           String prefix, String fullpath)
    {
  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 void copyFile(File from, File to) throws BuildException {

  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 ) {}
  }
    }
}
TOP

Related Classes of org.apache.tools.ant.taskdefs.optional.sun.appserv.UpdateTask

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.