| /* ==================================================================== |
| 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 java.io.ByteArrayInputStream; |
| import java.io.ByteArrayOutputStream; |
| import java.io.InputStream; |
| import java.net.URI; |
| import java.util.regex.Pattern; |
| |
| import junit.framework.TestCase; |
| |
| import org.apache.poi.openxml4j.OpenXML4JTestDataSamples; |
| import org.apache.poi.util.POILogFactory; |
| import org.apache.poi.util.POILogger; |
| import org.apache.poi.xwpf.usermodel.XWPFRelation; |
| |
| |
| public class TestRelationships extends TestCase { |
| private static final String HYPERLINK_REL_TYPE = |
| "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"; |
| private static final String COMMENTS_REL_TYPE = |
| "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments"; |
| private static final String SHEET_WITH_COMMENTS = |
| "/xl/worksheets/sheet1.xml"; |
| |
| private static final POILogger logger = POILogFactory.getLogger(TestPackageCoreProperties.class); |
| |
| /** |
| * Test relationships are correctly loaded. This at the moment fails (as of r499) |
| * whenever a document is loaded before its correspondig .rels file has been found. |
| * The code in this case assumes there are no relationships defined, but it should |
| * really look also for not yet loaded parts. |
| */ |
| public void testLoadRelationships() throws Exception { |
| InputStream is = OpenXML4JTestDataSamples.openSampleStream("sample.xlsx"); |
| OPCPackage pkg = OPCPackage.open(is); |
| logger.log(POILogger.DEBUG, "1: " + pkg); |
| PackageRelationshipCollection rels = pkg.getRelationshipsByType(PackageRelationshipTypes.CORE_DOCUMENT); |
| PackageRelationship coreDocRelationship = rels.getRelationship(0); |
| PackagePart corePart = pkg.getPart(coreDocRelationship); |
| String relIds[] = { "rId1", "rId2", "rId3" }; |
| for (String relId : relIds) { |
| PackageRelationship rel = corePart.getRelationship(relId); |
| assertNotNull(rel); |
| PackagePartName relName = PackagingURIHelper.createPartName(rel.getTargetURI()); |
| PackagePart sheetPart = pkg.getPart(relName); |
| assertEquals("Number of relationships1 for " + sheetPart.getPartName(), 1, sheetPart.getRelationships().size()); |
| } |
| } |
| |
| /** |
| * Checks that we can fetch a collection of relations by |
| * type, then grab from within there by id |
| */ |
| public void testFetchFromCollection() throws Exception { |
| InputStream is = OpenXML4JTestDataSamples.openSampleStream("ExcelWithHyperlinks.xlsx"); |
| OPCPackage pkg = OPCPackage.open(is); |
| PackagePart sheet = pkg.getPart( |
| PackagingURIHelper.createPartName(SHEET_WITH_COMMENTS)); |
| assertNotNull(sheet); |
| |
| assertTrue(sheet.hasRelationships()); |
| assertEquals(6, sheet.getRelationships().size()); |
| |
| // Should have three hyperlinks, and one comment |
| PackageRelationshipCollection hyperlinks = |
| sheet.getRelationshipsByType(HYPERLINK_REL_TYPE); |
| PackageRelationshipCollection comments = |
| sheet.getRelationshipsByType(COMMENTS_REL_TYPE); |
| assertEquals(3, hyperlinks.size()); |
| assertEquals(1, comments.size()); |
| |
| // Check we can get bits out by id |
| // Hyperlinks are rId1, rId2 and rId3 |
| // Comment is rId6 |
| assertNotNull(hyperlinks.getRelationshipByID("rId1")); |
| assertNotNull(hyperlinks.getRelationshipByID("rId2")); |
| assertNotNull(hyperlinks.getRelationshipByID("rId3")); |
| assertNull(hyperlinks.getRelationshipByID("rId6")); |
| |
| assertNull(comments.getRelationshipByID("rId1")); |
| assertNull(comments.getRelationshipByID("rId2")); |
| assertNull(comments.getRelationshipByID("rId3")); |
| assertNotNull(comments.getRelationshipByID("rId6")); |
| |
| assertNotNull(sheet.getRelationship("rId1")); |
| assertNotNull(sheet.getRelationship("rId2")); |
| assertNotNull(sheet.getRelationship("rId3")); |
| assertNotNull(sheet.getRelationship("rId6")); |
| } |
| |
| /** |
| * Excel uses relations on sheets to store the details of |
| * external hyperlinks. Check we can load these ok. |
| */ |
| public void testLoadExcelHyperlinkRelations() throws Exception { |
| InputStream is = OpenXML4JTestDataSamples.openSampleStream("ExcelWithHyperlinks.xlsx"); |
| OPCPackage pkg = OPCPackage.open(is); |
| PackagePart sheet = pkg.getPart( |
| PackagingURIHelper.createPartName(SHEET_WITH_COMMENTS)); |
| assertNotNull(sheet); |
| |
| // rId1 is url |
| PackageRelationship url = sheet.getRelationship("rId1"); |
| assertNotNull(url); |
| assertEquals("rId1", url.getId()); |
| assertEquals("/xl/worksheets/sheet1.xml", url.getSourceURI().toString()); |
| assertEquals("http://poi.apache.org/", url.getTargetURI().toString()); |
| |
| // rId2 is file |
| PackageRelationship file = sheet.getRelationship("rId2"); |
| assertNotNull(file); |
| assertEquals("rId2", file.getId()); |
| assertEquals("/xl/worksheets/sheet1.xml", file.getSourceURI().toString()); |
| assertEquals("WithVariousData.xlsx", file.getTargetURI().toString()); |
| |
| // rId3 is mailto |
| PackageRelationship mailto = sheet.getRelationship("rId3"); |
| assertNotNull(mailto); |
| assertEquals("rId3", mailto.getId()); |
| assertEquals("/xl/worksheets/sheet1.xml", mailto.getSourceURI().toString()); |
| assertEquals("mailto:dev@poi.apache.org?subject=XSSF%20Hyperlinks", mailto.getTargetURI().toString()); |
| } |
| |
| /* |
| * Excel uses relations on sheets to store the details of |
| * external hyperlinks. Check we can create these OK, |
| * then still read them later |
| */ |
| public void testCreateExcelHyperlinkRelations() throws Exception { |
| String filepath = OpenXML4JTestDataSamples.getSampleFileName("ExcelWithHyperlinks.xlsx"); |
| OPCPackage pkg = OPCPackage.open(filepath, PackageAccess.READ_WRITE); |
| PackagePart sheet = pkg.getPart( |
| PackagingURIHelper.createPartName(SHEET_WITH_COMMENTS)); |
| assertNotNull(sheet); |
| |
| assertEquals(3, sheet.getRelationshipsByType(HYPERLINK_REL_TYPE).size()); |
| |
| // Add three new ones |
| PackageRelationship openxml4j = |
| sheet.addExternalRelationship("http://www.openxml4j.org/", HYPERLINK_REL_TYPE); |
| PackageRelationship sf = |
| sheet.addExternalRelationship("http://openxml4j.sf.net/", HYPERLINK_REL_TYPE); |
| PackageRelationship file = |
| sheet.addExternalRelationship("MyDocument.docx", HYPERLINK_REL_TYPE); |
| |
| // Check they were added properly |
| assertNotNull(openxml4j); |
| assertNotNull(sf); |
| assertNotNull(file); |
| |
| assertEquals(6, sheet.getRelationshipsByType(HYPERLINK_REL_TYPE).size()); |
| |
| assertEquals("http://www.openxml4j.org/", openxml4j.getTargetURI().toString()); |
| assertEquals("/xl/worksheets/sheet1.xml", openxml4j.getSourceURI().toString()); |
| assertEquals(HYPERLINK_REL_TYPE, openxml4j.getRelationshipType()); |
| |
| assertEquals("http://openxml4j.sf.net/", sf.getTargetURI().toString()); |
| assertEquals("/xl/worksheets/sheet1.xml", sf.getSourceURI().toString()); |
| assertEquals(HYPERLINK_REL_TYPE, sf.getRelationshipType()); |
| |
| assertEquals("MyDocument.docx", file.getTargetURI().toString()); |
| assertEquals("/xl/worksheets/sheet1.xml", file.getSourceURI().toString()); |
| assertEquals(HYPERLINK_REL_TYPE, file.getRelationshipType()); |
| |
| // Will get ids 7, 8 and 9, as we already have 1-6 |
| assertEquals("rId7", openxml4j.getId()); |
| assertEquals("rId8", sf.getId()); |
| assertEquals("rId9", file.getId()); |
| |
| |
| // Write out and re-load |
| ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
| pkg.save(baos); |
| |
| // use revert to not re-write the input file |
| pkg.revert(); |
| |
| ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); |
| pkg = OPCPackage.open(bais); |
| |
| // Check again |
| sheet = pkg.getPart( |
| PackagingURIHelper.createPartName(SHEET_WITH_COMMENTS)); |
| |
| assertEquals(6, sheet.getRelationshipsByType(HYPERLINK_REL_TYPE).size()); |
| |
| assertEquals("http://poi.apache.org/", |
| sheet.getRelationship("rId1").getTargetURI().toString()); |
| assertEquals("mailto:dev@poi.apache.org?subject=XSSF%20Hyperlinks", |
| sheet.getRelationship("rId3").getTargetURI().toString()); |
| |
| assertEquals("http://www.openxml4j.org/", |
| sheet.getRelationship("rId7").getTargetURI().toString()); |
| assertEquals("http://openxml4j.sf.net/", |
| sheet.getRelationship("rId8").getTargetURI().toString()); |
| assertEquals("MyDocument.docx", |
| sheet.getRelationship("rId9").getTargetURI().toString()); |
| } |
| |
| public void testCreateRelationsFromScratch() throws Exception { |
| ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
| OPCPackage pkg = OPCPackage.create(baos); |
| |
| PackagePart partA = |
| pkg.createPart(PackagingURIHelper.createPartName("/partA"), "text/plain"); |
| PackagePart partB = |
| pkg.createPart(PackagingURIHelper.createPartName("/partB"), "image/png"); |
| assertNotNull(partA); |
| assertNotNull(partB); |
| |
| // Internal |
| partA.addRelationship(partB.getPartName(), TargetMode.INTERNAL, "http://example/Rel"); |
| |
| // External |
| partA.addExternalRelationship("http://poi.apache.org/", "http://example/poi"); |
| partB.addExternalRelationship("http://poi.apache.org/ss/", "http://example/poi/ss"); |
| |
| // Check as expected currently |
| assertEquals("/partB", partA.getRelationship("rId1").getTargetURI().toString()); |
| assertEquals("http://poi.apache.org/", |
| partA.getRelationship("rId2").getTargetURI().toString()); |
| assertEquals("http://poi.apache.org/ss/", |
| partB.getRelationship("rId1").getTargetURI().toString()); |
| |
| |
| // Save, and re-load |
| pkg.close(); |
| ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); |
| pkg = OPCPackage.open(bais); |
| |
| partA = pkg.getPart(PackagingURIHelper.createPartName("/partA")); |
| partB = pkg.getPart(PackagingURIHelper.createPartName("/partB")); |
| |
| |
| // Check the relations |
| assertEquals(2, partA.getRelationships().size()); |
| assertEquals(1, partB.getRelationships().size()); |
| |
| assertEquals("/partB", partA.getRelationship("rId1").getTargetURI().toString()); |
| assertEquals("http://poi.apache.org/", |
| partA.getRelationship("rId2").getTargetURI().toString()); |
| assertEquals("http://poi.apache.org/ss/", |
| partB.getRelationship("rId1").getTargetURI().toString()); |
| // Check core too |
| assertEquals("/docProps/core.xml", |
| pkg.getRelationshipsByType("http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties").getRelationship(0).getTargetURI().toString()); |
| |
| |
| // Add some more |
| partB.addExternalRelationship("http://poi.apache.org/new", "http://example/poi/new"); |
| partB.addExternalRelationship("http://poi.apache.org/alt", "http://example/poi/alt"); |
| |
| // Check the relations |
| assertEquals(2, partA.getRelationships().size()); |
| assertEquals(3, partB.getRelationships().size()); |
| |
| assertEquals("/partB", partA.getRelationship("rId1").getTargetURI().toString()); |
| assertEquals("http://poi.apache.org/", |
| partA.getRelationship("rId2").getTargetURI().toString()); |
| assertEquals("http://poi.apache.org/ss/", |
| partB.getRelationship("rId1").getTargetURI().toString()); |
| assertEquals("http://poi.apache.org/new", |
| partB.getRelationship("rId2").getTargetURI().toString()); |
| assertEquals("http://poi.apache.org/alt", |
| partB.getRelationship("rId3").getTargetURI().toString()); |
| } |
| |
| |
| public void testTargetWithSpecialChars() throws Exception{ |
| OPCPackage pkg; |
| |
| String filepath = OpenXML4JTestDataSamples.getSampleFileName("50154.xlsx"); |
| pkg = OPCPackage.open(filepath); |
| assert_50154(pkg); |
| |
| ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
| pkg.save(baos); |
| |
| // use revert to not re-write the input file |
| pkg.revert(); |
| |
| ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); |
| pkg = OPCPackage.open(bais); |
| |
| assert_50154(pkg); |
| } |
| |
| public void assert_50154(OPCPackage pkg) throws Exception { |
| URI drawingURI = new URI("/xl/drawings/drawing1.xml"); |
| PackagePart drawingPart = pkg.getPart(PackagingURIHelper.createPartName(drawingURI)); |
| PackageRelationshipCollection drawingRels = drawingPart.getRelationships(); |
| |
| assertEquals(6, drawingRels.size()); |
| |
| // expected one image |
| assertEquals(1, drawingPart.getRelationshipsByType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/image").size()); |
| // and three hyperlinks |
| assertEquals(5, drawingPart.getRelationshipsByType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink").size()); |
| |
| PackageRelationship rId1 = drawingPart.getRelationship("rId1"); |
| URI parent = drawingPart.getPartName().getURI(); |
| URI rel1 = parent.relativize(rId1.getTargetURI()); |
| URI rel11 = PackagingURIHelper.relativizeURI(drawingPart.getPartName().getURI(), rId1.getTargetURI()); |
| assertEquals("'Another Sheet'!A1", rel1.getFragment()); |
| assertEquals("'Another Sheet'!A1", rel11.getFragment()); |
| |
| PackageRelationship rId2 = drawingPart.getRelationship("rId2"); |
| URI rel2 = PackagingURIHelper.relativizeURI(drawingPart.getPartName().getURI(), rId2.getTargetURI()); |
| assertEquals("../media/image1.png", rel2.getPath()); |
| |
| PackageRelationship rId3 = drawingPart.getRelationship("rId3"); |
| URI rel3 = parent.relativize(rId3.getTargetURI()); |
| assertEquals("ThirdSheet!A1", rel3.getFragment()); |
| |
| PackageRelationship rId4 = drawingPart.getRelationship("rId4"); |
| URI rel4 = parent.relativize(rId4.getTargetURI()); |
| assertEquals("'\u0410\u043F\u0430\u0447\u0435 \u041F\u041E\u0418'!A1", rel4.getFragment()); |
| |
| PackageRelationship rId5 = drawingPart.getRelationship("rId5"); |
| URI rel5 = parent.relativize(rId5.getTargetURI()); |
| // back slashed have been replaced with forward |
| assertEquals("file:///D:/chan-chan.mp3", rel5.toString()); |
| |
| PackageRelationship rId6 = drawingPart.getRelationship("rId6"); |
| URI rel6 = parent.relativize(rId6.getTargetURI()); |
| assertEquals("../../../../../../../cygwin/home/yegor/dinom/&&&[access].2010-10-26.log", rel6.getPath()); |
| assertEquals("'\u0410\u043F\u0430\u0447\u0435 \u041F\u041E\u0418'!A5", rel6.getFragment()); |
| } |
| |
| public void testSelfRelations_bug51187() throws Exception { |
| ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
| OPCPackage pkg = OPCPackage.create(baos); |
| |
| PackagePart partA = |
| pkg.createPart(PackagingURIHelper.createPartName("/partA"), "text/plain"); |
| assertNotNull(partA); |
| |
| // reference itself |
| PackageRelationship rel1 = partA.addRelationship(partA.getPartName(), TargetMode.INTERNAL, "partA"); |
| |
| |
| // Save, and re-load |
| pkg.close(); |
| ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); |
| pkg = OPCPackage.open(bais); |
| |
| partA = pkg.getPart(PackagingURIHelper.createPartName("/partA")); |
| |
| |
| // Check the relations |
| assertEquals(1, partA.getRelationships().size()); |
| |
| PackageRelationship rel2 = partA.getRelationships().getRelationship(0); |
| |
| assertEquals(rel1.getRelationshipType(), rel2.getRelationshipType()); |
| assertEquals(rel1.getId(), rel2.getId()); |
| assertEquals(rel1.getSourceURI(), rel2.getSourceURI()); |
| assertEquals(rel1.getTargetURI(), rel2.getTargetURI()); |
| assertEquals(rel1.getTargetMode(), rel2.getTargetMode()); |
| } |
| |
| public void testTrailingSpacesInURI_53282() throws Exception { |
| InputStream is = OpenXML4JTestDataSamples.openSampleStream("53282.xlsx"); |
| OPCPackage pkg = OPCPackage.open(is); |
| is.close(); |
| |
| PackageRelationshipCollection sheetRels = pkg.getPartsByName(Pattern.compile("/xl/worksheets/sheet1.xml")).get(0).getRelationships(); |
| assertEquals(3, sheetRels.size()); |
| PackageRelationship rId1 = sheetRels.getRelationshipByID("rId1"); |
| assertEquals(TargetMode.EXTERNAL, rId1.getTargetMode()); |
| URI targetUri = rId1.getTargetURI(); |
| assertEquals("mailto:nobody@nowhere.uk%C2%A0", targetUri.toASCIIString()); |
| assertEquals("nobody@nowhere.uk\u00A0", targetUri.getSchemeSpecificPart()); |
| |
| ByteArrayOutputStream out = new ByteArrayOutputStream(); |
| pkg.save(out); |
| out.close(); |
| |
| pkg = OPCPackage.open(new ByteArrayInputStream(out.toByteArray())); |
| sheetRels = pkg.getPartsByName(Pattern.compile("/xl/worksheets/sheet1.xml")).get(0).getRelationships(); |
| assertEquals(3, sheetRels.size()); |
| rId1 = sheetRels.getRelationshipByID("rId1"); |
| assertEquals(TargetMode.EXTERNAL, rId1.getTargetMode()); |
| targetUri = rId1.getTargetURI(); |
| assertEquals("mailto:nobody@nowhere.uk%C2%A0", targetUri.toASCIIString()); |
| assertEquals("nobody@nowhere.uk\u00A0", targetUri.getSchemeSpecificPart()); |
| } |
| |
| public void testEntitiesInRels_56164() throws Exception { |
| InputStream is = OpenXML4JTestDataSamples.openSampleStream("PackageRelsHasEntities.ooxml"); |
| OPCPackage p = OPCPackage.open(is); |
| is.close(); |
| |
| // Should have 3 root relationships |
| boolean foundDocRel = false, foundCorePropRel = false, foundExtPropRel = false; |
| for (PackageRelationship pr : p.getRelationships()) { |
| if (pr.getRelationshipType().equals(PackageRelationshipTypes.CORE_DOCUMENT)) |
| foundDocRel = true; |
| if (pr.getRelationshipType().equals(PackageRelationshipTypes.CORE_PROPERTIES)) |
| foundCorePropRel = true; |
| if (pr.getRelationshipType().equals(PackageRelationshipTypes.EXTENDED_PROPERTIES)) |
| foundExtPropRel = true; |
| } |
| assertTrue("Core/Doc Relationship not found in " + p.getRelationships(), foundDocRel); |
| assertTrue("Core Props Relationship not found in " + p.getRelationships(), foundCorePropRel); |
| assertTrue("Ext Props Relationship not found in " + p.getRelationships(), foundExtPropRel); |
| |
| // Should have normal work parts |
| boolean foundCoreProps = false, foundDocument = false, foundTheme1 = false; |
| for (PackagePart part : p.getParts()) { |
| if (part.getPartName().toString().equals("/docProps/core.xml")) { |
| assertEquals(ContentTypes.CORE_PROPERTIES_PART, part.getContentType()); |
| foundCoreProps = true; |
| } |
| if (part.getPartName().toString().equals("/word/document.xml")) { |
| assertEquals(XWPFRelation.DOCUMENT.getContentType(), part.getContentType()); |
| foundDocument = true; |
| } |
| if (part.getPartName().toString().equals("/word/theme/theme1.xml")) { |
| assertEquals(XWPFRelation.THEME.getContentType(), part.getContentType()); |
| foundTheme1 = true; |
| } |
| } |
| assertTrue("Core not found in " + p.getParts(), foundCoreProps); |
| assertTrue("Document not found in " + p.getParts(), foundDocument); |
| assertTrue("Theme1 not found in " + p.getParts(), foundTheme1); |
| } |
| } |