Mercurial Hosting > luan
comparison src/org/eclipse/jetty/util/resource/JarResource.java @ 802:3428c60d7cfc
replace jetty jars with source
| author | Franklin Schmidt <fschmidt@gmail.com> |
|---|---|
| date | Wed, 07 Sep 2016 21:15:48 -0600 |
| parents | |
| children | 8e9db0bbf4f9 |
comparison
equal
deleted
inserted
replaced
| 801:6a21393191c1 | 802:3428c60d7cfc |
|---|---|
| 1 // | |
| 2 // ======================================================================== | |
| 3 // Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd. | |
| 4 // ------------------------------------------------------------------------ | |
| 5 // All rights reserved. This program and the accompanying materials | |
| 6 // are made available under the terms of the Eclipse Public License v1.0 | |
| 7 // and Apache License v2.0 which accompanies this distribution. | |
| 8 // | |
| 9 // The Eclipse Public License is available at | |
| 10 // http://www.eclipse.org/legal/epl-v10.html | |
| 11 // | |
| 12 // The Apache License v2.0 is available at | |
| 13 // http://www.opensource.org/licenses/apache2.0.php | |
| 14 // | |
| 15 // You may elect to redistribute this code under either of these licenses. | |
| 16 // ======================================================================== | |
| 17 // | |
| 18 | |
| 19 package org.eclipse.jetty.util.resource; | |
| 20 | |
| 21 import java.io.File; | |
| 22 import java.io.FileOutputStream; | |
| 23 import java.io.FilterInputStream; | |
| 24 import java.io.IOException; | |
| 25 import java.io.InputStream; | |
| 26 import java.net.JarURLConnection; | |
| 27 import java.net.URL; | |
| 28 import java.util.jar.JarEntry; | |
| 29 import java.util.jar.JarInputStream; | |
| 30 import java.util.jar.Manifest; | |
| 31 | |
| 32 import org.eclipse.jetty.util.IO; | |
| 33 import org.eclipse.jetty.util.URIUtil; | |
| 34 import org.eclipse.jetty.util.log.Log; | |
| 35 import org.eclipse.jetty.util.log.Logger; | |
| 36 | |
| 37 | |
| 38 /* ------------------------------------------------------------ */ | |
| 39 public class JarResource extends URLResource | |
| 40 { | |
| 41 private static final Logger LOG = Log.getLogger(JarResource.class); | |
| 42 protected JarURLConnection _jarConnection; | |
| 43 | |
| 44 /* -------------------------------------------------------- */ | |
| 45 JarResource(URL url) | |
| 46 { | |
| 47 super(url,null); | |
| 48 } | |
| 49 | |
| 50 /* ------------------------------------------------------------ */ | |
| 51 JarResource(URL url, boolean useCaches) | |
| 52 { | |
| 53 super(url, null, useCaches); | |
| 54 } | |
| 55 | |
| 56 /* ------------------------------------------------------------ */ | |
| 57 @Override | |
| 58 public synchronized void release() | |
| 59 { | |
| 60 _jarConnection=null; | |
| 61 super.release(); | |
| 62 } | |
| 63 | |
| 64 /* ------------------------------------------------------------ */ | |
| 65 @Override | |
| 66 protected synchronized boolean checkConnection() | |
| 67 { | |
| 68 super.checkConnection(); | |
| 69 try | |
| 70 { | |
| 71 if (_jarConnection!=_connection) | |
| 72 newConnection(); | |
| 73 } | |
| 74 catch(IOException e) | |
| 75 { | |
| 76 LOG.ignore(e); | |
| 77 _jarConnection=null; | |
| 78 } | |
| 79 | |
| 80 return _jarConnection!=null; | |
| 81 } | |
| 82 | |
| 83 /* ------------------------------------------------------------ */ | |
| 84 /** | |
| 85 * @throws IOException Sub-classes of <code>JarResource</code> may throw an IOException (or subclass) | |
| 86 */ | |
| 87 protected void newConnection() throws IOException | |
| 88 { | |
| 89 _jarConnection=(JarURLConnection)_connection; | |
| 90 } | |
| 91 | |
| 92 /* ------------------------------------------------------------ */ | |
| 93 /** | |
| 94 * Returns true if the respresenetd resource exists. | |
| 95 */ | |
| 96 @Override | |
| 97 public boolean exists() | |
| 98 { | |
| 99 if (_urlString.endsWith("!/")) | |
| 100 return checkConnection(); | |
| 101 else | |
| 102 return super.exists(); | |
| 103 } | |
| 104 | |
| 105 /* ------------------------------------------------------------ */ | |
| 106 @Override | |
| 107 public File getFile() | |
| 108 throws IOException | |
| 109 { | |
| 110 return null; | |
| 111 } | |
| 112 | |
| 113 /* ------------------------------------------------------------ */ | |
| 114 @Override | |
| 115 public InputStream getInputStream() | |
| 116 throws java.io.IOException | |
| 117 { | |
| 118 checkConnection(); | |
| 119 if (!_urlString.endsWith("!/")) | |
| 120 return new FilterInputStream(super.getInputStream()) | |
| 121 { | |
| 122 @Override | |
| 123 public void close() throws IOException {this.in=IO.getClosedStream();} | |
| 124 }; | |
| 125 | |
| 126 URL url = new URL(_urlString.substring(4,_urlString.length()-2)); | |
| 127 InputStream is = url.openStream(); | |
| 128 return is; | |
| 129 } | |
| 130 | |
| 131 /* ------------------------------------------------------------ */ | |
| 132 @Override | |
| 133 public void copyTo(File directory) | |
| 134 throws IOException | |
| 135 { | |
| 136 if (!exists()) | |
| 137 return; | |
| 138 | |
| 139 if(LOG.isDebugEnabled()) | |
| 140 LOG.debug("Extract "+this+" to "+directory); | |
| 141 | |
| 142 String urlString = this.getURL().toExternalForm().trim(); | |
| 143 int endOfJarUrl = urlString.indexOf("!/"); | |
| 144 int startOfJarUrl = (endOfJarUrl >= 0?4:0); | |
| 145 | |
| 146 if (endOfJarUrl < 0) | |
| 147 throw new IOException("Not a valid jar url: "+urlString); | |
| 148 | |
| 149 URL jarFileURL = new URL(urlString.substring(startOfJarUrl, endOfJarUrl)); | |
| 150 String subEntryName = (endOfJarUrl+2 < urlString.length() ? urlString.substring(endOfJarUrl + 2) : null); | |
| 151 boolean subEntryIsDir = (subEntryName != null && subEntryName.endsWith("/")?true:false); | |
| 152 | |
| 153 if (LOG.isDebugEnabled()) | |
| 154 LOG.debug("Extracting entry = "+subEntryName+" from jar "+jarFileURL); | |
| 155 | |
| 156 InputStream is = jarFileURL.openConnection().getInputStream(); | |
| 157 JarInputStream jin = new JarInputStream(is); | |
| 158 JarEntry entry; | |
| 159 boolean shouldExtract; | |
| 160 while((entry=jin.getNextJarEntry())!=null) | |
| 161 { | |
| 162 String entryName = entry.getName(); | |
| 163 if ((subEntryName != null) && (entryName.startsWith(subEntryName))) | |
| 164 { | |
| 165 // is the subentry really a dir? | |
| 166 if (!subEntryIsDir && subEntryName.length()+1==entryName.length() && entryName.endsWith("/")) | |
| 167 subEntryIsDir=true; | |
| 168 | |
| 169 //if there is a particular subEntry that we are looking for, only | |
| 170 //extract it. | |
| 171 if (subEntryIsDir) | |
| 172 { | |
| 173 //if it is a subdirectory we are looking for, then we | |
| 174 //are looking to extract its contents into the target | |
| 175 //directory. Remove the name of the subdirectory so | |
| 176 //that we don't wind up creating it too. | |
| 177 entryName = entryName.substring(subEntryName.length()); | |
| 178 if (!entryName.equals("")) | |
| 179 { | |
| 180 //the entry is | |
| 181 shouldExtract = true; | |
| 182 } | |
| 183 else | |
| 184 shouldExtract = false; | |
| 185 } | |
| 186 else | |
| 187 shouldExtract = true; | |
| 188 } | |
| 189 else if ((subEntryName != null) && (!entryName.startsWith(subEntryName))) | |
| 190 { | |
| 191 //there is a particular entry we are looking for, and this one | |
| 192 //isn't it | |
| 193 shouldExtract = false; | |
| 194 } | |
| 195 else | |
| 196 { | |
| 197 //we are extracting everything | |
| 198 shouldExtract = true; | |
| 199 } | |
| 200 | |
| 201 | |
| 202 if (!shouldExtract) | |
| 203 { | |
| 204 if (LOG.isDebugEnabled()) | |
| 205 LOG.debug("Skipping entry: "+entryName); | |
| 206 continue; | |
| 207 } | |
| 208 | |
| 209 String dotCheck = entryName.replace('\\', '/'); | |
| 210 dotCheck = URIUtil.canonicalPath(dotCheck); | |
| 211 if (dotCheck == null) | |
| 212 { | |
| 213 if (LOG.isDebugEnabled()) | |
| 214 LOG.debug("Invalid entry: "+entryName); | |
| 215 continue; | |
| 216 } | |
| 217 | |
| 218 File file=new File(directory,entryName); | |
| 219 | |
| 220 if (entry.isDirectory()) | |
| 221 { | |
| 222 // Make directory | |
| 223 if (!file.exists()) | |
| 224 file.mkdirs(); | |
| 225 } | |
| 226 else | |
| 227 { | |
| 228 // make directory (some jars don't list dirs) | |
| 229 File dir = new File(file.getParent()); | |
| 230 if (!dir.exists()) | |
| 231 dir.mkdirs(); | |
| 232 | |
| 233 // Make file | |
| 234 FileOutputStream fout = null; | |
| 235 try | |
| 236 { | |
| 237 fout = new FileOutputStream(file); | |
| 238 IO.copy(jin,fout); | |
| 239 } | |
| 240 finally | |
| 241 { | |
| 242 IO.close(fout); | |
| 243 } | |
| 244 | |
| 245 // touch the file. | |
| 246 if (entry.getTime()>=0) | |
| 247 file.setLastModified(entry.getTime()); | |
| 248 } | |
| 249 } | |
| 250 | |
| 251 if ((subEntryName == null) || (subEntryName != null && subEntryName.equalsIgnoreCase("META-INF/MANIFEST.MF"))) | |
| 252 { | |
| 253 Manifest manifest = jin.getManifest(); | |
| 254 if (manifest != null) | |
| 255 { | |
| 256 File metaInf = new File (directory, "META-INF"); | |
| 257 metaInf.mkdir(); | |
| 258 File f = new File(metaInf, "MANIFEST.MF"); | |
| 259 FileOutputStream fout = new FileOutputStream(f); | |
| 260 manifest.write(fout); | |
| 261 fout.close(); | |
| 262 } | |
| 263 } | |
| 264 IO.close(jin); | |
| 265 } | |
| 266 | |
| 267 public static Resource newJarResource(Resource resource) throws IOException | |
| 268 { | |
| 269 if (resource instanceof JarResource) | |
| 270 return resource; | |
| 271 return Resource.newResource("jar:" + resource + "!/"); | |
| 272 } | |
| 273 } |
