/************************************************************************ | |
* | |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER | |
* | |
* Copyright 2008, 2010 Oracle and/or its affiliates. All rights reserved. | |
* | |
* Use is subject to license terms. | |
* | |
* Licensed 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. You can also | |
* obtain a copy of the License at http://odftoolkit.org/docs/license.txt | |
* | |
* 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.odftoolkit.odfdom.pkg; | |
import static org.junit.Assert.fail; | |
import java.io.BufferedInputStream; | |
import java.io.ByteArrayInputStream; | |
import java.io.ByteArrayOutputStream; | |
import java.io.File; | |
import java.io.FileInputStream; | |
import java.io.FileNotFoundException; | |
import java.io.InputStream; | |
import java.net.URI; | |
import java.util.HashMap; | |
import java.util.Map; | |
import java.util.logging.Level; | |
import java.util.logging.Logger; | |
import java.util.zip.ZipEntry; | |
import java.util.zip.ZipInputStream; | |
import java.util.zip.ZipOutputStream; | |
import javax.xml.transform.Templates; | |
import javax.xml.transform.TransformerFactory; | |
import javax.xml.transform.sax.SAXSource; | |
import javax.xml.transform.stream.StreamResult; | |
import junit.framework.Assert; | |
import org.junit.Test; | |
import org.odftoolkit.odfdom.doc.OdfDocument; | |
import org.odftoolkit.odfdom.doc.OdfPresentationDocument; | |
import org.odftoolkit.odfdom.doc.OdfSpreadsheetDocument; | |
import org.odftoolkit.odfdom.doc.OdfTextDocument; | |
import org.odftoolkit.odfdom.dom.element.draw.DrawFrameElement; | |
import org.odftoolkit.odfdom.dom.element.draw.DrawPageElement; | |
import org.odftoolkit.odfdom.dom.element.office.OfficePresentationElement; | |
import org.odftoolkit.odfdom.incubator.doc.draw.OdfDrawImage; | |
import org.odftoolkit.odfdom.type.AnyURI; | |
import org.odftoolkit.odfdom.utils.ErrorHandlerStub; | |
import org.odftoolkit.odfdom.utils.ResourceUtilities; | |
import org.xml.sax.InputSource; | |
import org.xml.sax.SAXException; | |
import org.xml.sax.helpers.DefaultHandler; | |
public class PackageTest { | |
private static final Logger LOG = Logger.getLogger(PackageTest.class.getName()); | |
private static final String mImagePath = "src/main/javadoc/doc-files/"; | |
private static final String mImageName = "ODFDOM-Layered-Model.png"; | |
private static final String mImageMediaType = "image/png"; | |
private static final String XSL_CONCAT = "xslt/concatfiles.xsl"; | |
private static final String XSL_OUTPUT = "ResolverTest.html"; | |
// ToDo: Package Structure for test output possbile? | |
// private static final String XSL_OUTPUT ="pkg" + File.separator + | |
// "ResolverTest.html"; | |
private static final String SIMPLE_ODT = "test2.odt"; | |
private static final String ODF_FORMULAR_TEST_FILE = "SimpleFormula.odf"; | |
private static final String IMAGE_TEST_FILE = "testA.jpg"; | |
private static final String IMAGE_PRESENTATION = "imageCompressed.odp"; | |
private static final String TARGET_STEP_1 = "PackageLoadTestStep1.ods"; | |
private static final String TARGET_STEP_2 = "PackageLoadTestStep2.ods"; | |
private static final String TARGET_STEP_3 = "PackageLoadTestStep3.ods"; | |
private static final String TEST_STYLE_STYLE_ATTRIBUTE_ODT = "TestStyleStyleAttribute.odt"; | |
public PackageTest() { | |
} | |
@Test | |
public void testNotCompressImages() throws Exception { | |
// create test presentation | |
OdfPresentationDocument odp = OdfPresentationDocument.newPresentationDocument(); | |
OfficePresentationElement officePresentation = odp.getContentRoot(); | |
DrawPageElement page = officePresentation.newDrawPageElement(null); | |
DrawFrameElement frame = page.newDrawFrameElement(); | |
OdfDrawImage image = (OdfDrawImage) frame.newDrawImageElement(); | |
image.newImage(ResourceUtilities.getURI(IMAGE_TEST_FILE)); | |
odp.save(ResourceUtilities.newTestOutputFile(IMAGE_PRESENTATION)); | |
// test if the image is not compressed | |
ZipInputStream zinput = new ZipInputStream(ResourceUtilities.getTestResourceAsStream(IMAGE_PRESENTATION)); | |
ZipEntry entry = zinput.getNextEntry(); | |
while (entry != null) { | |
String entryName = entry.getName(); | |
if (entryName.endsWith(".jpg")) { | |
File f = new File(ResourceUtilities.getAbsolutePath(IMAGE_TEST_FILE)); | |
Assert.assertEquals(ZipEntry.STORED, entry.getMethod()); | |
Assert.assertEquals(f.length(), entry.getSize()); | |
} | |
entry = zinput.getNextEntry(); | |
} | |
} | |
@Test | |
public void loadPackage() { | |
try { | |
// LOAD PACKAGE FORMULA | |
LOG.info("Loading an unsupported ODF Formula document as an ODF Package!"); | |
OdfPackage formulaPackage = OdfPackage.loadPackage(ResourceUtilities.getAbsolutePath(ODF_FORMULAR_TEST_FILE)); | |
Assert.assertNotNull(formulaPackage); | |
// LOAD PACKAGE IMAGE | |
LOG.info("Loading an unsupported image file as an ODF Package!"); | |
try { | |
// Exception is expected! | |
OdfPackage.loadPackage(ResourceUtilities.getAbsolutePath(IMAGE_TEST_FILE)); | |
Assert.fail(); | |
} catch (Exception e) { | |
String errorMsg = OdfPackageConstraint.PACKAGE_IS_NO_ZIP.getMessage(); | |
if (!e.getMessage().endsWith(errorMsg.substring(errorMsg.indexOf("%1$s") + 4))) { | |
LOG.log(Level.SEVERE, null, e); | |
Assert.fail(); | |
} | |
} | |
// LOAD PACKAGE IMAGE (WITH ERROR HANDLER) | |
LOG.info("Loading an unsupported image file as an ODF Package (with error handler)!"); | |
try { | |
// Exception is expected by error handler! | |
OdfPackage.loadPackage(new File(ResourceUtilities.getAbsolutePath(IMAGE_TEST_FILE)), null, new DefaultHandler()); | |
Assert.fail(); | |
} catch (SAXException e) { | |
String errorMsg = OdfPackageConstraint.PACKAGE_IS_NO_ZIP.getMessage(); | |
if (!e.getMessage().endsWith(errorMsg.substring(errorMsg.indexOf("%1$s") + 4))) { | |
LOG.log(Level.SEVERE, null, e); | |
Assert.fail(); | |
} | |
} | |
} catch (Exception e) { | |
LOG.log(Level.SEVERE, null, e); | |
Assert.fail(e.getMessage()); | |
} | |
} | |
@Test | |
public void testPackage() { | |
File tmpFile1 = ResourceUtilities.newTestOutputFile(TARGET_STEP_1); | |
File tmpFile2 = ResourceUtilities.newTestOutputFile(TARGET_STEP_2); | |
File tmpFile3 = ResourceUtilities.newTestOutputFile(TARGET_STEP_3); | |
OdfDocument doc = null; | |
try { | |
doc = OdfSpreadsheetDocument.newSpreadsheetDocument(); | |
doc.save(tmpFile1); | |
doc.close(); | |
} catch (Exception ex) { | |
LOG.log(Level.SEVERE, mImagePath, ex); | |
Assert.fail(); | |
} | |
long lengthBefore = tmpFile1.length(); | |
try { | |
// not allowed to change the document simply by open and save | |
OdfPackage odfPackage = OdfPackage.loadPackage(tmpFile1); | |
URI imageURI = new URI(mImagePath + mImageName); | |
// testing encoded none ASCII in URL path | |
String pkgRef1 = AnyURI.encodePath("Pictures/a&b.jpg"); | |
LOG.log(Level.INFO, "Attempt to write graphic to package path: {0}", pkgRef1); | |
odfPackage.insert(uri2ByteArray(imageURI), pkgRef1, mImageMediaType); | |
// testing allowed none-ASCII in URL path (see rfc1808.txt) | |
String pkgRef2 = "Pictures/a&%" + "\u00ea" + "\u00f1" + "\u00fc" + "b.jpg"; | |
LOG.log(Level.INFO, "Attempt to write graphic to package path: {0}", pkgRef2); | |
odfPackage.insert(uri2ByteArray(imageURI), pkgRef2, mImageMediaType); | |
odfPackage.save(tmpFile2); | |
long lengthAfter2 = tmpFile2.length(); | |
// the new package with the images have to be bigger | |
Assert.assertTrue(lengthBefore < lengthAfter2); | |
odfPackage.remove(pkgRef1); | |
odfPackage.remove(pkgRef2); | |
odfPackage.remove("Pictures/"); | |
odfPackage.save(tmpFile3); | |
long lengthAfter3 = tmpFile3.length(); | |
odfPackage.close(); | |
// the package without the images should be as long as before | |
Assert.assertTrue("The files \n\t" + tmpFile1.getAbsolutePath() + " and \n\t" + tmpFile3.getAbsolutePath() + " differ!", lengthBefore == lengthAfter3); | |
} catch (Exception ex) { | |
LOG.log(Level.SEVERE, mImagePath, ex); | |
Assert.fail(); | |
} | |
} | |
private static byte[] uri2ByteArray(URI uri) { | |
byte[] fileBytes = null; | |
try { | |
InputStream fileStream = null; | |
if (uri.isAbsolute()) { | |
// if the URI is absolute it can be converted to URL | |
fileStream = uri.toURL().openStream(); | |
} else { | |
// otherwise create a file class to open the transformStream | |
fileStream = new FileInputStream(uri.toString()); | |
// TODO: error handling in this case! -> allow method | |
// insert(URI, ppath, mtype)? | |
} | |
ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |
BufferedInputStream bis = new BufferedInputStream(fileStream); | |
StreamHelper.transformStream(bis, baos); | |
fileBytes = baos.toByteArray(); | |
} catch (Exception e) { | |
Logger.getLogger(PackageTest.class.getName()).log(Level.SEVERE, null, e); | |
Assert.fail(e.getMessage()); | |
e.getLocalizedMessage(); | |
} | |
return fileBytes; | |
} | |
/** | |
* Testing the XML helper and the OdfPackage to handle two files at the same | |
* time (have them open) | |
*/ | |
@Test | |
public void testResolverWithXSLT() { | |
try { | |
OdfXMLHelper helper = new OdfXMLHelper(); | |
OdfTextDocument odt = (OdfTextDocument) OdfDocument.loadDocument(ResourceUtilities.getAbsolutePath(SIMPLE_ODT)); | |
InputSource inputSource = new InputSource(ResourceUtilities.getURI(XSL_CONCAT).toString()); | |
Templates multiFileAccessTemplate = TransformerFactory.newInstance().newTemplates(new SAXSource(inputSource)); | |
File xslOut = ResourceUtilities.newTestOutputFile(XSL_OUTPUT); | |
helper.transform(odt.getPackage(), "content.xml", multiFileAccessTemplate, new StreamResult(xslOut)); | |
LOG.info("Transformed ODF document " + SIMPLE_ODT + " to " + xslOut.getAbsolutePath() + "!"); | |
File testOutputFile = new File(xslOut.getAbsolutePath()); | |
if (testOutputFile.length() < 100) { | |
String errorMsg = "The file " + xslOut.getAbsolutePath() + " is smaller than it should be. \nIt was not created from multiple package files!"; | |
LOG.severe(errorMsg); | |
Assert.fail(errorMsg); | |
} | |
} catch (Throwable t) { | |
Logger.getLogger(PackageTest.class.getName()).log(Level.SEVERE, t.getMessage(), t); | |
Assert.fail(); | |
} | |
} | |
@Test | |
public void validationTestDefault() { | |
try { | |
// default no error handler: warnings and errors are not reported | |
OdfPackage.loadPackage(ResourceUtilities.getAbsolutePath("testInvalidPkg1.odt")); | |
OdfPackage.loadPackage(ResourceUtilities.getAbsolutePath("testInvalidPkg2.odt")); | |
} catch (Exception ex) { | |
LOG.log(Level.SEVERE, null, ex); | |
Assert.fail(); | |
} | |
// default no error handler: fatal errors are reported | |
try { | |
OdfPackage.loadPackage(ResourceUtilities.getAbsolutePath("testA.jpg")); | |
Assert.fail(); | |
} catch (Exception e) { | |
String errorMsg = OdfPackageConstraint.PACKAGE_IS_NO_ZIP.getMessage(); | |
if (!e.getMessage().endsWith(errorMsg.substring(errorMsg.indexOf("%1$s") + 4))) { | |
Assert.fail(); | |
} | |
} | |
} | |
@Test | |
public void loadPackageWithoutManifest() { | |
try { | |
// regression for ODFTOOLKIT-327: invalid package without | |
// errorhandler | |
// doesn't throw NPE | |
ByteArrayOutputStream out = new ByteArrayOutputStream(); | |
ZipOutputStream zipped = new ZipOutputStream(out); | |
ZipEntry entry = new ZipEntry("someentry"); | |
zipped.putNextEntry(entry); | |
zipped.close(); | |
byte[] data = out.toByteArray(); | |
ByteArrayInputStream in = new ByteArrayInputStream(data); | |
OdfPackage pkg = OdfPackage.loadPackage(in); | |
Assert.assertNotNull(pkg); | |
} catch (Exception ex) { | |
LOG.log(Level.SEVERE, null, ex); | |
Assert.fail(); | |
} | |
} | |
@Test | |
public void validationTest() { | |
// TESTDOC1: Expected ODF Warnings | |
Map expectedWarning1 = new HashMap(); | |
expectedWarning1.put(OdfPackageConstraint.MANIFEST_LISTS_DIRECTORY, 10); | |
// TESTDOC1: Expected ODF Errors | |
Map expectedErrors1 = new HashMap(); | |
expectedErrors1.put(OdfPackageConstraint.MIMETYPE_NOT_FIRST_IN_PACKAGE, 1); | |
expectedErrors1.put(OdfPackageConstraint.MIMETYPE_IS_COMPRESSED, 1); | |
expectedErrors1.put(OdfPackageConstraint.MIMETYPE_HAS_EXTRA_FIELD, 1); | |
expectedErrors1.put(OdfPackageConstraint.MIMETYPE_DIFFERS_FROM_PACKAGE, 1); | |
expectedErrors1.put(OdfPackageConstraint.MANIFEST_LISTS_NONEXISTENT_FILE, 1); | |
ErrorHandlerStub handler1 = new ErrorHandlerStub(expectedWarning1, expectedErrors1, null); | |
handler1.setTestFilePath("testInvalidPkg1.odt"); | |
// TESTDOC2: Expected ODF Warnings | |
Map expectedWarning2 = new HashMap(); | |
expectedWarning2.put(OdfPackageConstraint.MIMETYPE_NOT_IN_PACKAGE, 1); | |
expectedWarning2.put(OdfPackageConstraint.MANIFEST_LISTS_DIRECTORY, 10); | |
// TESTDOC2: Expected ODF Errors | |
Map expectedErrors2 = new HashMap(); | |
expectedErrors2.put(OdfPackageConstraint.MANIFEST_DOES_NOT_LIST_FILE, 1); | |
expectedErrors2.put(OdfPackageConstraint.MANIFEST_LISTS_NONEXISTENT_FILE, 3); | |
ErrorHandlerStub handler2 = new ErrorHandlerStub(expectedWarning2, expectedErrors2, null); | |
handler2.setTestFilePath("testInvalidPkg2.odt"); | |
// TESTDOC3 DESCRIPTION - only mimetype file in package | |
// TESTDOC3: Expected ODF Errors | |
Map expectedErrors3 = new HashMap(); | |
expectedErrors3.put(OdfPackageConstraint.MANIFEST_NOT_IN_PACKAGE, 1); | |
expectedErrors3.put(OdfPackageConstraint.MIMETYPE_WITHOUT_MANIFEST_MEDIATYPE, 1); | |
ErrorHandlerStub handler3 = new ErrorHandlerStub(null, expectedErrors3, null); | |
handler3.setTestFilePath("testInvalidPkg3.odt"); | |
// TESTDOC4: Expected ODF FatalErrors | |
Map<ValidationConstraint, Integer> expectedFatalErrors4 = new HashMap<ValidationConstraint, Integer>(); | |
// loading a graphic instead an ODF document | |
expectedFatalErrors4.put(OdfPackageConstraint.PACKAGE_IS_NO_ZIP, 1); | |
ErrorHandlerStub handler4 = new ErrorHandlerStub(null, null, expectedFatalErrors4); | |
try { | |
OdfPackage pkg1 = OdfPackage.loadPackage(new File(ResourceUtilities.getAbsolutePath(handler1.getTestFilePath())), null, handler1); | |
Assert.assertNotNull(pkg1); | |
OdfPackage pkg2 = OdfPackage.loadPackage(new File(ResourceUtilities.getAbsolutePath(handler2.getTestFilePath())), null, handler2); | |
Assert.assertNotNull(pkg2); | |
OdfPackage pkg3 = OdfPackage.loadPackage(new File(ResourceUtilities.getAbsolutePath(handler3.getTestFilePath())), null, handler3); | |
Assert.assertNotNull(pkg3); | |
try { | |
OdfPackage.loadPackage(new File(ResourceUtilities.getAbsolutePath("testA.jpg")), null, handler4); | |
Assert.fail(); | |
} catch (Exception e) { | |
String errorMsg = OdfPackageConstraint.PACKAGE_IS_NO_ZIP.getMessage(); | |
if (!e.getMessage().endsWith(errorMsg.substring(errorMsg.indexOf("%1$s") + 4))) { | |
Assert.fail(); | |
} | |
} | |
} catch (Exception ex) { | |
LOG.log(Level.SEVERE, null, ex); | |
Assert.fail(ex.toString()); | |
} | |
handler1.validate(); | |
handler2.validate(); | |
handler3.validate(); | |
handler4.validate(); | |
} | |
@Test | |
public void testPackagePassword() { | |
File tmpFile = ResourceUtilities.newTestOutputFile("PackagePassword.ods"); | |
OdfDocument doc = null; | |
try { | |
doc = OdfSpreadsheetDocument.newSpreadsheetDocument(); | |
OdfPackage odfPackage = doc.getPackage(); | |
LOG.info("Unencrypted content.xml" + odfPackage.getRootDocument().getFileDom("content.xml").toString()); | |
odfPackage.setPassword("password"); | |
doc.save(tmpFile); | |
doc.close(); | |
// using wrong password | |
odfPackage = OdfPackage.loadPackage(tmpFile, "passwordx"); | |
byte[] contentBytes = odfPackage.getBytes("content.xml"); | |
// some encrypted XML | |
Assert.assertNotNull(contentBytes); | |
try{ | |
odfPackage.getRootDocument().getFileDom("content.xml").toString(); | |
fail("NullPointerException missing!"); | |
}catch(NullPointerException e){ | |
// as expected | |
} | |
// using correct password | |
OdfPackage odfPackage2 = OdfPackage.loadPackage(tmpFile, "password"); | |
byte[] contentBytes2 = odfPackage2.getBytes("content.xml"); | |
// some encrypted XML | |
Assert.assertNotNull(contentBytes2); | |
// due to XML parse errors null | |
LOG.info("Decrypted content.xml" + odfPackage2.getRootDocument().getFileDom("content.xml").toString()); | |
} catch (Exception ex) { | |
LOG.log(Level.SEVERE, "password test failed.", ex); | |
Assert.fail(); | |
} | |
} | |
@Test | |
public void testLoadingDocumentWithStyleStyleAttribute() { | |
try { | |
OdfDocument doc = OdfDocument.loadDocument(ResourceUtilities.getAbsolutePath(TEST_STYLE_STYLE_ATTRIBUTE_ODT)); | |
OdfElement contentRoot = doc.getContentRoot(); | |
} catch (Throwable t) { | |
Logger.getLogger(PackageTest.class.getName()).log(Level.SEVERE, t.getMessage(), t); | |
Assert.fail(); | |
} | |
} | |
} |