All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.healthmarketscience.jackcess.impl.CompoundOleUtil Maven / Gradle / Ivy

Go to download

A pure Java library for reading from and writing to MS Access databases.

There is a newer version: 4.0.8
Show newest version
/*
Copyright (c) 2013 James Ahlborn

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library 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
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
USA
*/

package com.healthmarketscience.jackcess.impl;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.healthmarketscience.jackcess.RuntimeIOException;
import static com.healthmarketscience.jackcess.impl.OleUtil.*;
import com.healthmarketscience.jackcess.util.MemFileChannel;
import static com.healthmarketscience.jackcess.util.OleBlob.*;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.poi.poifs.filesystem.DirectoryEntry;
import org.apache.poi.poifs.filesystem.DocumentEntry;
import org.apache.poi.poifs.filesystem.DocumentInputStream;
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;

/**
 * Utility code for working with OLE data which is in the compound storage
 * format.  This functionality relies on the optional POI library.
 * 

* Note that all POI usage is restricted to this file so that the basic ole * support in OleUtil can be utilized without requiring POI. * * @author James Ahlborn * @usage _advanced_class_ */ public class CompoundOleUtil implements OleUtil.CompoundPackageFactory { private static final String ENTRY_NAME_CHARSET = "UTF-8"; private static final String ENTRY_SEPARATOR = "/"; private static final String CONTENTS_ENTRY = "CONTENTS"; static { // force a poi class to be loaded to ensure that when this class is // loaded, we know that the poi classes are available NPOIFSFileSystem.class.getName(); } public CompoundOleUtil() { } /** * Creates a nes CompoundContent for the given blob information. */ public ContentImpl createCompoundPackageContent( OleBlobImpl blob, String prettyName, String className, String typeName, ByteBuffer blobBb, int dataBlockLen) { return new CompoundContentImpl(blob, prettyName, className, typeName, blobBb.position(), dataBlockLen); } /** * Gets a DocumentEntry from compound storage based on a fully qualified, * encoded entry name. * * @param entryName fully qualified, encoded entry name * @param dir root directory of the compound storage * * @return the relevant DocumentEntry * @throws FileNotFoundException if the entry does not exist * @throws IOException if some other io error occurs */ public static DocumentEntry getDocumentEntry(String entryName, DirectoryEntry dir) throws IOException { // split entry name into individual components and decode them List entryNames = new ArrayList(); for(String str : entryName.split(ENTRY_SEPARATOR)) { if(str.length() == 0) { continue; } entryNames.add(decodeEntryName(str)); } DocumentEntry entry = null; Iterator iter = entryNames.iterator(); while(iter.hasNext()) { org.apache.poi.poifs.filesystem.Entry tmpEntry = dir.getEntry(iter.next()); if(tmpEntry instanceof DirectoryEntry) { dir = (DirectoryEntry)tmpEntry; } else if(!iter.hasNext() && (tmpEntry instanceof DocumentEntry)) { entry = (DocumentEntry)tmpEntry; } else { break; } } if(entry == null) { throw new FileNotFoundException("Could not find document " + entryName); } return entry; } private static String encodeEntryName(String name) { try { return URLEncoder.encode(name, ENTRY_NAME_CHARSET); } catch(UnsupportedEncodingException e) { throw new RuntimeException(e); } } private static String decodeEntryName(String name) { try { return URLDecoder.decode(name, ENTRY_NAME_CHARSET); } catch(UnsupportedEncodingException e) { throw new RuntimeException(e); } } private static final class CompoundContentImpl extends EmbeddedPackageContentImpl implements CompoundContent { private NPOIFSFileSystem _fs; private CompoundContentImpl( OleBlobImpl blob, String prettyName, String className, String typeName, int position, int length) { super(blob, prettyName, className, typeName, position, length); } public ContentType getType() { return ContentType.COMPOUND_STORAGE; } private NPOIFSFileSystem getFileSystem() throws IOException { if(_fs == null) { _fs = new NPOIFSFileSystem(MemFileChannel.newChannel(getStream(), "r")); } return _fs; } public Iterator iterator() { try { return getEntries(new ArrayList(), getFileSystem().getRoot(), ENTRY_SEPARATOR).iterator(); } catch(IOException e) { throw new RuntimeIOException(e); } } public EntryImpl getEntry(String entryName) throws IOException { return new EntryImpl(entryName, getDocumentEntry(entryName, getFileSystem().getRoot())); } public boolean hasContentsEntry() throws IOException { return getFileSystem().getRoot().hasEntry(CONTENTS_ENTRY); } public EntryImpl getContentsEntry() throws IOException { return getEntry(CONTENTS_ENTRY); } private List getEntries(List entries, DirectoryEntry dir, String prefix) { for(org.apache.poi.poifs.filesystem.Entry entry : dir) { if (entry instanceof DirectoryEntry) { // .. recurse into this directory getEntries(entries, (DirectoryEntry)entry, prefix + ENTRY_SEPARATOR); } else if(entry instanceof DocumentEntry) { // grab the entry name/detils DocumentEntry de = (DocumentEntry)entry; String entryName = prefix + encodeEntryName(entry.getName()); entries.add(new EntryImpl(entryName, de)); } } return entries; } @Override public void close() { ByteUtil.closeQuietly(_fs); _fs = null; super.close(); } @Override public String toString() { ToStringBuilder sb = toString(CustomToStringStyle.builder(this)); try { sb.append("hasContentsEntry", hasContentsEntry()); sb.append("entries", getEntries(new ArrayList(), getFileSystem().getRoot(), ENTRY_SEPARATOR)); } catch(IOException e) { sb.append("entries", "<" + e + ">"); } return sb.toString(); } private final class EntryImpl implements CompoundContent.Entry { private final String _name; private final DocumentEntry _docEntry; private EntryImpl(String name, DocumentEntry docEntry) { _name = name; _docEntry = docEntry; } public ContentType getType() { return ContentType.UNKNOWN; } public String getName() { return _name; } public CompoundContentImpl getParent() { return CompoundContentImpl.this; } public OleBlobImpl getBlob() { return getParent().getBlob(); } public long length() { return _docEntry.getSize(); } public InputStream getStream() throws IOException { return new DocumentInputStream(_docEntry); } public void writeTo(OutputStream out) throws IOException { InputStream in = null; try { ByteUtil.copy(in = getStream(), out); } finally { ByteUtil.closeQuietly(in); } } @Override public String toString() { return CustomToStringStyle.valueBuilder(this) .append("name", _name) .append("length", length()) .toString(); } } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy