blob: b67cfcffb4eecda08216c666331966fe589cb160 [file] [log] [blame]
/************************************************************************
*
* 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();
}
}
}