fixed compatibility issues with OpenOffice 3.0 and Excel 2008 Mac sp2, see Bugzilla #46419 and #47559

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@797350 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Yegor Kozlov 2009-07-24 07:29:22 +00:00
parent 32d0c7213e
commit 0f1f7d1d48
11 changed files with 91 additions and 30 deletions

View File

@ -22,10 +22,6 @@
<document> <document>
<header> <header>
<title>Busy Developers' Guide to HSSF and XSSF Features</title> <title>Busy Developers' Guide to HSSF and XSSF Features</title>
<authors>
<person email="user@poi.apache.org" name="Glen Stampoultzis" id="CO"/>
<person email="user@poi.apache.org" name="Yegor Kozlov" id="YK"/>
</authors>
</header> </header>
<body> <body>
<section><title>Busy Developers' Guide to Features</title> <section><title>Busy Developers' Guide to Features</title>

View File

@ -33,6 +33,8 @@
<changes> <changes>
<release version="3.5-beta7" date="2009-??-??"> <release version="3.5-beta7" date="2009-??-??">
<action dev="POI-DEVELOPERS" type="fix">46419 - Fixed compatibility issue with OpenOffice 3.0</action>
<action dev="POI-DEVELOPERS" type="fix">47559 - Fixed compatibility issue with Excel 2008 Max sp2</action>
<action dev="POI-DEVELOPERS" type="fix">47540 - Fix for saving custom and extended OOXML properties</action> <action dev="POI-DEVELOPERS" type="fix">47540 - Fix for saving custom and extended OOXML properties</action>
<action dev="POI-DEVELOPERS" type="fix">47535 - Fixed WordExtractor to tolerate files with empty footnote block</action> <action dev="POI-DEVELOPERS" type="fix">47535 - Fixed WordExtractor to tolerate files with empty footnote block</action>
<action dev="POI-DEVELOPERS" type="fix">47517 - Fixed ExtractorFactory to support .xltx and .dotx files</action> <action dev="POI-DEVELOPERS" type="fix">47517 - Fixed ExtractorFactory to support .xltx and .dotx files</action>

View File

