//Copyright 2007-2008 David Yu dyuproject@gmail.com
//------------------------------------------------------------------------
//Licensed under the Apache License, Version 2.0 (the "License");
//you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//http://www.apache.org/licenses/LICENSE-2.0
//Unless required by applicable law or agreed to in writing, software
//distributed under the License is distributed on an "AS IS" BASIS,
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and
//limitations under the License.
//package com.dyuproject.util;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
/**
* Util for extracting *.jar, *.war and *.zip archives.
*
* @author David Yu
* @created Feb 25, 2008
*/
public final class ArchiveUtil
{
/**
* The suffixes of the files to support.
*/
public static final String[] SUPPORTED_FILES = new String[]{
".zip",
".jar",
".war"
};
private static File __tempDir;
static
{
__tempDir = new File(System.getProperty("java.io.tmpdir"));
}
public static void setTempDir(File tempDir)
{
if(tempDir.isDirectory() && tempDir.exists())
__tempDir = tempDir;
}
/**
* Gets the temp dir (the sys property "java.io.tmpdir" if not
* overridden via {@link #setTempDir(File)}).
*/
public static File getTempDir()
{
return __tempDir;
}
/**
* Returns true if the given {@code resource} is either a zip, jar or war file.
*/
public static boolean isSupported(String resource)
{
int idx = resource.lastIndexOf('.');
if(resource.length()==idx+4)
{
for(int i=0; i {
if(resource.endsWith(SUPPORTED_FILES[i]))
return true;
}
}
return false;
}
public static boolean extract(File archive, File targetDir) throws IOException
{
return extract(archive.toURI().toURL(), targetDir, true);
}
public static boolean extract(File archive, File targetDir, boolean deleteOnExit) throws IOException
{
return extract(archive.toURI().toURL(), targetDir, deleteOnExit);
}
public static boolean extract(URL archive, File targetDir) throws IOException
{
return extract(archive, targetDir, true);
}
/**
* Extracts the file {@code archive} to the target dir {@code targetDir} and deletes the
* files extracted upon jvm exit if the flag {@code deleteOnExit} is true.
*/
public static boolean extract(URL archive, File targetDir, boolean deleteOnExit) throws IOException
{
String archiveStr = archive.toString();
String jarEntry = null;
int idx = archiveStr.indexOf("!/");
if(idx!=-1)
{
if(!archiveStr.startsWith("jar:") && archiveStr.length()==idx+2)
return false;
archive = new URL(archiveStr.substring(4, idx));
jarEntry = archiveStr.substring(idx+2);
}
else if(!isSupported(archiveStr))
return false;
JarInputStream jis = new JarInputStream(archive.openConnection().getInputStream());
if(!targetDir.exists())
targetDir.mkdirs();
JarEntry entry = null;
while((entry=jis.getNextJarEntry())!=null)
{
String entryName = entry.getName();
File entryFile = new File(targetDir, entryName);
if(!entry.isDirectory())
{
if(jarEntry==null || entryName.startsWith(jarEntry))
{
if(!entryFile.exists() || entryFile.lastModified()!=entry.getTime())
extractEntry(entryFile, jis, entry, deleteOnExit);
}
}
}
try{jis.close();}catch(Exception e){}
return true;
}
private static void extractEntry(File entryFile, JarInputStream jis, JarEntry entry,
boolean deleteOnExit) throws IOException
{
File parent = new File(entryFile.getParent());
if(!parent.exists())
parent.mkdirs();
ResourceUtil.copy(jis, new FileOutputStream(entryFile));
entryFile.setLastModified(entry.getTime());
if(deleteOnExit)
{
parent.deleteOnExit();
entryFile.deleteOnExit();
}
}
}
/**
* Util for files and streams.
*
* @author David Yu
*/
final class ResourceUtil
{
static int __copyBufferSize = 4096;
/**
* Sets the buffer size to use when copying data from streams.
*/
public static void setCopyBufferSize(int size)
{
__copyBufferSize = size;
}
/**
* Gets the buffer size to use when copying data from streams.
*/
public static int getCopyBufferSize()
{
return __copyBufferSize;
}
/**
* Reads the contents of the file into a byte array.
*/
public static byte[] readBytes(File file) throws IOException
{
return readBytes(file.toURI());
}
/**
* Reads the contents of the given file into a byte array.
*/
public static byte[] readBytes(String file) throws IOException
{
return readBytes(URI.create(file));
}
/**
* Reads the contents of the given file into a byte array.
*/
public static byte[] readBytes(URI file) throws IOException
{
return readBytes(file.toURL());
}
/**
* Reads the contents of the given file into a byte array.
*/
public static byte[] readBytes(URL file) throws IOException
{
return readBytes(file.openStream());
}
/**
* Reads the contents of the given input stream into a byte array.
*/
public static byte[] readBytes(InputStream in) throws IOException
{
return getByteArrayOutputStream(in).toByteArray();
}
/**
* Gets the ByteArrayOutputStream that was filled when reading from the
* given input stream {@code in}.
*/
public static ByteArrayOutputStream getByteArrayOutputStream(InputStream in) throws IOException
{
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buffer = new byte[__copyBufferSize];
int length = 0;
while((length=in.read(buffer, 0, __copyBufferSize)) != -1)
out.write(buffer, 0, length);
try{in.close();}catch(Exception e){}
return out;
}
/**
* Copies the contents of the input url to the output url.
*/
public static void copy(URL in, URL out) throws IOException
{
copy(in.openStream(), out.openConnection().getOutputStream());
}
/**
* Copies the contents of the input file to the output file.
*/
public static void copy(File in, File out) throws IOException
{
copy(new FileInputStream(in), new FileOutputStream(out));
}
/**
* Copies the contents of the input url to the output file.
*/
public static void copy(URL in, File out) throws IOException
{
copy(in.openStream(), new FileOutputStream(out));
}
/**
* Copies the contents of the input stream to the output stream.
*/
public static void copy(InputStream in, OutputStream out) throws IOException
{
byte[] buffer = new byte[__copyBufferSize];
int length = 0;
while((length=in.read(buffer, 0, __copyBufferSize)) != -1)
out.write(buffer, 0, length);
try{out.close();}catch(Exception e){}
}
/**
* Copies the contents of the input stream to the output stream with the specified
* buffer size to use for copying.
*/
public static void copy(InputStream in, OutputStream out, int bufferSize) throws IOException
{
byte[] buffer = new byte[bufferSize];
int length = 0;
while((length=in.read(buffer, 0, bufferSize)) != -1)
out.write(buffer, 0, length);
try{out.close();}catch(Exception e){}
}
static void copyDir(File dirFrom, File dirTo) throws IOException
{
File[] files = dirFrom.listFiles();
if(!dirTo.exists())
dirTo.mkdirs();
for(int i=0; i {
File f = files[i];
if(f.isDirectory())
copyDir(f, new File(dirTo, f.getName()));
else
copy(f, new File(dirTo, f.getName()));
}
}
/**
* Copies the given {@code file} to the given dir.
*/
public static void copyFileToDir(File file, File dirTo) throws IOException
{
if(file.exists())
{
if(file.isDirectory())
copyDir(file, dirTo);
else
{
if(!dirTo.exists())
dirTo.mkdirs();
copy(file, new File(dirTo, file.getName()));
}
}
}
/**
* Returns a list of file filtered by their file types/extensions; (E.g ".zip")
*/
public static List getFilesByExtension(File dir, String[] extensions)
{
if(!dir.isDirectory() || extensions==null)
return Collections.emptyList();
List files = new ArrayList();
addFilesByExtension(files, dir, extensions);
return files;
}
static void addFilesByExtension(List list, File dir, String[] extensions)
{
File[] files = dir.listFiles();
for(int i=0; i {
File f = files[i];
if(f.isDirectory())
addFilesByExtension(list, f, extensions);
else
{
for(String s : extensions)
{
if(f.getName().endsWith(s))
{
list.add(f);
break;
}
}
}
}
}
}