nativepackedinputstream.java
来自「java调用ie浏览器demo源码,可以用在windows或者linux」· Java 代码 · 共 337 行
JAVA
337 行
/*
* Copyright (C) 2008 Sun Microsystems, Inc. All rights reserved. Use is
* subject to license terms.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the Lesser GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*/
package org.jdic.arc;
import java.io.*;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipEntry;
import java.util.zip.CRC32;
import java.util.zip.ZipException;
import org.jdic.NativeLoadMgr;
/**
* The class is responsible for CAB unpack operatrions.
* @author uta
*/
public class NativePackedInputStream extends ZipInputStream {
static {
NativeLoadMgr.loadLibrary("jdicArc");
initIDs();
}
/**
* Initialize methods and fields IDs for JNI
*/
private static native void initIDs();
/*
* fields
*/
protected InputStream is; //source stream
protected long isNative; //native handler for unpacker
protected ZipEntry entry; //current ZipEntry
protected CRC32 crc = new CRC32(); //CRC calculator/verifier
/**
* Format constant for constructor.
* Primitive stream copier. Non-functionable.
* Test purpose only
*/
public static int FORMAT_COPY = 0;
/**
* Format constant for constructor.
* CAB stream unpacker. Applies for CAB stream unpacking.
*/
public static int FORMAT_CAB = 1;
/**
* Hint constant for constructor.
* Hold all temporary buffers in temp folder as files.
*/
public static final long HINT_ON_DISK = 1;
/**
* Hint constant for constructor.
* Hold all temporary buffers in memory.
*/
public static final long HINT_IN_MEMORY = 0;
/**
* consts for getProperty call.
*/
public static int arc_time = 0;
public static int arc_attr = arc_time + 1;
public static int arc_original_size = arc_attr + 1;
public static int cab_next_file = arc_original_size + 1;
public static int cab_next_disk = cab_next_file + 1;
public static int cab_path = cab_next_disk + 1;
public static int cab_set_ID = cab_path + 1;
public static int cab_number = cab_set_ID + 1;
public static int cab_torn_file = cab_number + 1;
public static int cab_prev_file = cab_torn_file + 1;
public static int cab_prev_disk = cab_prev_file + 1;
/**
* Internal state validator
*/
void checkValid() throws IOException {
if(null == is || 0==isNative) {
throw new IOException("Empty or corrupted input stream");
}
//checkNativeValid(isNative);
}
//private static native void checkNativeValid(long isNative) throws IOException;
/**
* Constructs a wrapper for native decompressor
* @param _is the source stream
* @param iFormat the FORMAT_XXXX constant for stream format selection
* @param hint the HINT_XXXX constant
* @throws java.io.IOException
*/
public NativePackedInputStream(
InputStream _is,
int iFormat,
long hint) throws IOException
{
super(_is);
is = _is;
if(null == is) {
throw new IOException("No base input stream");
}
isNative = createNativeStream(is, iFormat, hint);
}
/**
* Constructs a wrapper for native decompressor with staff-buffers on the disk.
* @param _is the source stream
* @param iFormat the FORMAT_XXXX constant for stream format selection
* @throws java.io.IOException
*/
public NativePackedInputStream(
InputStream _is,
int iFormat) throws IOException
{
this(_is, iFormat, HINT_ON_DISK);
}
/**
* Creates native packer instance.
* @param is the source stream
* @param iFormat the FORMAT_XXXX constant for stream format selection
* @param hint the HINT_XXXX constant
* @return
* @throws java.io.IOException
*/
private static native long createNativeStream(
InputStream is,
int iFormat,
long hint) throws IOException;
/**
* See java.util.zip.ZipInputStream.available
* @return bytes available
*/
@Override
public int available() throws IOException
{
checkValid();
return null == entry ? 0 : 1;
}
/**
* Reads uncompressed data into an array of bytes. If <code>len</code> is not
* zero, the method will block until some input can be decompressed; otherwise,
* no bytes are read and <code>0</code> is returned.
* @param b the buffer into which the data is read
* @param off the start offset in the destination array <code>b</code>
* @param len the maximum number of bytes read
* @return the actual number of bytes read, or -1 if the end of the
* compressed input is reached or a preset dictionary is needed
* @exception NullPointerException If <code>b</code> is <code>null</code>.
* @exception IndexOutOfBoundsException If <code>off</code> is negative,
* <code>len</code> is negative, or <code>len</code> is greater than
* <code>b.length - off</code>
* @exception IOException if an I/O error has occurred
*/
@Override
public int read(byte[] b, int off, int len) throws IOException {
checkValid();
if (off < 0 || len < 0 || off > b.length - len) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return 0;
}
if(null == entry) {
return -1;
}
int ret = readNativeBytes(isNative, b, off, len);
if(-1 == ret){
long newCrc = crc.getValue();
long oldCrc = entry.getCrc();
//suffux L in 0xffffffffL is VERY critical!
if(0xffffffffL==(oldCrc & 0xffffffffL)){
entry.setCrc(newCrc);
oldCrc = newCrc;
}
entry = null;
if( oldCrc != newCrc ) {
throw new ZipException(
"invalid entry CRC (expected 0x" + Long.toHexString(oldCrc) +
", but got 0x" + Long.toHexString(newCrc) + ")");
}
} else {
crc.update(b, off, len);
}
return ret;
}
private static native int readNativeBytes(
long isNative,
byte[] b,
int off,
int len) throws IOException;
/**
* See java.util.zip.ZipInputStream.close.
*/
@Override
public void close() throws IOException {
if(0 != isNative) {
closeNative(isNative);
isNative = 0;
}
// this call are in super
//if(null != is)
// is.close();
super.close();
}
private static native void closeNative(long isNative);
/**
* Reads the next CAB file entry and positions the stream at the
* beginning of the entry data.
* @return the next CAB file entry, or null if there are no more entries
* @exception IOException if an I/O error has occurred
*/
@Override
public ZipEntry getNextEntry() throws IOException {
checkValid();
if(null != entry) {
closeEntry();
}
crc.reset();
return preprocessNewEntry(isNative);
}
private static native ZipEntry readNextEntryNative(long isNative);
/**
* Converts string like "1234ABCD" to number 0x1234ABCD.
* @param st the string for conversion
* @param iPos the offset for the first converted hex literal in <code>st</code>
* @param len the number of chars from <code>st</code> for conversion
* @return converted <code>long</code> value
*/
public static long HexSubstr(String st, int iPos, int len)
{
final String szHex = "0123456789abcdefABCDEF";
final byte[] Nibbles = new byte[]{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
};
int iLastPos = iPos + len;
if( iLastPos > st.length() ){
return -1;
}
long ret = 0;
for(int i = iPos; i < iLastPos; ++i){
int k = szHex.indexOf(st.charAt(i));
if( 0 > k ){
//non-hex value
return -1;
} else {
ret <<= 4;
ret |= Nibbles[k];
}
}
return ret;
}
private ZipEntry preprocessNewEntry(long isNative)
{
entry = readNextEntryNative(isNative);
if(null!=entry && !entry.isDirectory()){
String name = entry.toString();
int iDotPos = name.lastIndexOf('.');
if(-1==iDotPos){
iDotPos = name.length();
}
int iCloseInfoPos = name.lastIndexOf('}', iDotPos);
if( 0<=iCloseInfoPos ){
int iOpenInfoPos = name.lastIndexOf('{', iCloseInfoPos);
if( 0<=iOpenInfoPos ){
long crc = HexSubstr(name, iOpenInfoPos+1, 8);
if(0<=crc){
long csize = HexSubstr(name, iOpenInfoPos+10, 8);
if(0<=csize){
//cut the extended attributes information
name = name.substring(0, iOpenInfoPos) + name.substring(iDotPos);
ZipEntryAccessor.setName(entry, name);
}
}
}
}
}
return entry;
}
/**
* Returns the value for the propery specified by arc_XXXX or cab_XXXX const.
* @return custom property for current state
* consts arc_XXXX and cab_XXXX are applicable
* @exception IOException if an I/O error has occurred
*/
String getProperty(int iIndex) throws IOException {
checkValid();
return getPropertyNative(isNative, iIndex);
}
private static native String getPropertyNative(long isNative, int iIndex) throws IOException;
/**
* Closes the current CAB entry and positions the stream for reading the
* next entry.
* @exception IOException if an I/O error has occurred
*/
@Override
public void closeEntry() throws IOException {
checkValid();
if(null != entry) {
byte[] tmpbuf = new byte[1024];
while( read(tmpbuf, 0, tmpbuf.length) != -1 ) ;
}
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?