package org.docx4j.extras.vfs;
import java.io.IOException;
import java.io.OutputStream;
import org.apache.commons.vfs.FileObject;
import org.apache.commons.vfs.FileSystemException;
import org.docx4j.model.images.AbstractConversionImageHandler;
import org.docx4j.openpackaging.exceptions.Docx4JException;
import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPart;
public class VFSConversionImageHandler extends AbstractConversionImageHandler {
/** Creates a DefaultConversionImageHandler with java.io.tmpdir as the target directory
*/
public VFSConversionImageHandler() {
this(System.getProperty("java.io.tmpdir"), true);
}
/** Creates a DefaultConversionImageHandler with the supplied imageDirPath
*/
public VFSConversionImageHandler(String imageDirPath, boolean includeUUID) {
super(imageDirPath, includeUUID);
}
@Override
protected String createStoredImage(BinaryPart binaryPart, byte[] bytes) throws Docx4JException {
String uri = null;
try {
// To create directory:
FileObject folder = setupRootFolder(binaryPart);
// Construct a file name from the part name
String filename = setupImageName(binaryPart);
log.debug("image file name: " + filename);
uri = storeImage(binaryPart, bytes, folder, filename);
}
catch (FileSystemException fse) {
throw new Docx4JException(fse.toString(), fse);
}
catch (IOException ioe) {
throw new Docx4JException(ioe.toString(), ioe);
}
return uri;
}
protected String storeImage(BinaryPart binaryPart, byte[] bytes, FileObject folder, String filename) throws FileSystemException, IOException {
String uri = null;
FileObject imageFileObject = folder.resolveFile(filename);
if (imageFileObject.exists()) {
log.warn("Overwriting (!) existing file!");
} else {
imageFileObject.createFile();
}
// System.out.println("URL: " +
// fo.getURL().toExternalForm() );
// System.out.println("String: " + fo.toString() );
// Save the file
OutputStream out = imageFileObject.getContent().getOutputStream();
// instance of org.apache.commons.vfs.provider.DefaultFileContent$FileContentOutputStream
// which extends MonitorOutputStream
// which in turn extends BufferedOutputStream
// which in turn extends FilterOutputStream.
try {
out.write(bytes);
// return the uri
uri = fixImgSrcURL(imageFileObject);
log.info("Wrote @src='" + uri);
} finally {
try {
imageFileObject.close();
// That Closes this file, and its content.
// Closing the content in turn
// closes any open stream.
// out.flush() is unnecessary, since
// FilterOutputStream's close() does do flush() first.
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
return uri;
}
protected FileObject setupRootFolder(BinaryPart binaryPart) throws FileSystemException {
FileObject folder = VFSUtils.getFileSystemManager().resolveFile(imageDirPath);
if (!folder.exists()) {
folder.createFolder();
}
return folder;
}
/**
* imageDirPath is anything VFSJFileChooser can resolve into a FileObject.
* That's enough for saving the image. In order for a web browser to
* display it, the URI Scheme has to be something a web browser can
* understand. So at that point, webdav:// will have to become http://,
* and smb:// become file:// ...
*/
protected String fixImgSrcURL(FileObject fo) {
String itemUrl = null;
try {
itemUrl = fo.getURL().toExternalForm();
log.debug(itemUrl);
String itemUrlLower = itemUrl.toLowerCase();
if (itemUrlLower.startsWith("http://")
|| itemUrlLower.startsWith("https://")) {
return itemUrl;
} else if (itemUrlLower.startsWith("file://")) {
// we'll convert file protocol to relative reference
// if this is html output
if (fo.getParent() == null) {
return itemUrl;
} else if (fo.getParent().getURL().toExternalForm().equalsIgnoreCase(
VFSUtils.getFileSystemManager().resolveFile(System.getProperty("java.io.tmpdir")).getURL().toExternalForm() )) {
// The image is being stored in the system temp directory,
// so assume this is a pdf export, and preserve the absolute
// file path
// org.apache.commons.vfs.provider.local.LocalFile has a
// method doIsSameFile, but the point of using FileObject is
// that it won't necessarily be a local file.
return itemUrl;
} else {
// Otherwise, assume it is an html export and return a relative path
return fo.getParent().getName().getBaseName()
+ "/" + fo.getName().getBaseName();
}
} else if (itemUrlLower.startsWith("webdav://")) {
// TODO - convert to http:, dropping username / password
return itemUrl;
}
log.warn("How to handle scheme: " + itemUrl );
} catch (FileSystemException e) {
log.error("Problem fixing Img Src URL", e);
}
return itemUrl;
}
}