org.eclipse.jetty.util.resource.JarResource Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ehcache Show documentation
Show all versions of ehcache Show documentation
Ehcache is an open source, standards-based cache used to boost performance,
offload the database and simplify scalability. Ehcache is robust, proven and full-featured and
this has made it the most widely-used Java-based cache.
//
// ========================================================================
// 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 JarResource
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 + "!/");
}
}