View Javadoc

    1   // ========================================================================
    2   // Copyright 1996-2005 Mort Bay Consulting Pty. Ltd.
    3   // ------------------------------------------------------------------------
    4   // Licensed under the Apache License, Version 2.0 (the "License");
    5   // you may not use this file except in compliance with the License.
    6   // You may obtain a copy of the License at
    7   // http://www.apache.org/licenses/LICENSE-2.0
    8   // Unless required by applicable law or agreed to in writing, software
    9   // distributed under the License is distributed on an "AS IS" BASIS,
    10  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  // ========================================================================
    14  package org.mortbay.resource;
    15
    16  import java.io.File;
    17  import java.io.FileOutputStream;
    18  import java.io.FilterInputStream;
    19  import java.io.IOException;
    20  import java.io.InputStream;
    21  import java.net.JarURLConnection;
    22  import java.net.URL;
    23  import java.util.jar.JarEntry;
    24  import java.util.jar.JarInputStream;
    25
    26  import org.mortbay.log.Log;
    27  import org.mortbay.util.IO;
    28
    29
    30  /* ------------------------------------------------------------ */
    31  public class JarResource extends URLResource
    32  {
    33
    34      protected transient JarURLConnection _jarConnection;
    35
    36      /* -------------------------------------------------------- */
    37      JarResource(URL url)
    38      {
    39          super(url,null);
    40      }
    41
    42      /* ------------------------------------------------------------ */
    43      JarResource(URL url, boolean useCaches)
    44      {
    45          super(url, null, useCaches);
    46      }
    47
    48      /* ------------------------------------------------------------ */
    49      public synchronized void release()
    50      {
    51          _jarConnection=null;
    52          super.release();
    53      }
    54
    55      /* ------------------------------------------------------------ */
    56      protected boolean checkConnection()
    57      {
    58          super.checkConnection();
    59          try
    60          {
    61              if (_jarConnection!=_connection)
    62                  newConnection();
    63          }
    64          catch(IOException e)
    65          {
    66              Log.ignore(e);
    67              _jarConnection=null;
    68          }
    69
    70          return _jarConnection!=null;
    71      }
    72
    73      /* ------------------------------------------------------------ */
    74      /**
    75       * @throws IOException Sub-classes of <code>JarResource</code> may throw an IOException (or subclass)
    76       */
    77      protected void newConnection() throws IOException
    78      {
    79          _jarConnection=(JarURLConnection)_connection;
    80      }
    81
    82      /* ------------------------------------------------------------ */
    83      /**
    84       * Returns true if the respresenetd resource exists.
    85       */
    86      public boolean exists()
    87      {
    88          if (_urlString.endsWith("!/"))
    89              return checkConnection();
    90          else
    91              return super.exists();
    92      }
    93
    94      /* ------------------------------------------------------------ */
    95      public File getFile()
    96          throws IOException
    97      {
    98          return null;
    99      }
    100
    101     /* ------------------------------------------------------------ */
    102     public InputStream getInputStream()
    103         throws java.io.IOException
    104     {
    105         checkConnection();
    106         if (!_urlString.endsWith("!/"))
    107             return new FilterInputStream(super.getInputStream())
    108             {
    109                 public void close() throws IOException {this.in=IO.getClosedStream();}
    110             };
    111
    112         URL url = new URL(_urlString.substring(4,_urlString.length()-2));
    113         InputStream is = url.openStream();
    114         return is;
    115     }
    116
    117     /* ------------------------------------------------------------ */
    118     public static void extract(Resource resource, File directory, boolean deleteOnExit)
    119         throws IOException
    120     {
    121         if(Log.isDebugEnabled())Log.debug("Extract "+resource+" to "+directory);
    122
    123
    124         String urlString = resource.getURL().toExternalForm().trim();
    125         int endOfJarUrl = urlString.indexOf("!/");
    126         int startOfJarUrl = (endOfJarUrl >= 0?4:0);
    127
    128         if (endOfJarUrl < 0)
    129             throw new IOException("Not a valid jar url: "+urlString);
    130
    131         URL jarFileURL = new URL(urlString.substring(startOfJarUrl, endOfJarUrl));
    132         String subEntryName = (endOfJarUrl+2 < urlString.length() ? urlString.substring(endOfJarUrl + 2) : null);
    133         boolean subEntryIsDir = (subEntryName != null && subEntryName.endsWith("/")?true:false);
    134
    135         if (Log.isDebugEnabled()) Log.debug("Extracting entry = "+subEntryName+" from jar "+jarFileURL);
    136
    137         InputStream is = jarFileURL.openConnection().getInputStream();
    138         JarInputStream jin = new JarInputStream(is);
    139         JarEntry entry;
    140         boolean shouldExtract;
    141         while((entry=jin.getNextJarEntry())!=null)
    142         {
    143             String entryName = entry.getName();
    144
    145             if ((subEntryName != null) && (entryName.startsWith(subEntryName)))
    146             {
    147                 //if there is a particular subEntry that we are looking for, only
    148                 //extract it.
    149                 if (subEntryIsDir)
    150                 {
    151                     //if it is a subdirectory we are looking for, then we
    152                     //are looking to extract its contents into the target
    153                     //directory. Remove the name of the subdirectory so
    154                     //that we don't wind up creating it too.
    155                     entryName = entryName.substring(subEntryName.length());
    156                     if (!entryName.equals(""))
    157                     {
    158                         //the entry is
    159                         shouldExtract = true;
    160                     }
    161                     else
    162                         shouldExtract = false;
    163                 }
    164                 else
    165                     shouldExtract = true;
    166             }
    167             else if ((subEntryName != null) && (!entryName.startsWith(subEntryName)))
    168             {
    169                 //there is a particular entry we are looking for, and this one
    170                 //isn't it
    171                 shouldExtract = false;
    172             }
    173             else
    174             {
    175                 //we are extracting everything
    176                 shouldExtract =  true;
    177             }
    178
    179
    180             if (!shouldExtract)
    181             {
    182                 if (Log.isDebugEnabled()) Log.debug("Skipping entry: "+entryName);
    183                 continue;
    184             }
    185
    186
    187             File file=new File(directory,entryName);
    188             if (entry.isDirectory())
    189             {
    190                 // Make directory
    191                 if (!file.exists())
    192                     file.mkdirs();
    193             }
    194             else
    195             {
    196                 // make directory (some jars don't list dirs)
    197                 File dir = new File(file.getParent());
    198                 if (!dir.exists())
    199                     dir.mkdirs();
    200
    201                 // Make file
    202                 FileOutputStream fout = null;
    203                 try
    204                 {
    205                     fout = new FileOutputStream(file);
    206                     IO.copy(jin,fout);
    207                 }
    208                 finally
    209                 {
    210                     IO.close(fout);
    211                 }
    212
    213                 // touch the file.
    214                 if (entry.getTime()>=0)
    215                     file.setLastModified(entry.getTime());
    216             }
    217             if (deleteOnExit)
    218                 file.deleteOnExit();
    219         }
    220         IO.close(jin);
    221     }
    222
    223     /* ------------------------------------------------------------ */
    224     public void extract(File directory, boolean deleteOnExit)
    225         throws IOException
    226     {
    227         extract(this,directory,deleteOnExit);
    228     }
    229 }