net.sf.sevenzipjbinding.SevenZip Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jwrapper-7zip-jbinding Show documentation
Show all versions of jwrapper-7zip-jbinding Show documentation
${project.organization.name} JWrapper 7zip Jbinding
The newest version!
package net.sf.sevenzipjbinding;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.Random;
import net.sf.sevenzipjbinding.impl.RandomAccessFileInStream;
import net.sf.sevenzipjbinding.impl.VolumedArchiveInStream;
/**
* 7-Zip-JBinding entry point class. Finds and initializes 7-Zip-JBinding native library. Opens archives and returns
* implementation of {@link ISevenZipInArchive}
*
* Initialization of the native library
*
* Typically the library doesn't need an explicit initialization. The first call to an open archive method will try to
* initialize the native library by calling {@link #initSevenZipFromPlatformJAR()} method. This initialization process
* requires a platform jar to be in a class path. The automatic initialization starts before the first access to an
* archive, if native library wasn't already initialized manually with one of the initSevenZip...
methods.
* If manual or automatic initialization failed, no further automatic initialization attempts will be made. The
* initialization status and error messages can be obtained by following methods:
*
* - {@link #isInitializedSuccessfully()} - get initialization status
* - {@link #isAutoInitializationWillOccur()} - determine, if an initialization attempt was made
* - {@link #getLastInitializationException()} - get last thrown initialization exception
*
*
* The platform jar is a additional jar file sevenzipjbinding-Platform.jar
with one or more native
* libraries for respective one or more platforms. Here is some examples of 7-Zip-JBinding platform jar files.
*
* sevenzipjbinding-Linux-i386.jar
with native library for exact one platform: Linux, 32 bit
* sevenzipjbinding-AllWindows.jar
with native libraries for two platforms: Windows 32 and 64 bit
* sevenzipjbinding-AllPlatforms.jar
with native libraries for all available platforms
*
* The single and multiple platform jar files can be determined by counting dashes in the filename. Single platform jar
* files always contain two dashes in their names.
*
* Here is a schema of the different initialization processes:
*
*
* - Initialization using platform jar
*
* - First, the list of available native libraries is read out of the
*
/sevenzipjbinding-platforms.properties
file in the class path by calling {@link #getPlatformList()}
* method. The list is cached in a static variable.
* - The platform is chosen by calling {@link #getPlatformBestMatch()} method. If the list of available platforms
* contains exact one platform the platform is always considered the best match. If more, that one platforms are
* available to choose from, the system properties
os.arch
and os.name
(first part) are used
* to make the choice.
* - The list of the native libraries is determined by reading
*
/ChosenPlatform/sevenzipjbinding-lib.properties
in the class path. The list contains names of the
* dynamic libraries situated in the /ChosenPlatform/
directory in the same jar.
* - The dynamic libraries for the chosen platform are copied (if not already) to the unique temporary directory using
* "build-ref" postfix. If not passed as a parameter for one of
initSevenZipFromPlatformJAR(...)
methods,
* the temporary directory is determined using system property java.io.tmpdir
.
* - The dynamic libraries are loaded into JVM using {@link System#load(String)} method.
* - 7-Zip-JBinding native initialization method called to complete initialization process.
*
* - Manual initialization
*
* - User loads 7-Zip-JBinding native dynamic libraries manually into JVM using {@link System#load(String)} or
* {@link System#loadLibrary(String)}
* - User calls {@link #initLoadedLibraries()} method to initialize manually loaded native library
*
*
*
*
*
* By default the initialization occurred within the
* {@link AccessController#doPrivileged(java.security.PrivilegedAction)} block. This can be overruled by setting
* sevenzip.no_doprivileged_initialization
system property. For example:
* java -Dsevenzip.no_doprivileged_initialization=1 ...
*
* Temporary artifacts
*
* During initialization phase of the 7-Zip-JBinding the native libraries from the platform jar must be extracted to the
* disk in order to be loaded into the JVM. Since the count of the native libraries (depending on the platform) can be
* greater than one, a temporary sub-directory is created to hold those native libraries. The path to the directory for
* the temporary artifacts will determined according to following rules (see {@link #createOrVerifyTmpDir(File)}:
*
* - If path specified directly using
tmpDirectory
parameter of
* {@link #initSevenZipFromPlatformJAR(File)} or {@link #initSevenZipFromPlatformJAR(String, File)} it will be used
* - If no path specified directly, the system property
java.io.tmpdir
get used
* - If the system property
java.io.tmpdir
isn't set, an exception get raised
*
*
* The list of the temporary created artifact can be obtained with {@link #getTemporaryArtifacts()}. By default,
* 7-Zip-JBinding doesn't delete those artifacts trying to reduce subsequent initialization overhead. If 7-Zip-JBinding
* finds the native libraries within the temporary directory, it uses those without further verification. In order to
* allow smoothly updates, the temporary sub-directory with the native libraries named with a unique build reference
* number. If 7-Zip-JBinding get updated, a new temporary sub-directory get created and the new native libraries get
* copied and used.
*
* Opening archives
*
* The methods for opening archive files (read-only):
*
* - {@link #openInArchive(ArchiveFormat, IInStream)} - simple open archive method.
* - {@link #openInArchive(ArchiveFormat, IInStream, IArchiveOpenCallback)} - generic open archive method. It's
* possible to open all kinds of archives providing call back object that implements following interfaces
*
* - {@link IArchiveOpenCallback} - base interface. Must be implemented by all call back classes
* - {@link ICryptoGetTextPassword} - (optional) Provides password encrypted index
* - {@link IArchiveOpenVolumeCallback} - (optional) Provides information about volumes in multipart archives.
* Currently used only for multipart
RAR
archives. For opening multipart 7z
archives use
* {@link VolumedArchiveInStream}.
*
*
* - {@link #openInArchive(ArchiveFormat, IInStream, String)} a shortcut method for opening archives with an encrypted
* index.
*
*
*
* @author Boris Brodski
* @version 4.65-1
*/
public class SevenZip {
private static final String SYSTEM_PROPERTY_TMP = "java.io.tmpdir";
private static final String SYSTEM_PROPERTY_SEVEN_ZIP_NO_DO_PRIVILEGED_INITIALIZATION = "sevenzip.no_doprivileged_initialization";
private static final String PROPERTY_SEVENZIPJBINDING_LIBNAME = "sevenzipjbinding.libname.%s";
private static final String PROPERTY_BUILD_REF = "build.ref";
private static final String SEVENZIPJBINDING_LIB_PROPERTIES_FILENAME = "sevenzipjbinding-lib.properties";
private static final String SEVENZIPJBINDING_PLATFORMS_PROPRETIES_FILENAME = "/sevenzipjbinding-platforms.properties";
private static boolean autoInitializationWillOccur = true;
private static boolean initializationSuccessful = false;
private static SevenZipNativeInitializationException lastInitializationException = null;
private static List availablePlatforms = null;
private static String usedPlatform = null;
private static File[] temporaryArtifacts = null;
/**
* Hide default constructor
*/
private SevenZip() {
}
/**
* Tests native library initialization status of SevenZipJBinding. Use {@link #getLastInitializationException()}
* method to get more information in case of initialization failure.
*
* @return true
7-Zip-JBinding native library was initialized successfully. Native library wasn't
* initialized successfully (yet).
* @see #getLastInitializationException()
* @see #isAutoInitializationWillOccur()
*/
public static boolean isInitializedSuccessfully() {
return initializationSuccessful;
}
/**
* Returns last native library initialization exception, if occurs.
*
* @return null
- no initialization exception occurred (yet), else initialization exception
* @see SevenZip#isInitializedSuccessfully()
*/
public static Throwable getLastInitializationException() {
return lastInitializationException;
}
/**
* Returns weather automatic initialization will occur or not. Automatic initialization starts before opening an
* archive, if native library wasn't already initialized manually with one of the initSevenZip...
* methods. If manual or automatic initialization failed, no further automatic initialization attempts will be made.
*
* @return true
automatic initialization will occur, false
automatic initialization will
* not occur
*
* @see #isInitializedSuccessfully()
* @see #getLastInitializationException()
*/
public static boolean isAutoInitializationWillOccur() {
return autoInitializationWillOccur;
}
/**
* Return the platform used for the initialization. The Platform is one element out of the list of available
* platforms returned by {@link #getPlatformList()}.
*
* @return the platform used for the initialization or null
if initialization wasn't performed yet.
* @see SevenZip#getPlatformList()
*/
public static String getUsedPlatform() {
return usedPlatform;
}
/**
* Load list of the available platforms out of sevenzipjbinding-Platform.jar
in the class path.
*
* @return list of the available platforms
*
* @throws SevenZipNativeInitializationException
* indicated problems finding or parsing platform property file
*/
public static List getPlatformList() throws SevenZipNativeInitializationException {
if (availablePlatforms != null) {
return availablePlatforms;
}
InputStream propertiesInputStream = SevenZip.class
.getResourceAsStream(SEVENZIPJBINDING_PLATFORMS_PROPRETIES_FILENAME);
if (propertiesInputStream == null) {
throw new SevenZipNativeInitializationException("Can not find 7-Zip-JBinding platform property file "
+ SEVENZIPJBINDING_PLATFORMS_PROPRETIES_FILENAME
+ ". Make sure the 'sevenzipjbinding-.jar' file is "
+ "in the class path or consider initializing SevenZipJBinding manualy using one of "
+ "the offered initialization methods: 'net.sf.sevenzipjbinding.SevenZip.init*()'");
}
Properties properties = new Properties();
try {
properties.load(propertiesInputStream);
} catch (IOException e) {
throwInitException(e, "Error loading existing property file "
+ SEVENZIPJBINDING_PLATFORMS_PROPRETIES_FILENAME);
}
List platformList = new ArrayList();
for (int i = 1;; i++) {
String platform = properties.getProperty("platform." + i);
if (platform == null) {
break;
}
platformList.add(platform);
}
return availablePlatforms = platformList;
}
/**
* Returns list of the temporary created artifacts (one directory and one or more files within this directory). The
* directory is always the last element in the array.
*
* @return array of {@link File}s.
*/
public static File[] getTemporaryArtifacts() {
return temporaryArtifacts;
}
/**
* Initialize native SevenZipJBinding library assuming sevenzipjbinding-Platform.jar
on the
* class path. The platform depended library will be extracted from the jar file and copied to the temporary
* directory. Then it will be loaded into JVM using {@link System#load(String)} method. Finally the library specific
* native initialization method will be called. Please see JavaDoc of {@link SevenZip} for detailed information.
*
* If libraries for more that one platform exists, the choice will be made by calling
* {@link #getPlatformBestMatch()} method. Use {@link #initSevenZipFromPlatformJAR(String)} to set platform
* manually.
*
* @throws SevenZipNativeInitializationException
* indicated problems finding a native library, coping it into the temporary directory or loading it.
*
* @see SevenZip
* @see #initSevenZipFromPlatformJAR(File)
* @see #initSevenZipFromPlatformJAR(String)
* @see #initSevenZipFromPlatformJAR(String, File)
*/
public static void initSevenZipFromPlatformJAR() throws SevenZipNativeInitializationException {
initSevenZipFromPlatformJARIntern(null, null);
}
/**
* Initialize native SevenZipJBinding library assuming sevenzipjbinding-Platform.jar
on the
* class path. The platform depended library will be extracted from the jar file and copied to the temporary
* directory. Then it will be loaded into JVM using {@link System#load(String)} method. Finally the library specific
* native initialization method will be called. Please see JavaDoc of {@link SevenZip} for detailed information.
*
* If libraries for more that one platform exists, the choice will be made by calling
* {@link #getPlatformBestMatch()} method. Use {@link #initSevenZipFromPlatformJAR(String)} to set platform
* manually.
*
* @param tmpDirectory
* temporary directory to copy native libraries to. This directory must be writable and contain at least
* 2 MB free space.
*
* @throws SevenZipNativeInitializationException
* indicated problems finding a native library, coping it into the temporary directory or loading it.
*
* @see SevenZip
* @see #initSevenZipFromPlatformJAR()
* @see #initSevenZipFromPlatformJAR(String)
* @see #initSevenZipFromPlatformJAR(String, File)
*/
public static void initSevenZipFromPlatformJAR(File tmpDirectory) throws SevenZipNativeInitializationException {
initSevenZipFromPlatformJARIntern(null, tmpDirectory);
}
/**
* Initialize native SevenZipJBinding library assuming sevenzipjbinding-Platform.jar
on the
* class path. The platform depended library will be extracted from the jar file and copied to the temporary
* directory. Then it will be loaded into JVM using {@link System#load(String)} method. Finally the library specific
* native initialization method will be called. Please see JavaDoc of {@link SevenZip} for detailed information.
*
* If libraries for more that one platform exists, the choice will be made by calling
* {@link #getPlatformBestMatch()} method. Use {@link #initSevenZipFromPlatformJAR(String)} to set platform
* manually.
*
* @param tmpDirectory
* temporary directory to copy native libraries to. This directory must be writable and contain at least
* 2 MB free space.
*
* @param platform
* Platform to load native library for. The platform must be one of the elements of the list of available
* platforms returned by {@link #getPlatformList()}.
*
* @throws SevenZipNativeInitializationException
* indicated problems finding a native library, coping it into the temporary directory or loading it.
*
* @see SevenZip
* @see #initSevenZipFromPlatformJAR()
* @see #initSevenZipFromPlatformJAR(File)
* @see #initSevenZipFromPlatformJAR(String)
* @see #getPlatformList()
*/
public static void initSevenZipFromPlatformJAR(String platform, File tmpDirectory)
throws SevenZipNativeInitializationException {
initSevenZipFromPlatformJARIntern(platform, tmpDirectory);
}
/**
* Initialize native SevenZipJBinding library assuming sevenzipjbinding-Platform.jar
on the
* class path. The platform depended library will be extracted from the jar file and copied to the temporary
* directory. Then it will be loaded into JVM using {@link System#load(String)} method. Finally the library specific
* native initialization method will be called. Please see JavaDoc of {@link SevenZip} for detailed information.
*
* If libraries for more that one platform exists, the choice will be made by calling
* {@link #getPlatformBestMatch()} method. Use {@link #initSevenZipFromPlatformJAR(String)} to set platform
* manually.
*
* @param platform
* Platform to load native library for. The platform must be one of the elements of the list of available
* platforms returned by {@link #getPlatformList()}.
*
* @throws SevenZipNativeInitializationException
* indicated problems finding a native library, coping it into the temporary directory or loading it.
*
* @see SevenZip
* @see #initSevenZipFromPlatformJAR()
* @see #initSevenZipFromPlatformJAR(File)
* @see #initSevenZipFromPlatformJAR(String, File)
* @see #getPlatformList()
*/
public static void initSevenZipFromPlatformJAR(String platform) throws SevenZipNativeInitializationException {
initSevenZipFromPlatformJARIntern(platform, null);
}
/**
* Perform the initialization: read platform property jar and retrieve list of available platforms. Pick best
* platform or use chosen by parameter platform. Locate sevenzipjbinding-lib.properties
property file,
* read list of native libraries needed to load. Copy native library to the temporary directory passed by parameter
* or using java.io.tmpdir
system property. Load native libraries into JVM. Call 7-Zip-JBinding native
* library initialization function.
*
* @param platform
* (optional) platform to use or null
.
* @param tmpDirectory
* (optional) temporary directory to use or null
.
* @throws SevenZipNativeInitializationException
* by initialization failure
*/
private static void initSevenZipFromPlatformJARIntern(String platform, File tmpDirectory)
throws SevenZipNativeInitializationException {
try {
autoInitializationWillOccur = false;
if (initializationSuccessful) {
// Native library was already initialized successfully. No need for further initialization.
return;
}
determineAndSetUsedPlatform(platform);
Properties properties = loadSevenZipJBindingLibProperties();
File tmpDirFile = createOrVerifyTmpDir(tmpDirectory);
File sevenZipJBindingTmpDir = getOrCreateSevenZipJBindingTmpDir(tmpDirFile, properties);
List nativeLibraries = copyOrSkipLibraries(properties, sevenZipJBindingTmpDir);
loadNativeLibraries(nativeLibraries);
nativeInitialization();
} catch (SevenZipNativeInitializationException sevenZipNativeInitializationException) {
lastInitializationException = sevenZipNativeInitializationException;
throw sevenZipNativeInitializationException;
}
}
private static void determineAndSetUsedPlatform(String platform) throws SevenZipNativeInitializationException {
if (platform == null) {
usedPlatform = getPlatformBestMatch();
} else {
usedPlatform = platform;
}
}
private static Properties loadSevenZipJBindingLibProperties() throws SevenZipNativeInitializationException {
String pathInJAR = "/" + usedPlatform + "/";
// Load 'sevenzipjbinding-lib.properties'
InputStream sevenZipJBindingLibProperties = SevenZip.class.getResourceAsStream(pathInJAR
+ SEVENZIPJBINDING_LIB_PROPERTIES_FILENAME);
if (sevenZipJBindingLibProperties == null) {
throwInitException("error loading property file '"
+ pathInJAR
+ SEVENZIPJBINDING_LIB_PROPERTIES_FILENAME
+ "' from a jar-file 'sevenzipjbinding-.jar'. Is the platform jar-file not in the class path?");
}
Properties properties = new Properties();
try {
properties.load(sevenZipJBindingLibProperties);
} catch (IOException e) {
throwInitException("error loading property file '" + SEVENZIPJBINDING_LIB_PROPERTIES_FILENAME
+ "' from a jar-file 'sevenzipjbinding-.jar'");
}
return properties;
}
private static File createOrVerifyTmpDir(File tmpDirectory) throws SevenZipNativeInitializationException {
File tmpDirFile;
if (tmpDirectory != null) {
tmpDirFile = tmpDirectory;
} else {
String systemPropertyTmp = System.getProperty(SYSTEM_PROPERTY_TMP);
if (systemPropertyTmp == null) {
throwInitException("can't determinte tmp directory. Use may use -D" + SYSTEM_PROPERTY_TMP
+ "= parameter for jvm to fix this.");
}
tmpDirFile = new File(systemPropertyTmp);
}
if (!tmpDirFile.exists() || !tmpDirFile.isDirectory()) {
throwInitException("invalid tmp directory '" + tmpDirectory + "'");
}
if (!tmpDirFile.canWrite()) {
throwInitException("can't create files in '" + tmpDirFile.getAbsolutePath() + "'");
}
return tmpDirFile;
}
private static File getOrCreateSevenZipJBindingTmpDir(File tmpDirFile, Properties properties)
throws SevenZipNativeInitializationException {
String buildRef = getOrGenerateBuildRef(properties);
File tmpSubdirFile = new File(tmpDirFile.getAbsolutePath() + File.separator + "SevenZipJBinding-" + buildRef);
if (!tmpSubdirFile.exists()) {
if (!tmpSubdirFile.mkdir()) {
throwInitException("Directory '" + tmpDirFile.getAbsolutePath() + "' couldn't be created");
}
}
return tmpSubdirFile;
}
private static String getOrGenerateBuildRef(Properties properties) {
String buildRef = properties.getProperty(PROPERTY_BUILD_REF);
if (buildRef == null) {
buildRef = Integer.toString(new Random().nextInt(10000000));
}
return buildRef;
}
private static List copyOrSkipLibraries(Properties properties, File sevenZipJBindingTmpDir)
throws SevenZipNativeInitializationException {
List nativeLibraries = new ArrayList(5);
for (int i = 1;; i++) {
String propertyName = String.format(PROPERTY_SEVENZIPJBINDING_LIBNAME, Integer.valueOf(i));
String libname = properties.getProperty(propertyName);
if (libname == null) {
if (nativeLibraries.size() == 0) {
throwInitException("property file '"
+ SEVENZIPJBINDING_LIB_PROPERTIES_FILENAME
+ "' from a jar-file 'sevenzipjbinding-.jar' don't contain the property named '"
+ propertyName + "'");
} else {
break;
}
}
File libTmpFile = new File(sevenZipJBindingTmpDir.getAbsolutePath() + File.separatorChar + libname);
if (!libTmpFile.exists()) {
InputStream libInputStream = SevenZip.class.getResourceAsStream("/" + usedPlatform + "/" + libname);
if (libInputStream == null) {
throwInitException("error loading native library '" + libname
+ "' from a jar-file 'sevenzipjbinding-.jar'.");
}
copyLibraryToFS(libTmpFile, libInputStream);
}
nativeLibraries.add(libTmpFile);
}
applyTemporaryArtifacts(sevenZipJBindingTmpDir, nativeLibraries);
return nativeLibraries;
}
private static void applyTemporaryArtifacts(File sevenZipJBindingTmpDir, List nativeLibraries) {
temporaryArtifacts = new File[nativeLibraries.size() + 1];
nativeLibraries.toArray(temporaryArtifacts);
temporaryArtifacts[temporaryArtifacts.length - 1] = sevenZipJBindingTmpDir;
}
private static void loadNativeLibraries(List libraryList) throws SevenZipNativeInitializationException {
// Load native libraries in to reverse order
for (int i = libraryList.size() - 1; i != -1; i--) {
String libraryFileName = libraryList.get(i).getAbsolutePath();
try {
System.load(libraryFileName);
} catch (Throwable t) {
throw new SevenZipNativeInitializationException(
"7-Zip-JBinding initialization failed: Error loading native library: '" + libraryFileName + "'",
t);
}
}
}
/**
* Initialize 7-Zip-JBinding native library without loading libraries in JVM first. Prevent automatic loading of
* 7-Zip-JBinding native libraries into JVM. This method will only call 7-Zip-JBinding internal initialization
* method, considering all needed native libraries as loaded. It method is useful, if the java application wants to
* load 7-Zip-JBinding native libraries manually.
*
* @throws SevenZipNativeInitializationException
*/
public static void initLoadedLibraries() throws SevenZipNativeInitializationException {
if (initializationSuccessful) {
return;
}
autoInitializationWillOccur = false;
nativeInitialization();
}
private static void nativeInitialization() throws SevenZipNativeInitializationException {
String doPrivileged = System.getProperty(SYSTEM_PROPERTY_SEVEN_ZIP_NO_DO_PRIVILEGED_INITIALIZATION);
final String errorMessage[] = new String[1];
final Throwable throwable[] = new Throwable[1];
if (doPrivileged == null || doPrivileged.trim().equals("0")) {
AccessController.doPrivileged(new PrivilegedAction() {
public Void run() {
try {
errorMessage[0] = nativeInitSevenZipLibrary();
}
catch (Throwable e) {
throwable[0] = e;
}
return null;
}
});
} else {
errorMessage[0] = nativeInitSevenZipLibrary();
}
if (errorMessage[0] != null || throwable[0] != null) {
String message = errorMessage[0];
if (message == null) {
message = "No message";
}
lastInitializationException = new SevenZipNativeInitializationException(
"Error initializing 7-Zip-JBinding: " + message, throwable[0]);
throw lastInitializationException;
}
initializationSuccessful = true;
}
/**
* Open archive of type archiveFormat
from the input stream inStream
using 'archive open
* call back' listener archiveOpenCallback
. To open archive from the file, use
* {@link RandomAccessFileInStream}.
*
* @param archiveFormat
* format of archive
* @param inStream
* input stream to open archive from
* @param archiveOpenCallback
* archive open call back listener to use. You can optionally implement {@link ICryptoGetTextPassword} to
* specify password to use.
* @return implementation of {@link ISevenZipInArchive} which represents opened archive.
*
* @throws SevenZipException
* 7-Zip or 7-Zip-JBinding intern error occur. Check exception message for more information.
* @throws NullPointerException
* is thrown, if inStream is null
*
* @see #openInArchive(ArchiveFormat, IInStream, IArchiveOpenCallback)
* @see #openInArchive(ArchiveFormat, IInStream, String)
*/
public static ISevenZipInArchive openInArchive(ArchiveFormat archiveFormat, IInStream inStream,
IArchiveOpenCallback archiveOpenCallback) throws SevenZipException {
ensureLibraryIsInitialized();
if (archiveFormat != null) {
return callNativeOpenArchive(archiveFormat.getMethodName(), inStream, archiveOpenCallback);
}
return callNativeOpenArchive(null, inStream, archiveOpenCallback);
}
/**
* Open archive of type archiveFormat
from the input stream inStream
using 'archive open
* call-back' listener archiveOpenCallback
. To open archive from the file, use
* {@link RandomAccessFileInStream}.
*
* @param archiveFormat
* format of archive
* @param inStream
* input stream to open archive from
* @param passwordForOpen
* password to use. Warning: this password will not be used to extract item from archive but only to open
* archive. (7-zip format supports encrypted filename)
* @return implementation of {@link ISevenZipInArchive} which represents opened archive.
*
* @throws SevenZipException
* 7-Zip or 7-Zip-JBinding intern error occur. Check exception message for more information.
* @throws NullPointerException
* is thrown, if inStream is null
*
* @see #openInArchive(ArchiveFormat, IInStream)
* @see #openInArchive(ArchiveFormat, IInStream, IArchiveOpenCallback)
*/
public static ISevenZipInArchive openInArchive(ArchiveFormat archiveFormat, IInStream inStream,
String passwordForOpen) throws SevenZipException {
ensureLibraryIsInitialized();
if (archiveFormat != null) {
return callNativeOpenArchive(archiveFormat.getMethodName(), inStream, new ArchiveOpenCryptoCallback(
passwordForOpen));
}
return callNativeOpenArchive(null, inStream, new ArchiveOpenCryptoCallback(passwordForOpen));
}
/**
* Open archive of type archiveFormat
from the input stream inStream
. To open archive from
* the file, use {@link RandomAccessFileInStream}.
*
* @param archiveFormat
* (optional) format of archive. If null
archive format will be auto-detected.
* @param inStream
* input stream to open archive from
* @return implementation of {@link ISevenZipInArchive} which represents opened archive.
*
* @throws SevenZipException
* 7-Zip or 7-Zip-JBinding intern error occur. Check exception message for more information.
* @throws NullPointerException
* is thrown, if inStream is null
*
* @see #openInArchive(ArchiveFormat, IInStream)
* @see #openInArchive(ArchiveFormat, IInStream, String)
*/
public static ISevenZipInArchive openInArchive(ArchiveFormat archiveFormat, IInStream inStream)
throws SevenZipException {
ensureLibraryIsInitialized();
if (archiveFormat != null) {
return callNativeOpenArchive(archiveFormat.getMethodName(), inStream, new DummyOpenArchiveCallback());
}
return callNativeOpenArchive(null, inStream, new DummyOpenArchiveCallback());
}
private static void ensureLibraryIsInitialized() {
if (autoInitializationWillOccur) {
autoInitializationWillOccur = false;
try {
initSevenZipFromPlatformJAR();
} catch (SevenZipNativeInitializationException exception) {
lastInitializationException = exception;
throw new RuntimeException("SevenZipJBinding couldn't be initialized automaticly using initialization "
+ "from platform depended JAR and the default temporary directory. Please, "
+ "make sure the correct 'sevenzipjbinding-.jar' file is "
+ "in the class path or consider initializing SevenZipJBinding manualy using one of "
+ "the offered initialization methods: 'net.sf.sevenzipjbinding.SevenZip.init*()'", exception);
}
}
if (!initializationSuccessful) {
throw new RuntimeException("SevenZipJBinding wasn't initialized successfully last time.",
lastInitializationException);
}
}
private static void throwInitException(String message) throws SevenZipNativeInitializationException {
throwInitException(null, message);
}
private static void throwInitException(Exception exception, String message)
throws SevenZipNativeInitializationException {
throw new SevenZipNativeInitializationException("Error loading SevenZipJBinding native library into JVM: "
+ message + " [You may also try different SevenZipJBinding initialization methods "
+ "'net.sf.sevenzipjbinding.SevenZip.init*()' in order to solve this problem] ", exception);
}
private static void copyLibraryToFS(File toLibTmpFile, InputStream fromLibInputStream) {
FileOutputStream libTmpOutputStream = null;
try {
libTmpOutputStream = new FileOutputStream(toLibTmpFile);
byte[] buffer = new byte[65536];
while (true) {
int read = fromLibInputStream.read(buffer);
if (read > 0) {
libTmpOutputStream.write(buffer, 0, read);
} else {
break;
}
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("Error initializing SevenZipJBinding native library: "
+ "can't copy native library out of a resource file to the temporary location: '"
+ toLibTmpFile.getAbsolutePath() + "'", e);
} finally {
try {
fromLibInputStream.close();
} catch (IOException e) {
// Ignore errors here
}
try {
if (fromLibInputStream != null) {
libTmpOutputStream.close();
}
} catch (IOException e) {
// Ignore errors here
}
}
}
/**
* Return best match for the current platform out of available platforms availablePlatform
*
* @param availablePlatform
* list of the platforms to choose from
* @return platform
* @throws SevenZipNativeInitializationException
* is no platform could be chosen
*/
private static String getPlatformBestMatch() throws SevenZipNativeInitializationException {
List availablePlatform = getPlatformList();
if (availablePlatform.size() == 1) {
return availablePlatform.get(0);
}
String arch = System.getProperty("os.arch");
String system = System.getProperty("os.name").split(" ")[0];
if (availablePlatform.contains(system + "-" + arch)) {
return system + "-" + arch;
}
// TODO allow fuzzy matches
StringBuilder stringBuilder = new StringBuilder("Can't find suited platform for os.arch=");
stringBuilder.append(arch);
stringBuilder.append(", os.name=");
stringBuilder.append(system);
stringBuilder.append("... Available list of platforms: ");
for (String platform : availablePlatform) {
stringBuilder.append(platform);
stringBuilder.append(", ");
}
stringBuilder.setLength(stringBuilder.length() - 2);
throwInitException(stringBuilder.toString());
return null; // Will never happen
}
private static ISevenZipInArchive callNativeOpenArchive(String formatName, IInStream inStream,
IArchiveOpenCallback archiveOpenCallback) throws SevenZipException {
if (inStream == null) {
throw new NullPointerException("SevenZip.callNativeOpenArchive(...): inStream parameter is null");
}
return nativeOpenArchive(formatName, inStream, archiveOpenCallback);
}
private static native ISevenZipInArchive nativeOpenArchive(String formatName, IInStream inStream,
IArchiveOpenCallback archiveOpenCallback) throws SevenZipException;
private static native String nativeInitSevenZipLibrary();
private static class DummyOpenArchiveCallback implements IArchiveOpenCallback, ICryptoGetTextPassword {
/**
* {@inheritDoc}
*/
public void setCompleted(Long files, Long bytes) {
}
/**
* {@inheritDoc}
*/
public void setTotal(Long files, Long bytes) {
}
/**
* {@inheritDoc}
*/
public String cryptoGetTextPassword() throws SevenZipException {
throw new SevenZipException("No password was provided for opening protected archive.");
}
}
private static final class ArchiveOpenCryptoCallback implements IArchiveOpenCallback, ICryptoGetTextPassword {
private final String passwordForOpen;
public ArchiveOpenCryptoCallback(String passwordForOpen) {
this.passwordForOpen = passwordForOpen;
}
public void setCompleted(Long files, Long bytes) {
}
public void setTotal(Long files, Long bytes) {
}
public String cryptoGetTextPassword() throws SevenZipException {
return passwordForOpen;
}
}
}