/* ====================================================================
   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
   this work for additional information regarding copyright ownership.
   The ASF licenses this file to You 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

   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.apache.poi.openxml4j.opc;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
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.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.TreeMap;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.POIDataSamples;
import org.apache.poi.POITestCase;
import org.apache.poi.POIXMLException;
import org.apache.poi.UnsupportedFileFormatException;
import org.apache.poi.openxml4j.OpenXML4JTestDataSamples;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.InvalidOperationException;
import org.apache.poi.openxml4j.exceptions.NotOfficeXmlFileException;
import org.apache.poi.openxml4j.exceptions.ODFNotOfficeXmlFileException;
import org.apache.poi.openxml4j.exceptions.OLE2NotOfficeXmlFileException;
import org.apache.poi.openxml4j.opc.internal.ContentTypeManager;
import org.apache.poi.openxml4j.opc.internal.FileHelper;
import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart;
import org.apache.poi.openxml4j.opc.internal.ZipHelper;
import org.apache.poi.openxml4j.util.ZipSecureFile;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.util.DocumentHelper;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import org.apache.poi.util.TempFile;
import org.junit.Ignore;
import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public final class TestPackage {
    private static final POILogger logger = POILogFactory.getLogger(TestPackage.class);

	/**
	 * Test that just opening and closing the file doesn't alter the document.
	 */
    @Test
	public void openSave() throws IOException, InvalidFormatException {
		String originalFile = OpenXML4JTestDataSamples.getSampleFileName("TestPackageCommon.docx");
		File targetFile = OpenXML4JTestDataSamples.getOutputFile("TestPackageOpenSaveTMP.docx");

		@SuppressWarnings("resource")
        OPCPackage p = OPCPackage.open(originalFile, PackageAccess.READ_WRITE);
		try {
    		p.save(targetFile.getAbsoluteFile());
    
    		// Compare the original and newly saved document
    		assertTrue(targetFile.exists());
    		ZipFileAssert.assertEquals(new File(originalFile), targetFile);
    		assertTrue(targetFile.delete());
		} finally {
            // use revert to not re-write the input file
            p.revert();
		}
	}

	/**
	 * Test that when we create a new Package, we give it
	 *  the correct default content types
	 * @throws IllegalAccessException 
	 * @throws NoSuchFieldException 
	 * @throws IllegalArgumentException 
	 * @throws SecurityException 
	 */
    @Test
	public void createGetsContentTypes()
    throws IOException, InvalidFormatException, SecurityException, IllegalArgumentException, NoSuchFieldException, IllegalAccessException {
		File targetFile = OpenXML4JTestDataSamples.getOutputFile("TestCreatePackageTMP.docx");

		// Zap the target file, in case of an earlier run
		if(targetFile.exists()) {
			assertTrue(targetFile.delete());
		}

		@SuppressWarnings("resource")
        OPCPackage pkg = OPCPackage.create(targetFile);

		// Check it has content types for rels and xml
		ContentTypeManager ctm = getContentTypeManager(pkg);
		assertEquals(
				"application/xml",
				ctm.getContentType(
						PackagingURIHelper.createPartName("/foo.xml")
				)
		);
		assertEquals(
				ContentTypes.RELATIONSHIPS_PART,
				ctm.getContentType(
						PackagingURIHelper.createPartName("/foo.rels")
				)
		);
		assertNull(
				ctm.getContentType(
						PackagingURIHelper.createPartName("/foo.txt")
				)
		);
		
		pkg.revert();
	}

	/**
	 * Test package creation.
	 */
    @Test
	public void createPackageAddPart() throws IOException, InvalidFormatException {
		File targetFile = OpenXML4JTestDataSamples.getOutputFile("TestCreatePackageTMP.docx");

		File expectedFile = OpenXML4JTestDataSamples.getSampleFile("TestCreatePackageOUTPUT.docx");

        // Zap the target file, in case of an earlier run
        if(targetFile.exists()) {
			assertTrue(targetFile.delete());
		}

        // Create a package
        OPCPackage pkg = OPCPackage.create(targetFile);
        PackagePartName corePartName = PackagingURIHelper
                .createPartName("/word/document.xml");

        pkg.addRelationship(corePartName, TargetMode.INTERNAL,
                PackageRelationshipTypes.CORE_DOCUMENT, "rId1");

        PackagePart corePart = pkg
                .createPart(
                        corePartName,
                        "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml");

        Document doc = DocumentHelper.createDocument();
        Element elDocument = doc.createElementNS("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w:document");
        doc.appendChild(elDocument);
        Element elBody = doc.createElementNS("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w:body");
        elDocument.appendChild(elBody);
        Element elParagraph = doc.createElementNS("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w:p");
        elBody.appendChild(elParagraph);
        Element elRun = doc.createElementNS("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w:r");
        elParagraph.appendChild(elRun);
        Element elText = doc.createElementNS("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w:t");
        elRun.appendChild(elText);
        elText.setTextContent("Hello Open XML !");

        StreamHelper.saveXmlInStream(doc, corePart.getOutputStream());
        pkg.close();

        ZipFileAssert.assertEquals(expectedFile, targetFile);
        assertTrue(targetFile.delete());
	}

	/**
	 * Tests that we can create a new package, add a core
	 *  document and another part, save and re-load and
	 *  have everything setup as expected
	 * @throws SAXException 
	 */
    @Test
	public void createPackageWithCoreDocument() throws IOException, InvalidFormatException, URISyntaxException, SAXException {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		OPCPackage pkg = OPCPackage.create(baos);

		// Add a core document
        PackagePartName corePartName = PackagingURIHelper.createPartName("/xl/workbook.xml");
        // Create main part relationship
        pkg.addRelationship(corePartName, TargetMode.INTERNAL, PackageRelationshipTypes.CORE_DOCUMENT, "rId1");
        // Create main document part
        PackagePart corePart = pkg.createPart(corePartName, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml");
        // Put in some dummy content
        OutputStream coreOut = corePart.getOutputStream();
        coreOut.write("<dummy-xml />".getBytes("UTF-8"));
        coreOut.close();

		// And another bit
        PackagePartName sheetPartName = PackagingURIHelper.createPartName("/xl/worksheets/sheet1.xml");
        PackageRelationship rel =
        	 corePart.addRelationship(sheetPartName, TargetMode.INTERNAL, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet", "rSheet1");
		assertNotNull(rel);

        PackagePart part = pkg.createPart(sheetPartName, "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml");
        assertNotNull(part);

        // Dummy content again
        coreOut = corePart.getOutputStream();
        coreOut.write("<dummy-xml2 />".getBytes("UTF-8"));
        coreOut.close();

        //add a relationship with internal target: "#Sheet1!A1"
        corePart.addRelationship(new URI("#Sheet1!A1"), TargetMode.INTERNAL, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink", "rId2");

        // Check things are as expected
        PackageRelationshipCollection coreRels =
        	pkg.getRelationshipsByType(PackageRelationshipTypes.CORE_DOCUMENT);
        assertEquals(1, coreRels.size());
        PackageRelationship coreRel = coreRels.getRelationship(0);
		assertNotNull(coreRel);
        assertEquals("/", coreRel.getSourceURI().toString());
        assertEquals("/xl/workbook.xml", coreRel.getTargetURI().toString());
        assertNotNull(pkg.getPart(coreRel));


        // Save and re-load
        pkg.close();
        File tmp = TempFile.createTempFile("testCreatePackageWithCoreDocument", ".zip");
        OutputStream fout = new FileOutputStream(tmp);
        try {
            fout.write(baos.toByteArray());
        } finally {
            fout.close();
        }
        pkg = OPCPackage.open(tmp.getPath());
        //tmp.delete();

        try {
            // Check still right
            coreRels = pkg.getRelationshipsByType(PackageRelationshipTypes.CORE_DOCUMENT);
            assertEquals(1, coreRels.size());
            coreRel = coreRels.getRelationship(0);

			assertNotNull(coreRel);
            assertEquals("/", coreRel.getSourceURI().toString());
            assertEquals("/xl/workbook.xml", coreRel.getTargetURI().toString());
            corePart = pkg.getPart(coreRel);
            assertNotNull(corePart);
    
            PackageRelationshipCollection rels = corePart.getRelationshipsByType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink");
            assertEquals(1, rels.size());
            rel = rels.getRelationship(0);
			assertNotNull(rel);
            assertEquals("Sheet1!A1", rel.getTargetURI().getRawFragment());
    
            assertMSCompatibility(pkg);
        } finally {
            pkg.close();
        }
    }

    private void assertMSCompatibility(OPCPackage pkg) throws IOException, InvalidFormatException, SAXException {
        PackagePartName relName = PackagingURIHelper.createPartName(PackageRelationship.getContainerPartRelationship());
        PackagePart relPart = pkg.getPart(relName);

        Document xmlRelationshipsDoc = DocumentHelper.readDocument(relPart.getInputStream());

        Element root = xmlRelationshipsDoc.getDocumentElement();
        NodeList nodeList = root.getElementsByTagName(PackageRelationship.RELATIONSHIP_TAG_NAME);
        int nodeCount = nodeList.getLength();
        for (int i = 0; i < nodeCount; i++) {
            Element element = (Element) nodeList.item(i);
            String value = element.getAttribute(PackageRelationship.TARGET_ATTRIBUTE_NAME);
            assertTrue("Root target must not start with a leading slash ('/'): " + value, value.charAt(0) != '/');
        }

    }

    /**
	 * Test package opening.
	 */
    @Test
	public void openPackage() throws IOException, InvalidFormatException {
		File targetFile = OpenXML4JTestDataSamples.getOutputFile("TestOpenPackageTMP.docx");

		File inputFile = OpenXML4JTestDataSamples.getSampleFile("TestOpenPackageINPUT.docx");

		File expectedFile = OpenXML4JTestDataSamples.getSampleFile("TestOpenPackageOUTPUT.docx");

		// Copy the input file in the output directory
		FileHelper.copyFile(inputFile, targetFile);

		// Create a package
		OPCPackage pkg = OPCPackage.open(targetFile.getAbsolutePath());

		// Modify core part
		PackagePartName corePartName = PackagingURIHelper
				.createPartName("/word/document.xml");

		PackagePart corePart = pkg.getPart(corePartName);

		// Delete some part to have a valid document
		for (PackageRelationship rel : corePart.getRelationships()) {
			corePart.removeRelationship(rel.getId());
			pkg.removePart(PackagingURIHelper.createPartName(PackagingURIHelper
					.resolvePartUri(corePart.getPartName().getURI(), rel
							.getTargetURI())));
		}

		// Create a content
		Document doc = DocumentHelper.createDocument();
        Element elDocument = doc.createElementNS("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w:document");
        doc.appendChild(elDocument);
        Element elBody = doc.createElementNS("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w:body");
        elDocument.appendChild(elBody);
        Element elParagraph = doc.createElementNS("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w:p");
        elBody.appendChild(elParagraph);
        Element elRun = doc.createElementNS("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w:r");
        elParagraph.appendChild(elRun);
        Element elText = doc.createElementNS("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w:t");
        elRun.appendChild(elText);
        elText.setTextContent("Hello Open XML !");

		StreamHelper.saveXmlInStream(doc, corePart.getOutputStream());

		// Save and close
		try {
			pkg.close();
		} catch (IOException e) {
			fail();
		}

		ZipFileAssert.assertEquals(expectedFile, targetFile);
		assertTrue(targetFile.delete());
	}

	/**
	 * Checks that we can write a package to a simple
	 *  OutputStream, in addition to the normal writing
	 *  to a file
	 */
    @Test
	public void saveToOutputStream() throws IOException, InvalidFormatException {
		String originalFile = OpenXML4JTestDataSamples.getSampleFileName("TestPackageCommon.docx");
		File targetFile = OpenXML4JTestDataSamples.getOutputFile("TestPackageOpenSaveTMP.docx");

		@SuppressWarnings("resource")
        OPCPackage p = OPCPackage.open(originalFile, PackageAccess.READ_WRITE);
		try {
    		FileOutputStream fout = new FileOutputStream(targetFile);
    		try {
    		    p.save(fout);
    		} finally {
    		    fout.close();
    		}
    
    		// Compare the original and newly saved document
    		assertTrue(targetFile.exists());
    		ZipFileAssert.assertEquals(new File(originalFile), targetFile);
    		assertTrue(targetFile.delete());
		} finally {
		    // use revert to not re-write the input file
		    p.revert();
		}
	}

	/**
	 * Checks that we can open+read a package from a
	 *  simple InputStream, in addition to the normal
	 *  reading from a file
	 */
    @Test
	public void openFromInputStream() throws IOException, InvalidFormatException {
		String originalFile = OpenXML4JTestDataSamples.getSampleFileName("TestPackageCommon.docx");

		FileInputStream finp = new FileInputStream(originalFile);

		@SuppressWarnings("resource")
        OPCPackage p = OPCPackage.open(finp);

		assertNotNull(p);
		assertNotNull(p.getRelationships());
		assertEquals(12, p.getParts().size());

		// Check it has the usual bits
		assertTrue(p.hasRelationships());
		assertTrue(p.containPart(PackagingURIHelper.createPartName("/_rels/.rels")));
		
		p.revert();
		finp.close();
	}

    /**
     * TODO: fix and enable
     * @throws URISyntaxException 
     */
    @Test
    @Ignore
    public void removePartRecursive() throws IOException, InvalidFormatException, URISyntaxException {
		String originalFile = OpenXML4JTestDataSamples.getSampleFileName("TestPackageCommon.docx");
		File targetFile = OpenXML4JTestDataSamples.getOutputFile("TestPackageRemovePartRecursiveOUTPUT.docx");
		File tempFile = OpenXML4JTestDataSamples.getOutputFile("TestPackageRemovePartRecursiveTMP.docx");

		@SuppressWarnings("resource")
        OPCPackage p = OPCPackage.open(originalFile, PackageAccess.READ_WRITE);
		p.removePartRecursive(PackagingURIHelper.createPartName(new URI(
				"/word/document.xml")));
		p.save(tempFile.getAbsoluteFile());

		// Compare the original and newly saved document
		assertTrue(targetFile.exists());
		ZipFileAssert.assertEquals(targetFile, tempFile);
		assertTrue(targetFile.delete());
		
		p.revert();
	}

    @Test
	public void deletePart() throws InvalidFormatException {
		TreeMap<PackagePartName, String> expectedValues;
		TreeMap<PackagePartName, String> values;

		values = new TreeMap<PackagePartName, String>();

		// Expected values
		expectedValues = new TreeMap<PackagePartName, String>();
		expectedValues.put(PackagingURIHelper.createPartName("/_rels/.rels"),
				"application/vnd.openxmlformats-package.relationships+xml");

		expectedValues
				.put(PackagingURIHelper.createPartName("/docProps/app.xml"),
						"application/vnd.openxmlformats-officedocument.extended-properties+xml");
		expectedValues.put(PackagingURIHelper
				.createPartName("/docProps/core.xml"),
				"application/vnd.openxmlformats-package.core-properties+xml");
		expectedValues
				.put(PackagingURIHelper.createPartName("/word/fontTable.xml"),
						"application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml");
		expectedValues.put(PackagingURIHelper
				.createPartName("/word/media/image1.gif"), "image/gif");
		expectedValues
				.put(PackagingURIHelper.createPartName("/word/settings.xml"),
						"application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml");
		expectedValues
				.put(PackagingURIHelper.createPartName("/word/styles.xml"),
						"application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml");
		expectedValues.put(PackagingURIHelper
				.createPartName("/word/theme/theme1.xml"),
				"application/vnd.openxmlformats-officedocument.theme+xml");
		expectedValues
				.put(
						PackagingURIHelper
								.createPartName("/word/webSettings.xml"),
						"application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml");

		String filepath =  OpenXML4JTestDataSamples.getSampleFileName("sample.docx");

		@SuppressWarnings("resource")
        OPCPackage p = OPCPackage.open(filepath, PackageAccess.READ_WRITE);
		// Remove the core part
		p.deletePart(PackagingURIHelper.createPartName("/word/document.xml"));

		for (PackagePart part : p.getParts()) {
			values.put(part.getPartName(), part.getContentType());
			logger.log(POILogger.DEBUG, part.getPartName());
		}

		// Compare expected values with values return by the package
		for (PackagePartName partName : expectedValues.keySet()) {
			assertNotNull(values.get(partName));
			assertEquals(expectedValues.get(partName), values.get(partName));
		}
		// Don't save modifications
		p.revert();
	}

    @Test
	public void deletePartRecursive() throws InvalidFormatException {
		TreeMap<PackagePartName, String> expectedValues;
		TreeMap<PackagePartName, String> values;

		values = new TreeMap<PackagePartName, String>();

		// Expected values
		expectedValues = new TreeMap<PackagePartName, String>();
		expectedValues.put(PackagingURIHelper.createPartName("/_rels/.rels"),
				"application/vnd.openxmlformats-package.relationships+xml");

		expectedValues
				.put(PackagingURIHelper.createPartName("/docProps/app.xml"),
						"application/vnd.openxmlformats-officedocument.extended-properties+xml");
		expectedValues.put(PackagingURIHelper
				.createPartName("/docProps/core.xml"),
				"application/vnd.openxmlformats-package.core-properties+xml");

		String filepath = OpenXML4JTestDataSamples.getSampleFileName("sample.docx");

		@SuppressWarnings("resource")
        OPCPackage p = OPCPackage.open(filepath, PackageAccess.READ_WRITE);
		// Remove the core part
		p.deletePartRecursive(PackagingURIHelper.createPartName("/word/document.xml"));

		for (PackagePart part : p.getParts()) {
			values.put(part.getPartName(), part.getContentType());
			logger.log(POILogger.DEBUG, part.getPartName());
		}

		// Compare expected values with values return by the package
		for (PackagePartName partName : expectedValues.keySet()) {
			assertNotNull(values.get(partName));
			assertEquals(expectedValues.get(partName), values.get(partName));
		}
		// Don't save modifications
		p.revert();
	}
	
	/**
	 * Test that we can open a file by path, and then
	 *  write changes to it.
	 */
    @Test
	public void openFileThenOverwrite() throws IOException, InvalidFormatException {
        File tempFile = TempFile.createTempFile("poiTesting","tmp");
        File origFile = OpenXML4JTestDataSamples.getSampleFile("TestPackageCommon.docx");
        FileHelper.copyFile(origFile, tempFile);
        
        // Open the temp file
        OPCPackage p = OPCPackage.open(tempFile.toString(), PackageAccess.READ_WRITE);
        // Close it
        p.close();
        // Delete it
        assertTrue(tempFile.delete());
        
        // Reset
        FileHelper.copyFile(origFile, tempFile);
        p = OPCPackage.open(tempFile.toString(), PackageAccess.READ_WRITE);
        
        // Save it to the same file - not allowed
        try {
            p.save(tempFile);
            fail("You shouldn't be able to call save(File) to overwrite the current file");
        } catch(InvalidOperationException e) {
			// expected here
		}

        p.close();
        // Delete it
        assertTrue(tempFile.delete());
        
        
        // Open it read only, then close and delete - allowed
        FileHelper.copyFile(origFile, tempFile);
        p = OPCPackage.open(tempFile.toString(), PackageAccess.READ);
        p.close();
        assertTrue(tempFile.delete());
	}
    /**
     * Test that we can open a file by path, save it
     *  to another file, then delete both
     */
    @Test
    public void openFileThenSaveDelete() throws IOException, InvalidFormatException {
        File tempFile = TempFile.createTempFile("poiTesting","tmp");
        File tempFile2 = TempFile.createTempFile("poiTesting","tmp");
        File origFile = OpenXML4JTestDataSamples.getSampleFile("TestPackageCommon.docx");
        FileHelper.copyFile(origFile, tempFile);
        
        // Open the temp file
        OPCPackage p = OPCPackage.open(tempFile.toString(), PackageAccess.READ_WRITE);

        // Save it to a different file
        p.save(tempFile2);
        p.close();
        
        // Delete both the files
        assertTrue(tempFile.delete());
        assertTrue(tempFile2.delete());
    }

	private static ContentTypeManager getContentTypeManager(OPCPackage pkg) {
	    return POITestCase.getFieldValue(OPCPackage.class, pkg, ContentTypeManager.class, "contentTypeManager");
	}

    @Test
    public void getPartsByName() throws IOException, InvalidFormatException {
        String filepath =  OpenXML4JTestDataSamples.getSampleFileName("sample.docx");

        @SuppressWarnings("resource")
        OPCPackage pkg = OPCPackage.open(filepath, PackageAccess.READ_WRITE);
        try {
            List<PackagePart> rs =  pkg.getPartsByName(Pattern.compile("/word/.*?\\.xml"));
            HashMap<String, PackagePart>  selected = new HashMap<String, PackagePart>();
    
            for(PackagePart p : rs)
                selected.put(p.getPartName().getName(), p);
    
            assertEquals(6, selected.size());
            assertTrue(selected.containsKey("/word/document.xml"));
            assertTrue(selected.containsKey("/word/fontTable.xml"));
            assertTrue(selected.containsKey("/word/settings.xml"));
            assertTrue(selected.containsKey("/word/styles.xml"));
            assertTrue(selected.containsKey("/word/theme/theme1.xml"));
            assertTrue(selected.containsKey("/word/webSettings.xml"));
        } finally {
            // use revert to not re-write the input file
            pkg.revert();
        }
    }
    
    @Test
    public void getPartSize() throws IOException, InvalidFormatException {
       String filepath =  OpenXML4JTestDataSamples.getSampleFileName("sample.docx");
       OPCPackage pkg = OPCPackage.open(filepath, PackageAccess.READ);
       try {
           int checked = 0;
           for (PackagePart part : pkg.getParts()) {
              // Can get the size of zip parts
              if (part.getPartName().getName().equals("/word/document.xml")) {
                 checked++;
                 assertEquals(ZipPackagePart.class, part.getClass());
                 assertEquals(6031L, part.getSize());
              }
              if (part.getPartName().getName().equals("/word/fontTable.xml")) {
                 checked++;
                 assertEquals(ZipPackagePart.class, part.getClass());
                 assertEquals(1312L, part.getSize());
              }
              
              // But not from the others
              if (part.getPartName().getName().equals("/docProps/core.xml")) {
                 checked++;
                 assertEquals(PackagePropertiesPart.class, part.getClass());
                 assertEquals(-1, part.getSize());
              }
           }
           // Ensure we actually found the parts we want to check
           assertEquals(3, checked);
       } finally {
           pkg.close();
       }
    }

    @Test
    public void replaceContentType()
    throws IOException, InvalidFormatException, SecurityException, IllegalArgumentException, NoSuchFieldException, IllegalAccessException {
        InputStream is = OpenXML4JTestDataSamples.openSampleStream("sample.xlsx");
        @SuppressWarnings("resource")
        OPCPackage p = OPCPackage.open(is);

        ContentTypeManager mgr = getContentTypeManager(p);

        assertTrue(mgr.isContentTypeRegister("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"));
        assertFalse(mgr.isContentTypeRegister("application/vnd.ms-excel.sheet.macroEnabled.main+xml"));

        assertTrue(
                p.replaceContentType(
                "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml",
                "application/vnd.ms-excel.sheet.macroEnabled.main+xml")
        );

        assertFalse(mgr.isContentTypeRegister("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"));
        assertTrue(mgr.isContentTypeRegister("application/vnd.ms-excel.sheet.macroEnabled.main+xml"));
        p.revert();
        is.close();
    }
    
    /**
     * Verify we give helpful exceptions (or as best we can) when
     *  supplied with non-OOXML file types (eg OLE2, ODF)
     */
    @Test
    public void NonOOXMLFileTypes() throws Exception {
        // Spreadsheet has a good mix of alternate file types
        POIDataSamples files = POIDataSamples.getSpreadSheetInstance();
        
        // OLE2 - Stream
        try {
			InputStream stream = files.openResourceAsStream("SampleSS.xls");
			try {
				OPCPackage.open(stream);
			} finally {
				stream.close();
			}
            fail("Shouldn't be able to open OLE2");
        } catch (OLE2NotOfficeXmlFileException e) {
            assertTrue(e.getMessage().contains("The supplied data appears to be in the OLE2 Format"));
            assertTrue(e.getMessage().contains("You are calling the part of POI that deals with OOXML"));
        }
        // OLE2 - File
        try {
            OPCPackage.open(files.getFile("SampleSS.xls"));
            fail("Shouldn't be able to open OLE2");
        } catch (OLE2NotOfficeXmlFileException e) {
            assertTrue(e.getMessage().contains("The supplied data appears to be in the OLE2 Format"));
            assertTrue(e.getMessage().contains("You are calling the part of POI that deals with OOXML"));
        }
        
        // Raw XML - Stream
        try {
			InputStream stream = files.openResourceAsStream("SampleSS.xml");
			try {
				OPCPackage.open(stream);
			} finally {
				stream.close();
			}
            fail("Shouldn't be able to open XML");
        } catch (NotOfficeXmlFileException e) {
            assertTrue(e.getMessage().contains("The supplied data appears to be a raw XML file"));
            assertTrue(e.getMessage().contains("Formats such as Office 2003 XML"));
        }
        // Raw XML - File
        try {
            OPCPackage.open(files.getFile("SampleSS.xml"));
            fail("Shouldn't be able to open XML");
        } catch (NotOfficeXmlFileException e) {
            assertTrue(e.getMessage().contains("The supplied data appears to be a raw XML file"));
            assertTrue(e.getMessage().contains("Formats such as Office 2003 XML"));
        }
        
        // ODF / ODS - Stream
        try {
			InputStream stream = files.openResourceAsStream("SampleSS.ods");
			try {
				OPCPackage.open(stream);
			} finally {
				stream.close();
			}
            fail("Shouldn't be able to open ODS");
        } catch (ODFNotOfficeXmlFileException e) {
            assertTrue(e.toString().contains("The supplied data appears to be in ODF"));
            assertTrue(e.toString().contains("Formats like these (eg ODS"));
        }
        // ODF / ODS - File
        try {
            OPCPackage.open(files.getFile("SampleSS.ods"));
            fail("Shouldn't be able to open ODS");
        } catch (ODFNotOfficeXmlFileException e) {
            assertTrue(e.toString().contains("The supplied data appears to be in ODF"));
            assertTrue(e.toString().contains("Formats like these (eg ODS"));
        }
        
        // Plain Text - Stream
        try {
			InputStream stream = files.openResourceAsStream("SampleSS.txt");
			try {
				OPCPackage.open(stream);
			} finally {
				stream.close();
			}
            fail("Shouldn't be able to open Plain Text");
        } catch (NotOfficeXmlFileException e) {
            assertTrue(e.getMessage().contains("No valid entries or contents found"));
            assertTrue(e.getMessage().contains("not a valid OOXML"));
        }
        // Plain Text - File
        try {
            OPCPackage.open(files.getFile("SampleSS.txt"));
            fail("Shouldn't be able to open Plain Text");
        } catch (UnsupportedFileFormatException e) {
            // Unhelpful low-level error, sorry
        }
    }

    @Test(expected=IOException.class)
    public void zipBombCreateAndHandle()
    throws IOException, EncryptedDocumentException, InvalidFormatException {
        // #50090 / #56865
        ZipFile zipFile = ZipHelper.openZipFile(OpenXML4JTestDataSamples.getSampleFile("sample.xlsx"));
		assertNotNull(zipFile);

		ByteArrayOutputStream bos = new ByteArrayOutputStream(2500000);
		ZipOutputStream append = new ZipOutputStream(bos);
		// first, copy contents from existing war
        Enumeration<? extends ZipEntry> entries = zipFile.entries();
        while (entries.hasMoreElements()) {
            ZipEntry e2 = entries.nextElement();
            ZipEntry e = new ZipEntry(e2.getName());
            e.setTime(e2.getTime());
            e.setComment(e2.getComment());
            e.setSize(e2.getSize());
            
            append.putNextEntry(e);
            if (!e.isDirectory()) {
                InputStream is = zipFile.getInputStream(e);
                if (e.getName().equals("[Content_Types].xml")) {
                    ByteArrayOutputStream bos2 = new ByteArrayOutputStream();
                    IOUtils.copy(is, bos2);
                    long size = bos2.size()-"</Types>".length();
                    append.write(bos2.toByteArray(), 0, (int)size);
                    byte spam[] = new byte[0x7FFF];
                    for (int i=0; i<spam.length; i++) spam[i] = ' ';
                    // 0x7FFF0000 is the maximum for 32-bit zips, but less still works
                    while (size < 0x7FFF00) {
                        append.write(spam);
                        size += spam.length;
                    }
                    append.write("</Types>".getBytes("UTF-8"));
                    size += 8;
                    e.setSize(size);
                } else {
                    IOUtils.copy(is, append);
                }
                is.close();
            }
            append.closeEntry();
        }
        
        append.close();
        zipFile.close();

        byte buf[] = bos.toByteArray();
		//noinspection UnusedAssignment
		bos = null;
        
        Workbook wb = WorkbookFactory.create(new ByteArrayInputStream(buf));
        wb.getSheetAt(0);
        wb.close();
        zipFile.close();
    }
    
    @Test
    public void zipBombCheckSizes()
    throws IOException, EncryptedDocumentException, InvalidFormatException {
        File file = OpenXML4JTestDataSamples.getSampleFile("sample.xlsx");

        try {
            double min_ratio = Double.MAX_VALUE;
            long max_size = 0;
            ZipFile zf = ZipHelper.openZipFile(file);
			assertNotNull(zf);
            Enumeration<? extends ZipEntry> entries = zf.entries();
            while (entries.hasMoreElements()) {
                ZipEntry ze = entries.nextElement();
                double ratio = (double)ze.getCompressedSize() / (double)ze.getSize();
                min_ratio = Math.min(min_ratio, ratio);
                max_size = Math.max(max_size, ze.getSize());
            }
            zf.close();
    
            // use values close to, but within the limits 
            ZipSecureFile.setMinInflateRatio(min_ratio-0.002);
			assertEquals(min_ratio-0.002, ZipSecureFile.getMinInflateRatio(), 0.00001);
            ZipSecureFile.setMaxEntrySize(max_size+1);
			assertEquals(max_size+1, ZipSecureFile.getMaxEntrySize());
			
            WorkbookFactory.create(file, null, true).close();
    
            // check ratio out of bounds
            ZipSecureFile.setMinInflateRatio(min_ratio+0.002);
            try {
                WorkbookFactory.create(file, null, true).close();
                // this is a bit strange, as there will be different exceptions thrown
                // depending if this executed via "ant test" or within eclipse
                // maybe a difference in JDK ...
            } catch (InvalidFormatException e) {
                checkForZipBombException(e);
            } catch (POIXMLException e) {
                checkForZipBombException(e);
            }
    
            // check max entry size ouf of bounds
            ZipSecureFile.setMinInflateRatio(min_ratio-0.002);
            ZipSecureFile.setMaxEntrySize(max_size-1);
            try {
                WorkbookFactory.create(file, null, true).close();
            } catch (InvalidFormatException e) {
                checkForZipBombException(e);
            } catch (POIXMLException e) {
                checkForZipBombException(e);
            }
        } finally {
            // reset otherwise a lot of ooxml tests will fail
            ZipSecureFile.setMinInflateRatio(0.01d);
            ZipSecureFile.setMaxEntrySize(0xFFFFFFFFL);
        }
    }

    private void checkForZipBombException(Throwable e) {
        if(e instanceof InvocationTargetException) {
            InvocationTargetException t = (InvocationTargetException)e;
            IOException t2 = (IOException)t.getTargetException();
            if(t2.getMessage().startsWith("Zip bomb detected!")) {
                return;
            }
        }
        
        String msg = e.getMessage();
        if(msg != null && msg.startsWith("Zip bomb detected!")) {
            return;
        }
        
        // recursively check the causes for the message as it can be nested further down in the exception-tree
        if(e.getCause() != null && e.getCause() != e) {
            checkForZipBombException(e.getCause());
            return;
        }

        throw new IllegalStateException("Expected to catch an Exception because of a detected Zip Bomb, but did not find the related error message in the exception", e);        
    }

    @Test
    public void testConstructors() throws IOException {
        // verify the various ways to construct a ZipSecureFile
        File file = OpenXML4JTestDataSamples.getSampleFile("sample.xlsx");
        ZipSecureFile zipFile = new ZipSecureFile(file);
        assertNotNull(zipFile.getName());
        zipFile.close();

        zipFile = new ZipSecureFile(file, ZipFile.OPEN_READ);
        assertNotNull(zipFile.getName());
        zipFile.close();

        zipFile = new ZipSecureFile(file.getAbsolutePath());
        assertNotNull(zipFile.getName());
        zipFile.close();
    }

    @Test
    public void testMaxTextSize() {
        long before = ZipSecureFile.getMaxTextSize();
        try {
            ZipSecureFile.setMaxTextSize(12345);
            assertEquals(12345, ZipSecureFile.getMaxTextSize());
        } finally {
            ZipSecureFile.setMaxTextSize(before);
        }
    }
    
    // bug 60128
    @Test
    public void testCorruptFile() throws IOException {
        OPCPackage pkg = null;
        File file = OpenXML4JTestDataSamples.getSampleFile("invalid.xlsx");
        try {
            pkg = OPCPackage.open(file, PackageAccess.READ);
        } catch (Exception e) {
            System.out.println(e.getClass().getName());
            System.out.println(e.getMessage());
            e.printStackTrace();
        } finally {
            if (pkg != null) {
                pkg.close();
            }
        }
    }
}
