Save This Page
Home » apache-tomcat-6.0.16-src » org.apache » catalina » startup » [javadoc | source]
    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    * 
    9    *      http://www.apache.org/licenses/LICENSE-2.0
   10    * 
   11    * Unless required by applicable law or agreed to in writing, software
   12    * distributed under the License is distributed on an "AS IS" BASIS,
   13    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    * See the License for the specific language governing permissions and
   15    * limitations under the License.
   16    */
   17   
   18   
   19   package org.apache.catalina.startup;
   20   
   21   import java.io.BufferedOutputStream;
   22   import java.io.File;
   23   import java.io.FileInputStream;
   24   import java.io.FileOutputStream;
   25   import java.io.InputStream;
   26   import java.io.IOException;
   27   import java.net.JarURLConnection;
   28   import java.net.URL;
   29   import java.nio.channels.FileChannel;
   30   import java.util.Enumeration;
   31   import java.util.jar.JarEntry;
   32   import java.util.jar.JarFile;
   33   
   34   import org.apache.catalina.Host;
   35   import org.apache.catalina.util.StringManager;
   36   import org.apache.juli.logging.Log;
   37   import org.apache.juli.logging.LogFactory;
   38   
   39   /**
   40    * Expand out a WAR in a Host's appBase.
   41    *
   42    * @author Craig R. McClanahan
   43    * @author Remy Maucherat
   44    * @author Glenn L. Nielsen
   45    * @version $Revision: 467222 $
   46    */
   47   
   48   public class ExpandWar {
   49   
   50       private static Log log = LogFactory.getLog(ExpandWar.class);
   51   
   52       /**
   53        * The string resources for this package.
   54        */
   55       protected static final StringManager sm =
   56           StringManager.getManager(Constants.Package);
   57   
   58   
   59       /**
   60        * Expand the WAR file found at the specified URL into an unpacked
   61        * directory structure, and return the absolute pathname to the expanded
   62        * directory.
   63        *
   64        * @param host Host war is being installed for
   65        * @param war URL of the web application archive to be expanded
   66        *  (must start with "jar:")
   67        *
   68        * @exception IllegalArgumentException if this is not a "jar:" URL
   69        * @exception IOException if an input/output error was encountered
   70        *  during expansion
   71        */
   72       public static String expand(Host host, URL war)
   73           throws IOException {
   74   
   75           // Calculate the directory name of the expanded directory
   76           if (host.getLogger().isDebugEnabled()) {
   77               host.getLogger().debug("expand(" + war.toString() + ")");
   78           }
   79           String pathname = war.toString().replace('\\', '/');
   80           if (pathname.endsWith("!/")) {
   81               pathname = pathname.substring(0, pathname.length() - 2);
   82           }
   83           int period = pathname.lastIndexOf('.');
   84           if (period >= pathname.length() - 4)
   85               pathname = pathname.substring(0, period);
   86           int slash = pathname.lastIndexOf('/');
   87           if (slash >= 0) {
   88               pathname = pathname.substring(slash + 1);
   89           }
   90           if (host.getLogger().isDebugEnabled()) {
   91               host.getLogger().debug("  Proposed directory name: " + pathname);
   92           }
   93           return expand(host, war, pathname);
   94   
   95       }
   96   
   97   
   98       /**
   99        * Expand the WAR file found at the specified URL into an unpacked
  100        * directory structure, and return the absolute pathname to the expanded
  101        * directory.
  102        *
  103        * @param host Host war is being installed for
  104        * @param war URL of the web application archive to be expanded
  105        *  (must start with "jar:")
  106        * @param pathname Context path name for web application
  107        *
  108        * @exception IllegalArgumentException if this is not a "jar:" URL
  109        * @exception IOException if an input/output error was encountered
  110        *  during expansion
  111        */
  112       public static String expand(Host host, URL war, String pathname)
  113           throws IOException {
  114   
  115           // Make sure that there is no such directory already existing
  116           File appBase = new File(host.getAppBase());
  117           if (!appBase.isAbsolute()) {
  118               appBase = new File(System.getProperty("catalina.base"),
  119                                  host.getAppBase());
  120           }
  121           if (!appBase.exists() || !appBase.isDirectory()) {
  122               throw new IOException
  123                   (sm.getString("hostConfig.appBase",
  124                                 appBase.getAbsolutePath()));
  125           }
  126           File docBase = new File(appBase, pathname);
  127           if (docBase.exists()) {
  128               // War file is already installed
  129               return (docBase.getAbsolutePath());
  130           }
  131   
  132           // Create the new document base directory
  133           docBase.mkdir();
  134   
  135           // Expand the WAR into the new document base directory
  136           JarURLConnection juc = (JarURLConnection) war.openConnection();
  137           juc.setUseCaches(false);
  138           JarFile jarFile = null;
  139           InputStream input = null;
  140           try {
  141               jarFile = juc.getJarFile();
  142               Enumeration jarEntries = jarFile.entries();
  143               while (jarEntries.hasMoreElements()) {
  144                   JarEntry jarEntry = (JarEntry) jarEntries.nextElement();
  145                   String name = jarEntry.getName();
  146                   int last = name.lastIndexOf('/');
  147                   if (last >= 0) {
  148                       File parent = new File(docBase,
  149                                              name.substring(0, last));
  150                       parent.mkdirs();
  151                   }
  152                   if (name.endsWith("/")) {
  153                       continue;
  154                   }
  155                   input = jarFile.getInputStream(jarEntry);
  156   
  157                   // Bugzilla 33636
  158                   File expandedFile = expand(input, docBase, name);
  159                   long lastModified = jarEntry.getTime();
  160                   if ((lastModified != -1) && (lastModified != 0) && (expandedFile != null)) {
  161                       expandedFile.setLastModified(lastModified);
  162                   }
  163   
  164                   input.close();
  165                   input = null;
  166               }
  167           } catch (IOException e) {
  168               // If something went wrong, delete expanded dir to keep things 
  169               // clean
  170               deleteDir(docBase);
  171               throw e;
  172           } finally {
  173               if (input != null) {
  174                   try {
  175                       input.close();
  176                   } catch (Throwable t) {
  177                       ;
  178                   }
  179                   input = null;
  180               }
  181               if (jarFile != null) {
  182                   try {
  183                       jarFile.close();
  184                   } catch (Throwable t) {
  185                       ;
  186                   }
  187                   jarFile = null;
  188               }
  189           }
  190   
  191           // Return the absolute path to our new document base directory
  192           return (docBase.getAbsolutePath());
  193   
  194       }
  195   
  196   
  197       /**
  198        * Copy the specified file or directory to the destination.
  199        *
  200        * @param src File object representing the source
  201        * @param dest File object representing the destination
  202        */
  203       public static boolean copy(File src, File dest) {
  204           
  205           boolean result = true;
  206           
  207           String files[] = null;
  208           if (src.isDirectory()) {
  209               files = src.list();
  210               result = dest.mkdir();
  211           } else {
  212               files = new String[1];
  213               files[0] = "";
  214           }
  215           if (files == null) {
  216               files = new String[0];
  217           }
  218           for (int i = 0; (i < files.length) && result; i++) {
  219               File fileSrc = new File(src, files[i]);
  220               File fileDest = new File(dest, files[i]);
  221               if (fileSrc.isDirectory()) {
  222                   result = copy(fileSrc, fileDest);
  223               } else {
  224                   FileChannel ic = null;
  225                   FileChannel oc = null;
  226                   try {
  227                       ic = (new FileInputStream(fileSrc)).getChannel();
  228                       oc = (new FileOutputStream(fileDest)).getChannel();
  229                       ic.transferTo(0, ic.size(), oc);
  230                   } catch (IOException e) {
  231                       log.error(sm.getString
  232                               ("expandWar.copy", fileSrc, fileDest), e);
  233                       result = false;
  234                   } finally {
  235                       if (ic != null) {
  236                           try {
  237                               ic.close();
  238                           } catch (IOException e) {
  239                           }
  240                       }
  241                       if (oc != null) {
  242                           try {
  243                               oc.close();
  244                           } catch (IOException e) {
  245                           }
  246                       }
  247                   }
  248               }
  249           }
  250           return result;
  251           
  252       }
  253       
  254       
  255       /**
  256        * Delete the specified directory, including all of its contents and
  257        * subdirectories recursively.
  258        *
  259        * @param dir File object representing the directory to be deleted
  260        */
  261       public static boolean delete(File dir) {
  262           if (dir.isDirectory()) {
  263               return deleteDir(dir);
  264           } else {
  265               return dir.delete();
  266           }
  267       }
  268       
  269       
  270       /**
  271        * Delete the specified directory, including all of its contents and
  272        * subdirectories recursively.
  273        *
  274        * @param dir File object representing the directory to be deleted
  275        */
  276       public static boolean deleteDir(File dir) {
  277   
  278           String files[] = dir.list();
  279           if (files == null) {
  280               files = new String[0];
  281           }
  282           for (int i = 0; i < files.length; i++) {
  283               File file = new File(dir, files[i]);
  284               if (file.isDirectory()) {
  285                   deleteDir(file);
  286               } else {
  287                   file.delete();
  288               }
  289           }
  290           return dir.delete();
  291   
  292       }
  293   
  294   
  295       /**
  296        * Expand the specified input stream into the specified directory, creating
  297        * a file named from the specified relative path.
  298        *
  299        * @param input InputStream to be copied
  300        * @param docBase Document base directory into which we are expanding
  301        * @param name Relative pathname of the file to be created
  302        * @return A handle to the expanded File
  303        *
  304        * @exception IOException if an input/output error occurs
  305        */
  306       protected static File expand(InputStream input, File docBase, String name)
  307           throws IOException {
  308   
  309           File file = new File(docBase, name);
  310           BufferedOutputStream output = null;
  311           try {
  312               output = 
  313                   new BufferedOutputStream(new FileOutputStream(file));
  314               byte buffer[] = new byte[2048];
  315               while (true) {
  316                   int n = input.read(buffer);
  317                   if (n <= 0)
  318                       break;
  319                   output.write(buffer, 0, n);
  320               }
  321           } finally {
  322               if (output != null) {
  323                   try {
  324                       output.close();
  325                   } catch (IOException e) {
  326                       // Ignore
  327                   }
  328               }
  329           }
  330   
  331           return file;
  332       }
  333   
  334   
  335   }

Save This Page
Home » apache-tomcat-6.0.16-src » org.apache » catalina » startup » [javadoc | source]