Skip to content

Instantly share code, notes, and snippets.

@shaobin0604
Created April 8, 2013 10:10
Show Gist options
  • Select an option

  • Save shaobin0604/5335719 to your computer and use it in GitHub Desktop.

Select an option

Save shaobin0604/5335719 to your computer and use it in GitHub Desktop.
modified apache commons vfs which support zip file containing GBK encoded file name. dependency: ant.jar from apache ant
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.commons.vfs2.provider.antzip;
import java.io.InputStream;
import java.util.HashSet;
import org.apache.tools.zip.ZipEntry;
import org.apache.commons.vfs2.FileName;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.FileType;
import org.apache.commons.vfs2.provider.AbstractFileName;
import org.apache.commons.vfs2.provider.AbstractFileObject;
/**
* A file in a Zip file system.
*
* @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
*/
public class AntZipFileObject extends AbstractFileObject implements FileObject
{
/** The ZipEntry. */
protected ZipEntry entry;
private final HashSet<String> children = new HashSet<String>();
private final AntZipFileSystem fs;
// protected final ZipFile file;
private FileType type;
protected AntZipFileObject(AbstractFileName name,
ZipEntry entry,
AntZipFileSystem fs,
boolean zipExists) throws FileSystemException
{
super(name, fs);
this.fs = fs;
setZipEntry(entry);
if (!zipExists)
{
type = FileType.IMAGINARY;
}
}
/**
* Sets the details for this file object.
*/
protected void setZipEntry(final ZipEntry entry)
{
if (this.entry != null)
{
return;
}
if ((entry == null) || (entry.isDirectory()))
{
type = FileType.FOLDER;
}
else
{
type = FileType.FILE;
}
this.entry = entry;
}
/**
* Attaches a child.
* @param childName The name of the child.
*/
public void attachChild(FileName childName)
{
children.add(childName.getBaseName());
}
/**
* Determines if this file can be written to.
*
* @return <code>true</code> if this file is writeable, <code>false</code> if not.
* @throws FileSystemException if an error occurs.
*/
@Override
public boolean isWriteable() throws FileSystemException
{
return false;
}
/**
* Returns the file's type.
*/
@Override
protected FileType doGetType()
{
return type;
}
/**
* Lists the children of the file.
*/
@Override
protected String[] doListChildren()
{
try
{
if (!getType().hasChildren())
{
return null;
}
}
catch (FileSystemException e)
{
// should not happen as the type has already been cached.
throw new RuntimeException(e);
}
return children.toArray(new String[children.size()]);
}
/**
* Returns the size of the file content (in bytes). Is only called if
* {@link #doGetType} returns {@link FileType#FILE}.
*/
@Override
protected long doGetContentSize()
{
return entry.getSize();
}
/**
* Returns the last modified time of this file.
*/
@Override
protected long doGetLastModifiedTime() throws Exception
{
return entry.getTime();
}
/**
* Creates an input stream to read the file content from. Is only called
* if {@link #doGetType} returns {@link FileType#FILE}. The input stream
* returned by this method is guaranteed to be closed before this
* method is called again.
*/
@Override
protected InputStream doGetInputStream() throws Exception
{
// VFS-210: zip allows to gather an input stream even from a directory and will
// return -1 on the first read. getType should not be expensive and keeps the tests
// running
if (!getType().hasContent())
{
throw new FileSystemException("vfs.provider/read-not-file.error", getName());
}
return fs.getZipFile().getInputStream(entry);
}
}
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.commons.vfs2.provider.antzip;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import org.apache.commons.vfs2.Capability;
import org.apache.commons.vfs2.FileName;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystem;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.FileSystemOptions;
import org.apache.commons.vfs2.FileType;
import org.apache.commons.vfs2.provider.AbstractFileName;
import org.apache.commons.vfs2.provider.AbstractLayeredFileProvider;
import org.apache.commons.vfs2.provider.FileProvider;
import org.apache.commons.vfs2.provider.LayeredFileName;
/**
* A file system provider for Zip files. Provides read-only file systems.
*
* @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
*/
public class AntZipFileProvider extends AbstractLayeredFileProvider implements FileProvider
{
/** The list of capabilities this provider supports */
protected static final Collection<Capability> capabilities =
Collections.unmodifiableCollection(Arrays.asList(new Capability[]
{
Capability.GET_LAST_MODIFIED,
Capability.GET_TYPE,
Capability.LIST_CHILDREN,
Capability.READ_CONTENT,
Capability.URI,
Capability.COMPRESS,
Capability.VIRTUAL
}));
public AntZipFileProvider()
{
super();
}
/**
* Creates a layered file system. This method is called if the file system
* is not cached.
*
* @param scheme The URI scheme.
* @param file The file to create the file system on top of.
* @return The file system.
*/
@Override
protected FileSystem doCreateFileSystem(final String scheme,
final FileObject file,
final FileSystemOptions fileSystemOptions)
throws FileSystemException
{
final AbstractFileName rootName =
new LayeredFileName(scheme, file.getName(), FileName.ROOT_PATH, FileType.FOLDER);
return new AntZipFileSystem(rootName, file, fileSystemOptions);
}
public Collection<Capability> getCapabilities()
{
return capabilities;
}
}
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.commons.vfs2.provider.antzip;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.List;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipFile;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.vfs2.Capability;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystem;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.FileSystemOptions;
import org.apache.commons.vfs2.Selectors;
import org.apache.commons.vfs2.VfsLog;
import org.apache.commons.vfs2.provider.AbstractFileName;
import org.apache.commons.vfs2.provider.AbstractFileSystem;
import org.apache.commons.vfs2.provider.UriParser;
/**
* A read-only file system for Zip/Jar files.
*
* @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
*/
public class AntZipFileSystem extends AbstractFileSystem implements FileSystem
{
private static final Log LOG = LogFactory.getLog(AntZipFileSystem.class);
private final File file;
private ZipFile zipFile;
public AntZipFileSystem(final AbstractFileName rootName,
final FileObject parentLayer,
final FileSystemOptions fileSystemOptions)
throws FileSystemException
{
super(rootName, parentLayer, fileSystemOptions);
// Make a local copy of the file
file = parentLayer.getFileSystem().replicateFile(parentLayer, Selectors.SELECT_SELF);
// Open the Zip file
if (!file.exists())
{
// Don't need to do anything
zipFile = null;
return;
}
// zipFile = createZipFile(this.file);
}
@Override
public void init() throws FileSystemException
{
super.init();
try
{
// Build the index
List<AntZipFileObject> strongRef = new ArrayList<AntZipFileObject>(100);
Enumeration<? extends ZipEntry> entries = getZipFile().getEntries();
while (entries.hasMoreElements())
{
ZipEntry entry = entries.nextElement();
AbstractFileName name = (AbstractFileName) getFileSystemManager().resolveName(getRootName(),
UriParser.encode(entry.getName()));
// Create the file
AntZipFileObject fileObj;
if (entry.isDirectory() && getFileFromCache(name) != null)
{
fileObj = (AntZipFileObject) getFileFromCache(name);
fileObj.setZipEntry(entry);
continue;
}
fileObj = createZipFileObject(name, entry);
putFileToCache(fileObj);
strongRef.add(fileObj);
fileObj.holdObject(strongRef);
// Make sure all ancestors exist
// TODO - create these on demand
AntZipFileObject parent;
for (AbstractFileName parentName = (AbstractFileName) name.getParent();
parentName != null;
fileObj = parent, parentName = (AbstractFileName) parentName.getParent())
{
// Locate the parent
parent = (AntZipFileObject) getFileFromCache(parentName);
if (parent == null)
{
parent = createZipFileObject(parentName, null);
putFileToCache(parent);
strongRef.add(parent);
parent.holdObject(strongRef);
}
// Attach child to parent
parent.attachChild(fileObj.getName());
}
}
}
finally
{
closeCommunicationLink();
}
}
protected ZipFile getZipFile() throws FileSystemException
{
if (zipFile == null && this.file.exists())
{
ZipFile zipFile = createZipFile(this.file);
this.zipFile = zipFile;
}
return zipFile;
}
protected AntZipFileObject createZipFileObject(final AbstractFileName name,
final ZipEntry entry) throws FileSystemException
{
return new AntZipFileObject(name, entry, this, true);
}
protected ZipFile createZipFile(final File file) throws FileSystemException
{
try
{
return new ZipFile(file);
}
catch (IOException ioe)
{
throw new FileSystemException("vfs.provider.zip/open-zip-file.error", file, ioe);
}
}
@Override
protected void doCloseCommunicationLink()
{
// Release the zip file
try
{
if (zipFile != null)
{
zipFile.close();
zipFile = null;
}
}
catch (final IOException e)
{
// getLogger().warn("vfs.provider.zip/close-zip-file.error :" + file, e);
VfsLog.warn(getLogger(), LOG, "vfs.provider.zip/close-zip-file.error :" + file, e);
}
}
/**
* Returns the capabilities of this file system.
*/
@Override
protected void addCapabilities(final Collection<Capability> caps)
{
caps.addAll(AntZipFileProvider.capabilities);
}
/**
* Creates a file object.
*/
@Override
protected FileObject createFile(final AbstractFileName name) throws FileSystemException
{
// This is only called for files which do not exist in the Zip file
return new AntZipFileObject(name, null, this, false);
}
/**
* will be called after all file-objects closed their streams.
protected void notifyAllStreamsClosed()
{
closeCommunicationLink();
}
*/
}
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You 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.
-->
<providers>
<default-provider class-name="org.apache.commons.vfs2.provider.url.UrlFileProvider">
</default-provider>
<provider class-name="org.apache.commons.vfs2.provider.local.DefaultLocalFileProvider">
<scheme name="file"/>
</provider>
<!-- start: remove by shaobin
<provider class-name="org.apache.commons.vfs2.provider.zip.ZipFileProvider">
<scheme name="zip"/>
</provider>
end: remove by shaobin -->
<!-- start: added by shaobin -->
<provider class-name="org.apache.commons.vfs2.provider.antzip.AntZipFileProvider">
<scheme name="zip"/>
</provider>
<!-- end: added by shaobin -->
<provider class-name="org.apache.commons.vfs2.provider.tar.TarFileProvider">
<scheme name="tar"/>
<if-available class-name="org.apache.commons.vfs2.provider.tar.TarInputStream"/>
</provider>
<provider class-name="org.apache.commons.vfs2.provider.bzip2.Bzip2FileProvider">
<scheme name="bz2"/>
<if-available class-name="org.apache.commons.vfs2.provider.bzip2.CBZip2InputStream"/>
</provider>
<provider class-name="org.apache.commons.vfs2.provider.gzip.GzipFileProvider">
<scheme name="gz"/>
</provider>
<provider class-name="org.apache.commons.vfs2.provider.jar.JarFileProvider">
<scheme name="jar"/>
<scheme name="sar"/>
<scheme name="ear"/>
<scheme name="par"/>
<scheme name="ejb3"/>
<scheme name="war"/>
</provider>
<provider class-name="org.apache.commons.vfs2.provider.temp.TemporaryFileProvider">
<scheme name="tmp"/>
</provider>
<provider class-name="org.apache.commons.vfs2.provider.ftp.FtpFileProvider">
<scheme name="ftp"/>
<if-available class-name="org.apache.commons.net.ftp.FTPFile"/>
</provider>
<provider class-name="org.apache.commons.vfs2.provider.ftps.FtpsFileProvider">
<scheme name="ftps"/>
<if-available class-name="org.apache.commons.net.ftp.FTPFile"/>
</provider>
<provider class-name="org.apache.commons.vfs2.provider.http.HttpFileProvider">
<scheme name="http"/>
<if-available class-name="org.apache.commons.httpclient.HttpClient"/>
</provider>
<provider class-name="org.apache.commons.vfs2.provider.https.HttpsFileProvider">
<scheme name="https"/>
<if-available class-name="org.apache.commons.httpclient.HttpClient"/>
</provider>
<provider class-name="org.apache.commons.vfs2.provider.sftp.SftpFileProvider">
<scheme name="sftp"/>
<if-available class-name="javax.crypto.Cipher"/>
<if-available class-name="com.jcraft.jsch.JSch"/>
</provider>
<provider class-name="org.apache.commons.vfs2.provider.res.ResourceFileProvider">
<scheme name="res"/>
</provider>
<provider class-name="org.apache.commons.vfs2.provider.webdav.WebdavFileProvider">
<scheme name="webdav"/>
<if-available class-name="org.apache.commons.httpclient.HttpClient"/>
<if-available class-name="org.apache.jackrabbit.webdav.client.methods.DavMethod"/>
</provider>
<!--
<provider class-name="org.apache.commons.vfs2.provider.svn.SvnFileProvider">
<scheme name="svnhttps"/>
</provider>
-->
<!--
<provider class-name="org.apache.commons.vfs2.provider.tar.TgzFileProvider">
<scheme name="tgz"/>
<if-available scheme="gz"/>
<if-available scheme="tar"/>
</provider>
<provider class-name="org.apache.commons.vfs2.provider.tar.Tbz2FileProvider">
<scheme name="tbz2"/>
<if-available scheme="bz2"/>
<if-available scheme="tar"/>
</provider>
-->
<provider class-name="org.apache.commons.vfs2.provider.tar.TarFileProvider">
<scheme name="tgz"/>
<if-available scheme="gz"/>
<if-available scheme="tar"/>
</provider>
<provider class-name="org.apache.commons.vfs2.provider.tar.TarFileProvider">
<scheme name="tbz2"/>
<if-available scheme="bz2"/>
<if-available scheme="tar"/>
</provider>
<provider class-name="org.apache.commons.vfs2.provider.ram.RamFileProvider">
<scheme name="ram"/>
</provider>
<extension-map extension="zip" scheme="zip"/>
<extension-map extension="tar" scheme="tar"/>
<mime-type-map mime-type="application/zip" scheme="zip"/>
<mime-type-map mime-type="application/x-tar" scheme="tar"/>
<mime-type-map mime-type="application/x-gzip" scheme="gz"/>
<!--
<mime-type-map mime-type="application/x-tgz" scheme="tgz"/>
-->
<extension-map extension="jar" scheme="jar"/>
<extension-map extension="bz2" scheme="bz2"/>
<extension-map extension="gz" scheme="gz"/>
<!--
<extension-map extension="tgz" scheme="tgz"/>
<extension-map extension="tbz2" scheme="tbz2"/>
-->
<extension-map extension="tgz" scheme="tar"/>
<extension-map extension="tbz2" scheme="tar"/>
<!--
<filter-map class-name="org.apache.commons.vfs2.content.bzip2.Bzip2Compress">
<extension name="bz2"/>
<extension name="tbz2"/>
<if-available class-name="org.apache.commons.compress.bzip2.CBZip2InputStream"/>
</filter-map>
<filter-map class-name="org.apache.commons.vfs2.content.gzip.GzipCompress">
<extension name="gz"/>
<extension name="tgz"/>
<mime-type name="application/x-tgz" />
</filter-map>
-->
</providers>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment