Mercurial Hosting > luan
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/eclipse/jetty/util/resource/JarResource.java Wed Sep 07 21:15:48 2016 -0600 @@ -0,0 +1,273 @@ +// +// ======================================================================== +// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +package org.eclipse.jetty.util.resource; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.JarURLConnection; +import java.net.URL; +import java.util.jar.JarEntry; +import java.util.jar.JarInputStream; +import java.util.jar.Manifest; + +import org.eclipse.jetty.util.IO; +import org.eclipse.jetty.util.URIUtil; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; + + +/* ------------------------------------------------------------ */ +public class JarResource extends URLResource +{ + private static final Logger LOG = Log.getLogger(JarResource.class); + protected JarURLConnection _jarConnection; + + /* -------------------------------------------------------- */ + JarResource(URL url) + { + super(url,null); + } + + /* ------------------------------------------------------------ */ + JarResource(URL url, boolean useCaches) + { + super(url, null, useCaches); + } + + /* ------------------------------------------------------------ */ + @Override + public synchronized void release() + { + _jarConnection=null; + super.release(); + } + + /* ------------------------------------------------------------ */ + @Override + protected synchronized boolean checkConnection() + { + super.checkConnection(); + try + { + if (_jarConnection!=_connection) + newConnection(); + } + catch(IOException e) + { + LOG.ignore(e); + _jarConnection=null; + } + + return _jarConnection!=null; + } + + /* ------------------------------------------------------------ */ + /** + * @throws IOException Sub-classes of <code>JarResource</code> may throw an IOException (or subclass) + */ + protected void newConnection() throws IOException + { + _jarConnection=(JarURLConnection)_connection; + } + + /* ------------------------------------------------------------ */ + /** + * Returns true if the respresenetd resource exists. + */ + @Override + public boolean exists() + { + if (_urlString.endsWith("!/")) + return checkConnection(); + else + return super.exists(); + } + + /* ------------------------------------------------------------ */ + @Override + public File getFile() + throws IOException + { + return null; + } + + /* ------------------------------------------------------------ */ + @Override + public InputStream getInputStream() + throws java.io.IOException + { + checkConnection(); + if (!_urlString.endsWith("!/")) + return new FilterInputStream(super.getInputStream()) + { + @Override + public void close() throws IOException {this.in=IO.getClosedStream();} + }; + + URL url = new URL(_urlString.substring(4,_urlString.length()-2)); + InputStream is = url.openStream(); + return is; + } + + /* ------------------------------------------------------------ */ + @Override + public void copyTo(File directory) + throws IOException + { + if (!exists()) + return; + + if(LOG.isDebugEnabled()) + LOG.debug("Extract "+this+" to "+directory); + + String urlString = this.getURL().toExternalForm().trim(); + int endOfJarUrl = urlString.indexOf("!/"); + int startOfJarUrl = (endOfJarUrl >= 0?4:0); + + if (endOfJarUrl < 0) + throw new IOException("Not a valid jar url: "+urlString); + + URL jarFileURL = new URL(urlString.substring(startOfJarUrl, endOfJarUrl)); + String subEntryName = (endOfJarUrl+2 < urlString.length() ? urlString.substring(endOfJarUrl + 2) : null); + boolean subEntryIsDir = (subEntryName != null && subEntryName.endsWith("/")?true:false); + + if (LOG.isDebugEnabled()) + LOG.debug("Extracting entry = "+subEntryName+" from jar "+jarFileURL); + + InputStream is = jarFileURL.openConnection().getInputStream(); + JarInputStream jin = new JarInputStream(is); + JarEntry entry; + boolean shouldExtract; + while((entry=jin.getNextJarEntry())!=null) + { + String entryName = entry.getName(); + if ((subEntryName != null) && (entryName.startsWith(subEntryName))) + { + // is the subentry really a dir? + if (!subEntryIsDir && subEntryName.length()+1==entryName.length() && entryName.endsWith("/")) + subEntryIsDir=true; + + //if there is a particular subEntry that we are looking for, only + //extract it. + if (subEntryIsDir) + { + //if it is a subdirectory we are looking for, then we + //are looking to extract its contents into the target + //directory. Remove the name of the subdirectory so + //that we don't wind up creating it too. + entryName = entryName.substring(subEntryName.length()); + if (!entryName.equals("")) + { + //the entry is + shouldExtract = true; + } + else + shouldExtract = false; + } + else + shouldExtract = true; + } + else if ((subEntryName != null) && (!entryName.startsWith(subEntryName))) + { + //there is a particular entry we are looking for, and this one + //isn't it + shouldExtract = false; + } + else + { + //we are extracting everything + shouldExtract = true; + } + + + if (!shouldExtract) + { + if (LOG.isDebugEnabled()) + LOG.debug("Skipping entry: "+entryName); + continue; + } + + String dotCheck = entryName.replace('\\', '/'); + dotCheck = URIUtil.canonicalPath(dotCheck); + if (dotCheck == null) + { + if (LOG.isDebugEnabled()) + LOG.debug("Invalid entry: "+entryName); + continue; + } + + File file=new File(directory,entryName); + + if (entry.isDirectory()) + { + // Make directory + if (!file.exists()) + file.mkdirs(); + } + else + { + // make directory (some jars don't list dirs) + File dir = new File(file.getParent()); + if (!dir.exists()) + dir.mkdirs(); + + // Make file + FileOutputStream fout = null; + try + { + fout = new FileOutputStream(file); + IO.copy(jin,fout); + } + finally + { + IO.close(fout); + } + + // touch the file. + if (entry.getTime()>=0) + file.setLastModified(entry.getTime()); + } + } + + if ((subEntryName == null) || (subEntryName != null && subEntryName.equalsIgnoreCase("META-INF/MANIFEST.MF"))) + { + Manifest manifest = jin.getManifest(); + if (manifest != null) + { + File metaInf = new File (directory, "META-INF"); + metaInf.mkdir(); + File f = new File(metaInf, "MANIFEST.MF"); + FileOutputStream fout = new FileOutputStream(f); + manifest.write(fout); + fout.close(); + } + } + IO.close(jin); + } + + public static Resource newJarResource(Resource resource) throws IOException + { + if (resource instanceof JarResource) + return resource; + return Resource.newResource("jar:" + resource + "!/"); + } +}