@ -136,7 +136,7 @@ public final class PackageRelationship {
/* Getters */ /* Getters */
public URI getContainerPartRelationship() { public static URI getContainerPartRelationship() {
return containerRelationshipPart; return containerRelationshipPart;
} }

View File

@ -259,11 +259,14 @@ public final class PackagingURIHelper {
* The source part URI. * The source part URI.
* @param targetURI * @param targetURI
* The target part URI. * The target part URI.
* @param msCompatible if true then remove leading slash from the relativized URI.
* This flag violates [M1.4]: A part name shall start with a forward slash ('/') character, but
* allows generating URIs compatible with MS Office and OpenOffice.
* @return A fully relativize part name URI ('word/media/image1.gif', * @return A fully relativize part name URI ('word/media/image1.gif',
* '/word/document.xml' => 'media/image1.gif') else * '/word/document.xml' => 'media/image1.gif') else
* <code>null</code>. * <code>null</code>.
*/ */
public static URI relativizeURI(URI sourceURI, URI targetURI) { public static URI relativizeURI(URI sourceURI, URI targetURI, boolean msCompatible) {
StringBuilder retVal = new StringBuilder(); StringBuilder retVal = new StringBuilder();
String[] segmentsSource = sourceURI.getPath().split("/", -1); String[] segmentsSource = sourceURI.getPath().split("/", -1);
String[] segmentsTarget = targetURI.getPath().split("/", -1); String[] segmentsTarget = targetURI.getPath().split("/", -1);
@ -283,6 +286,15 @@ public final class PackagingURIHelper {
// If the source is the root, then the relativized // If the source is the root, then the relativized
// form must actually be an absolute URI // form must actually be an absolute URI
if(sourceURI.toString().equals("/")) { if(sourceURI.toString().equals("/")) {
String path = targetURI.getPath();
if(msCompatible && path.charAt(0) == '/') {
try {
targetURI = new URI(path.substring(1));
} catch (Exception e) {
System.err.println(e);
return null;
}
}
return targetURI; return targetURI;
} }
@ -358,6 +370,21 @@ public final class PackagingURIHelper {
} }
} }
/**
* Fully relativize the source part URI against the target part URI.
*
* @param sourceURI
* The source part URI.
* @param targetURI
* The target part URI.
* @return A fully relativize part name URI ('word/media/image1.gif',
* '/word/document.xml' => 'media/image1.gif') else
* <code>null</code>.
*/
public static URI relativizeURI(URI sourceURI, URI targetURI) {
return relativizeURI(sourceURI, targetURI, false);
}
/** /**
* Resolve a source uri against a target. * Resolve a source uri against a target.
* *

View File

@ -163,7 +163,7 @@ public final class ZipPartMarshaller implements PartMarshaller {
} else { } else {
URI targetURI = rel.getTargetURI(); URI targetURI = rel.getTargetURI();
targetValue = PackagingURIHelper.relativizeURI( targetValue = PackagingURIHelper.relativizeURI(
sourcePartURI, targetURI).getPath(); sourcePartURI, targetURI, true).getPath();
if (targetURI.getRawFragment() != null) { if (targetURI.getRawFragment() != null) {
targetValue += "#" + targetURI.getRawFragment(); targetValue += "#" + targetURI.getRawFragment();
} }

View File

@ -30,6 +30,7 @@ import javax.xml.namespace.QName;
import org.apache.poi.POIXMLDocument; import org.apache.poi.POIXMLDocument;
import org.apache.poi.POIXMLDocumentPart; import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.POIXMLException; import org.apache.poi.POIXMLException;
import org.apache.poi.POIXMLProperties;
import org.apache.poi.hssf.record.formula.SheetNameFormatter; import org.apache.poi.hssf.record.formula.SheetNameFormatter;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException; import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.OPCPackage;
@ -228,6 +229,10 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Iterable<X
bv.setActiveTab(0); bv.setActiveTab(0);
workbook.addNewSheets(); workbook.addNewSheets();
//required by Excel 2008 Mac sp2, see Bugzilla #47559
POIXMLProperties.ExtendedProperties expProps = getProperties().getExtendedProperties();
expProps.getUnderlyingProperties().setApplication("Microsoft Excel");
sharedStringSource = (SharedStringsTable)createRelationship(XSSFRelation.SHARED_STRINGS, XSSFFactory.getInstance()); sharedStringSource = (SharedStringsTable)createRelationship(XSSFRelation.SHARED_STRINGS, XSSFFactory.getInstance());
stylesSource = (StylesTable)createRelationship(XSSFRelation.STYLES, XSSFFactory.getInstance()); stylesSource = (StylesTable)createRelationship(XSSFRelation.STYLES, XSSFFactory.getInstance());

View File

@ -23,6 +23,7 @@ import java.util.*;
import org.apache.poi.POIXMLDocument; import org.apache.poi.POIXMLDocument;
import org.apache.poi.POIXMLException; import org.apache.poi.POIXMLException;
import org.apache.poi.POIXMLDocumentPart; import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.POIXMLProperties;
import org.apache.poi.util.PackageHelper; import org.apache.poi.util.PackageHelper;
import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy; import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;
import org.apache.xmlbeans.XmlException; import org.apache.xmlbeans.XmlException;
@ -187,6 +188,9 @@ public class XWPFDocument extends POIXMLDocument {
ctDocument = CTDocument1.Factory.newInstance(); ctDocument = CTDocument1.Factory.newInstance();
ctDocument.addNewBody(); ctDocument.addNewBody();
POIXMLProperties.ExtendedProperties expProps = getProperties().getExtendedProperties();
expProps.getUnderlyingProperties().setApplication("Microsoft Office Word");
} }
/** /**

View File

@ -27,6 +27,7 @@ import java.io.OutputStream;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.net.URI; import java.net.URI;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.Iterator;
import junit.framework.TestCase; import junit.framework.TestCase;
@ -36,11 +37,14 @@ import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.opc.internal.ContentTypeManager; import org.apache.poi.openxml4j.opc.internal.ContentTypeManager;
import org.apache.poi.openxml4j.opc.internal.FileHelper; import org.apache.poi.openxml4j.opc.internal.FileHelper;
import org.apache.poi.util.TempFile; import org.apache.poi.util.TempFile;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.POILogger;
import org.dom4j.Document; import org.dom4j.Document;
import org.dom4j.DocumentHelper; import org.dom4j.DocumentHelper;
import org.dom4j.Element; import org.dom4j.Element;
import org.dom4j.Namespace; import org.dom4j.Namespace;
import org.dom4j.QName; import org.dom4j.QName;
import org.dom4j.io.SAXReader;
public final class TestPackage extends TestCase { public final class TestPackage extends TestCase {
private static Logger logger = Logger.getLogger("org.apache.poi.openxml4j.test"); private static Logger logger = Logger.getLogger("org.apache.poi.openxml4j.test");
@ -195,6 +199,7 @@ public final class TestPackage extends TestCase {
coreRels = pkg.getRelationshipsByType(PackageRelationshipTypes.CORE_DOCUMENT); coreRels = pkg.getRelationshipsByType(PackageRelationshipTypes.CORE_DOCUMENT);
assertEquals(1, coreRels.size()); assertEquals(1, coreRels.size());
coreRel = coreRels.getRelationship(0); coreRel = coreRels.getRelationship(0);
assertEquals("/", coreRel.getSourceURI().toString()); assertEquals("/", coreRel.getSourceURI().toString());
assertEquals("/xl/workbook.xml", coreRel.getTargetURI().toString()); assertEquals("/xl/workbook.xml", coreRel.getTargetURI().toString());
corePart = pkg.getPart(coreRel); corePart = pkg.getPart(coreRel);
@ -205,6 +210,26 @@ public final class TestPackage extends TestCase {
rel = rels.getRelationship(0); rel = rels.getRelationship(0);
assertEquals("Sheet1!A1", rel.getTargetURI().getRawFragment()); assertEquals("Sheet1!A1", rel.getTargetURI().getRawFragment());
assertMSCompatibility(pkg);
}
private void assertMSCompatibility(OPCPackage pkg) throws Exception {
PackagePartName relName = PackagingURIHelper.createPartName(PackageRelationship.getContainerPartRelationship());
PackagePart relPart = pkg.getPart(relName);
SAXReader reader = new SAXReader();
Document xmlRelationshipsDoc = reader
.read(relPart.getInputStream());
Element root = xmlRelationshipsDoc.getRootElement();
for (Iterator i = root
.elementIterator(PackageRelationship.RELATIONSHIP_TAG_NAME); i
.hasNext();) {
Element element = (Element) i.next();
String value = element.attribute(
PackageRelationship.TARGET_ATTRIBUTE_NAME)
.getValue();
assertTrue("Root target must not start with a leadng slash ('/'): " + value, value.charAt(0) != '/');
}
} }

View File

@ -31,8 +31,6 @@ public class TestPackagingURIHelper extends TestCase {
/** /**
* Test relativizePartName() method. * Test relativizePartName() method.
*
* TODO: fix and unable
*/ */
public void testRelativizeURI() throws Exception { public void testRelativizeURI() throws Exception {
URI uri1 = new URI("/word/document.xml"); URI uri1 = new URI("/word/document.xml");
@ -54,22 +52,14 @@ public class TestPackagingURIHelper extends TestCase {
URI retURI2 = PackagingURIHelper.relativizeURI(uri1, uri1); URI retURI2 = PackagingURIHelper.relativizeURI(uri1, uri1);
assertEquals("", retURI2.getPath()); assertEquals("", retURI2.getPath());
// Document and root totally different // relativization against root
URI uri4 = new URI("/"); URI root = new URI("/");
try { uriRes = PackagingURIHelper.relativizeURI(root, uri1);
PackagingURIHelper.relativizeURI(uri1, uri4); assertEquals("/word/document.xml", uriRes.toString());
//TODO: figure oout why the assertion fails
//fail("Must throw an exception ! Can't relativize with an empty URI"); //URI compatible with MS Office and OpenOffice: leading slash is removed
} catch (Exception e) { uriRes = PackagingURIHelper.relativizeURI(root, uri1, true);
// Do nothing assertEquals("word/document.xml", uriRes.toString());
}
try {
PackagingURIHelper.relativizeURI(uri4, uri1);
//TODO: figure oout why the assertion fails
//fail("Must throw an exception ! Can't relativize with an empty URI");
} catch (Exception e) {
// Do nothing
}
} }
/** /**

View File

@ -260,6 +260,8 @@ public final class TestXSSFWorkbook extends BaseTestWorkbook {
XSSFWorkbook workbook = new XSSFWorkbook(); XSSFWorkbook workbook = new XSSFWorkbook();
POIXMLProperties props = workbook.getProperties(); POIXMLProperties props = workbook.getProperties();
assertNotNull(props); assertNotNull(props);
//the Application property must be set for new workbooks, see Bugzilla #47559
assertEquals("Microsoft Excel", props.getExtendedProperties().getUnderlyingProperties().getApplication());
PackagePropertiesPart opcProps = props.getCoreProperties().getUnderlyingProperties(); PackagePropertiesPart opcProps = props.getCoreProperties().getUnderlyingProperties();
assertNotNull(opcProps); assertNotNull(opcProps);
@ -269,6 +271,7 @@ public final class TestXSSFWorkbook extends BaseTestWorkbook {
opcProps.setCreatorProperty("poi-dev@poi.apache.org"); opcProps.setCreatorProperty("poi-dev@poi.apache.org");
workbook = XSSFTestDataSamples.writeOutAndReadBack(workbook); workbook = XSSFTestDataSamples.writeOutAndReadBack(workbook);
assertEquals("Microsoft Excel", workbook.getProperties().getExtendedProperties().getUnderlyingProperties().getApplication());
opcProps = workbook.getProperties().getCoreProperties().getUnderlyingProperties(); opcProps = workbook.getProperties().getCoreProperties().getUnderlyingProperties();
assertEquals("Testing Bugzilla #47460", opcProps.getTitleProperty().getValue()); assertEquals("Testing Bugzilla #47460", opcProps.getTitleProperty().getValue());
assertEquals("poi-dev@poi.apache.org", opcProps.getCreatorProperty().getValue()); assertEquals("poi-dev@poi.apache.org", opcProps.getCreatorProperty().getValue());

View File

@ -21,6 +21,7 @@ import java.io.File;
import junit.framework.TestCase; import junit.framework.TestCase;
import org.apache.poi.POIXMLDocument; import org.apache.poi.POIXMLDocument;
import org.apache.poi.POIXMLProperties;
import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFDocument;
@ -119,4 +120,12 @@ public class TestXWPFDocument extends TestCase {
assertEquals(" ", xml.getProperties().getCoreProperties().getTitle()); assertEquals(" ", xml.getProperties().getCoreProperties().getTitle());
assertEquals(" ", xml.getProperties().getCoreProperties().getUnderlyingProperties().getSubjectProperty().getValue()); assertEquals(" ", xml.getProperties().getCoreProperties().getUnderlyingProperties().getSubjectProperty().getValue());
} }
public void testWorkbookProperties() throws Exception {
XWPFDocument doc = new XWPFDocument();
POIXMLProperties props = doc.getProperties();
assertNotNull(props);
assertEquals("Microsoft Office Word", props.getExtendedProperties().getUnderlyingProperties().getApplication());
}
} }