git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1749528 13f79535-47bb-0310-9956-ffa450edef68tags/REL_3_15_BETA2
@@ -19,17 +19,20 @@ package org.apache.poi; | |||
import static org.apache.poi.POIXMLTypeLoader.DEFAULT_XML_OPTIONS; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.io.OutputStream; | |||
import java.util.Date; | |||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; | |||
import org.apache.poi.openxml4j.exceptions.OpenXML4JException; | |||
import org.apache.poi.openxml4j.opc.ContentTypes; | |||
import org.apache.poi.openxml4j.opc.OPCPackage; | |||
import org.apache.poi.openxml4j.opc.PackagePart; | |||
import org.apache.poi.openxml4j.opc.PackagePartName; | |||
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection; | |||
import org.apache.poi.openxml4j.opc.PackageRelationshipTypes; | |||
import org.apache.poi.openxml4j.opc.PackagingURIHelper; | |||
import org.apache.poi.openxml4j.opc.StreamHelper; | |||
import org.apache.poi.openxml4j.opc.TargetMode; | |||
import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart; | |||
import org.apache.poi.openxml4j.util.Nullable; | |||
@@ -37,8 +40,9 @@ import org.apache.xmlbeans.XmlException; | |||
import org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty; | |||
/** | |||
* Wrapper around the two different kinds of OOXML properties | |||
* a document can have | |||
* Wrapper around the three different kinds of OOXML properties | |||
* and metadata a document can have (Core, Extended and Custom), | |||
* as well Thumbnails. | |||
*/ | |||
public class POIXMLProperties { | |||
private OPCPackage pkg; | |||
@@ -121,6 +125,69 @@ public class POIXMLProperties { | |||
public CustomProperties getCustomProperties() { | |||
return cust; | |||
} | |||
/** | |||
* Returns the {@link PackagePart} for the Document | |||
* Thumbnail, or <code>null</code> if there isn't one | |||
* | |||
* @return The Document Thumbnail part or null | |||
*/ | |||
protected PackagePart getThumbnailPart() { | |||
PackageRelationshipCollection rels = | |||
pkg.getRelationshipsByType(PackageRelationshipTypes.THUMBNAIL); | |||
if(rels.size() == 1) { | |||
return pkg.getPart(rels.getRelationship(0)); | |||
} | |||
return null; | |||
} | |||
/** | |||
* Returns the name of the Document thumbnail, eg | |||
* <code>thumbnail.jpeg</code>, or <code>null</code> if there | |||
* isn't one. | |||
* | |||
* @return The thumbnail filename, or null | |||
*/ | |||
public String getThumbnailFilename() { | |||
PackagePart tPart = getThumbnailPart(); | |||
if (tPart == null) return null; | |||
String name = tPart.getPartName().getName(); | |||
return name.substring(name.lastIndexOf('/')); | |||
} | |||
/** | |||
* Returns the Document thumbnail image data, or | |||
* <code>null</code> if there isn't one. | |||
* | |||
* @return The thumbnail data, or null | |||
*/ | |||
public InputStream getThumbnailImage() throws IOException { | |||
PackagePart tPart = getThumbnailPart(); | |||
if (tPart == null) return null; | |||
return tPart.getInputStream(); | |||
} | |||
/** | |||
* Sets the Thumbnail for the document, replacing any existing | |||
* one. | |||
* | |||
* @param name The filename for the thumbnail image, eg <code>thumbnail.jpg</code> | |||
* @param imageData The inputstream to read the thumbnail image from | |||
*/ | |||
public void setThumbnail(String filename, InputStream imageData) throws IOException { | |||
PackagePart tPart = getThumbnailPart(); | |||
if (tPart == null) { | |||
// New thumbnail | |||
pkg.addThumbnail(filename, imageData); | |||
} else { | |||
// Change existing | |||
String newType = ContentTypes.getContentTypeFromFileExtension(filename); | |||
if (! newType.equals(tPart.getContentType())) { | |||
throw new IllegalArgumentException("Can't set a Thumbnail of type " + | |||
newType + " when existing one is of a different type " + | |||
tPart.getContentType()); | |||
} | |||
StreamHelper.copyStream(imageData, tPart.getOutputStream()); | |||
} | |||
} | |||
/** | |||
* Commit changes to the underlying OPC package |
@@ -474,19 +474,32 @@ public abstract class OPCPackage implements RelationshipSource, Closeable { | |||
* the addition of a thumbnail in a package. You can do the same work by | |||
* using the traditionnal relationship and part mechanism. | |||
* | |||
* @param path | |||
* The full path to the image file. | |||
* @param path The full path to the image file. | |||
*/ | |||
public void addThumbnail(String path) throws IOException { | |||
// Check parameter | |||
if (path == null || path.isEmpty()) { | |||
throw new IllegalArgumentException("path"); | |||
} | |||
String name = path.substring(path.lastIndexOf(File.separatorChar) + 1); | |||
FileInputStream is = new FileInputStream(path); | |||
addThumbnail(name, is); | |||
is.close(); | |||
} | |||
/** | |||
* Add a thumbnail to the package. This method is provided to make easier | |||
* the addition of a thumbnail in a package. You can do the same work by | |||
* using the traditionnal relationship and part mechanism. | |||
* | |||
* @param path The full path to the image file. | |||
*/ | |||
public void addThumbnail(String filename, InputStream data) throws IOException { | |||
// Check parameter | |||
if ("".equals(path)) { | |||
throw new IllegalArgumentException("path"); | |||
if (filename == null || filename.isEmpty()) { | |||
throw new IllegalArgumentException("filename"); | |||
} | |||
// Get the filename from the path | |||
String filename = path | |||
.substring(path.lastIndexOf(File.separatorChar) + 1); | |||
// Create the thumbnail part name | |||
String contentType = ContentTypes | |||
.getContentTypeFromFileExtension(filename); | |||
@@ -495,10 +508,10 @@ public abstract class OPCPackage implements RelationshipSource, Closeable { | |||
thumbnailPartName = PackagingURIHelper.createPartName("/docProps/" | |||
+ filename); | |||
} catch (InvalidFormatException e) { | |||
String partName = "/docProps/thumbnail" + | |||
filename.substring(filename.lastIndexOf(".") + 1); | |||
try { | |||
thumbnailPartName = PackagingURIHelper | |||
.createPartName("/docProps/thumbnail" | |||
+ path.substring(path.lastIndexOf(".") + 1)); | |||
thumbnailPartName = PackagingURIHelper.createPartName(partName); | |||
} catch (InvalidFormatException e2) { | |||
throw new InvalidOperationException( | |||
"Can't add a thumbnail file named '" + filename + "'", e2); | |||
@@ -519,10 +532,7 @@ public abstract class OPCPackage implements RelationshipSource, Closeable { | |||
PackageRelationshipTypes.THUMBNAIL); | |||
// Copy file data to the newly created part | |||
FileInputStream is = new FileInputStream(path); | |||
StreamHelper.copyStream(is, thumbnailPart | |||
.getOutputStream()); | |||
is.close(); | |||
StreamHelper.copyStream(data, thumbnailPart.getOutputStream()); | |||
} | |||
/** |
@@ -19,9 +19,11 @@ package org.apache.poi; | |||
import static org.junit.Assert.assertEquals; | |||
import static org.junit.Assert.assertNotNull; | |||
import static org.junit.Assert.assertNull; | |||
import static org.junit.Assert.assertTrue; | |||
import static org.junit.Assert.fail; | |||
import java.io.ByteArrayInputStream; | |||
import java.io.IOException; | |||
import java.util.Calendar; | |||
import java.util.Date; | |||
@@ -42,12 +44,16 @@ import org.junit.Test; | |||
*/ | |||
public final class TestPOIXMLProperties { | |||
private XWPFDocument sampleDoc; | |||
private XWPFDocument sampleNoThumb; | |||
private POIXMLProperties _props; | |||
private CoreProperties _coreProperties; | |||
@Before | |||
public void setUp() throws IOException { | |||
sampleDoc = XWPFTestDataSamples.openSampleDocument("documentProperties.docx"); | |||
sampleNoThumb = XWPFTestDataSamples.openSampleDocument("SampleDoc.docx"); | |||
assertNotNull(sampleDoc); | |||
assertNotNull(sampleNoThumb); | |||
_props = sampleDoc.getProperties(); | |||
_coreProperties = _props.getCoreProperties(); | |||
assertNotNull(_props); | |||
@@ -56,6 +62,7 @@ public final class TestPOIXMLProperties { | |||
@After | |||
public void closeResources() throws Exception { | |||
sampleDoc.close(); | |||
sampleNoThumb.close(); | |||
} | |||
@Test | |||
@@ -214,6 +221,35 @@ public final class TestPOIXMLProperties { | |||
return utcString.equals(dateTimeUtcString); | |||
} | |||
public void testThumbnails() throws Exception { | |||
POIXMLProperties noThumbProps = sampleNoThumb.getProperties(); | |||
assertNotNull(_props.getThumbnailPart()); | |||
assertNull(noThumbProps.getThumbnailPart()); | |||
assertNotNull(_props.getThumbnailFilename()); | |||
assertNull(noThumbProps.getThumbnailFilename()); | |||
assertNotNull(_props.getThumbnailImage()); | |||
assertNull(noThumbProps.getThumbnailImage()); | |||
assertEquals("thumbnail.jpeg", _props.getThumbnailFilename()); | |||
// Adding / changing | |||
noThumbProps.setThumbnail("Testing.png", new ByteArrayInputStream(new byte[1])); | |||
assertNotNull(noThumbProps.getThumbnailPart()); | |||
assertEquals("Testing.png", noThumbProps.getThumbnailFilename()); | |||
assertNotNull(noThumbProps.getThumbnailImage()); | |||
assertEquals(1, noThumbProps.getThumbnailImage().available()); | |||
noThumbProps.setThumbnail("Testing2.png", new ByteArrayInputStream(new byte[2])); | |||
assertNotNull(noThumbProps.getThumbnailPart()); | |||
assertEquals("Testing.png", noThumbProps.getThumbnailFilename()); | |||
assertNotNull(noThumbProps.getThumbnailImage()); | |||
assertEquals(2, noThumbProps.getThumbnailImage().available()); | |||
} | |||
private static String zeroPad(long i) { | |||
if (i >= 0 && i <=9) { |