git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@795587 13f79535-47bb-0310-9956-ffa450edef68tags/REL_3_5-FINAL
@@ -33,7 +33,8 @@ | |||
<changes> | |||
<release version="3.5-beta7" date="2009-??-??"> | |||
<action dev="POI-DEVELOPERS" type="fix">47535 - fixed WordExtractor to tolerate files with empty footnote block</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">47517 - Fixed ExtractorFactory to support .xltx and .dotx files</action> | |||
<action dev="POI-DEVELOPERS" type="add">45556 - Support for extraction of footnotes from docx files</action> | |||
<action dev="POI-DEVELOPERS" type="add">45555 - Support for extraction of endnotes from docx files</action> |
@@ -0,0 +1,75 @@ | |||
/* ==================================================================== | |||
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.xssf.usermodel.examples; | |||
import java.io.FileOutputStream; | |||
import org.apache.poi.xssf.usermodel.XSSFWorkbook; | |||
import org.apache.poi.POIXMLProperties; | |||
/** | |||
* How to set extended and custom properties | |||
* | |||
* @author Yegor Kozlov | |||
*/ | |||
public class WorkbookProperties { | |||
public static void main(String[]args) throws Exception { | |||
XSSFWorkbook workbook = new XSSFWorkbook(); | |||
workbook.createSheet("Workbook Properties"); | |||
POIXMLProperties props = workbook.getProperties(); | |||
/** | |||
* Extended properties are a predefined set of metadata properties | |||
* that are specifically applicable to Office Open XML documents. | |||
* Extended properties consist of 24 simple properties and 3 complex properties stored in the | |||
* part targeted by the relationship of type | |||
*/ | |||
POIXMLProperties.ExtendedProperties ext = props.getExtendedProperties(); | |||
ext.getUnderlyingProperties().setCompany("Apache Software Foundation"); | |||
ext.getUnderlyingProperties().setTemplate("XSSF"); | |||
/** | |||
* Custom properties enable users to define custom metadata properties | |||
* through a set of well-defined data types. For example, a custom | |||
* OLE Editor property of type string can be defined as follows: | |||
* | |||
* <property fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}" pid="2" name="Editor"> | |||
* <vt:lpwstr>John Smith</vt:lpwstr> | |||
* </property> | |||
*/ | |||
POIXMLProperties.CustomProperties cust = props.getCustomProperties(); | |||
org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty | |||
property = cust.getUnderlyingProperties().addNewProperty(); | |||
property.setFmtid("{D5CDD505-2E9C-101B-9397-08002B2CF9AE}"); | |||
property.setPid(2); | |||
property.setName("Editor"); | |||
property.setLpwstr("John Smith"); | |||
FileOutputStream out = new FileOutputStream("workbook.xlsx"); | |||
workbook.write(out); | |||
out.close(); | |||
} | |||
} |
@@ -157,9 +157,13 @@ public abstract class POIXMLDocument extends POIXMLDocumentPart{ | |||
* Get the document properties. This gives you access to the | |||
* core ooxml properties, and the extended ooxml properties. | |||
*/ | |||
public POIXMLProperties getProperties() throws OpenXML4JException, IOException, XmlException { | |||
public POIXMLProperties getProperties() { | |||
if(properties == null) { | |||
properties = new POIXMLProperties(pkg); | |||
try { | |||
properties = new POIXMLProperties(pkg); | |||
} catch (Exception e){ | |||
throw new POIXMLException(e); | |||
} | |||
} | |||
return properties; | |||
} | |||
@@ -197,6 +201,9 @@ public abstract class POIXMLDocument extends POIXMLDocumentPart{ | |||
//force all children to commit their changes into the underlying OOXML Package | |||
onSave(); | |||
//save extended and custom properties | |||
getProperties().commit(); | |||
getPackage().save(stream); | |||
} | |||
@@ -17,12 +17,17 @@ | |||
package org.apache.poi; | |||
import java.io.IOException; | |||
import java.io.OutputStream; | |||
import java.util.Map; | |||
import java.util.HashMap; | |||
import org.apache.poi.openxml4j.exceptions.OpenXML4JException; | |||
import org.apache.poi.openxml4j.opc.OPCPackage; | |||
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection; | |||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; | |||
import org.apache.poi.openxml4j.opc.*; | |||
import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart; | |||
import org.apache.xmlbeans.XmlException; | |||
import org.apache.xmlbeans.XmlOptions; | |||
import org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument; | |||
/** | |||
* Wrapper around the two different kinds of OOXML properties | |||
@@ -33,8 +38,22 @@ public class POIXMLProperties { | |||
private CoreProperties core; | |||
private ExtendedProperties ext; | |||
private CustomProperties cust; | |||
public POIXMLProperties(OPCPackage docPackage) throws IOException, OpenXML4JException, XmlException { | |||
private PackagePart extPart; | |||
private PackagePart custPart; | |||
private static final org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument NEW_EXT_INSTANCE; | |||
private static final org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument NEW_CUST_INSTANCE; | |||
static { | |||
NEW_EXT_INSTANCE = org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument.Factory.newInstance(); | |||
NEW_EXT_INSTANCE.addNewProperties(); | |||
NEW_CUST_INSTANCE = org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument.Factory.newInstance(); | |||
NEW_CUST_INSTANCE.addNewProperties(); | |||
} | |||
public POIXMLProperties(OPCPackage docPackage) throws IOException, OpenXML4JException, XmlException { | |||
this.pkg = docPackage; | |||
// Core properties | |||
@@ -44,24 +63,28 @@ public class POIXMLProperties { | |||
PackageRelationshipCollection extRel = | |||
pkg.getRelationshipsByType(POIXMLDocument.EXTENDED_PROPERTIES_REL_TYPE); | |||
if(extRel.size() == 1) { | |||
org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument props = org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument.Factory.parse( | |||
pkg.getPart( extRel.getRelationship(0) ).getInputStream() | |||
extPart = pkg.getPart( extRel.getRelationship(0)); | |||
org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument props = org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument.Factory.parse( | |||
extPart.getInputStream() | |||
); | |||
ext = new ExtendedProperties(props); | |||
} else { | |||
ext = new ExtendedProperties(org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument.Factory.newInstance()); | |||
} | |||
extPart = null; | |||
ext = new ExtendedProperties((org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument)NEW_EXT_INSTANCE.copy()); | |||
} | |||
// Custom properties | |||
PackageRelationshipCollection custRel = | |||
pkg.getRelationshipsByType(POIXMLDocument.CUSTOM_PROPERTIES_REL_TYPE); | |||
if(custRel.size() == 1) { | |||
org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument props = org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument.Factory.parse( | |||
pkg.getPart( custRel.getRelationship(0) ).getInputStream() | |||
custPart = pkg.getPart( custRel.getRelationship(0)); | |||
org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument props = org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument.Factory.parse( | |||
custPart.getInputStream() | |||
); | |||
cust = new CustomProperties(props); | |||
} else { | |||
cust = new CustomProperties(org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument.Factory.newInstance()); | |||
custPart = null; | |||
cust = new CustomProperties((org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument)NEW_CUST_INSTANCE.copy()); | |||
} | |||
} | |||
@@ -87,11 +110,44 @@ public class POIXMLProperties { | |||
} | |||
/** | |||
* Writes out the ooxml properties into the supplied, | |||
* new Package | |||
* Commit changes to the underlying OPC package | |||
*/ | |||
public void write(OPCPackage pkg) { | |||
// TODO | |||
public void commit() throws IOException{ | |||
if(extPart == null && !NEW_EXT_INSTANCE.toString().equals(ext.props.toString())){ | |||
try { | |||
PackagePartName prtname = PackagingURIHelper.createPartName("/docProps/app.xml"); | |||
pkg.addRelationship(prtname, TargetMode.INTERNAL, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties"); | |||
extPart = pkg.createPart(prtname, "application/vnd.openxmlformats-officedocument.extended-properties+xml"); | |||
} catch (InvalidFormatException e){ | |||
throw new POIXMLException(e); | |||
} | |||
} | |||
if(custPart == null && !NEW_CUST_INSTANCE.toString().equals(cust.props.toString())){ | |||
try { | |||
PackagePartName prtname = PackagingURIHelper.createPartName("/docProps/custom.xml"); | |||
pkg.addRelationship(prtname, TargetMode.INTERNAL, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties"); | |||
custPart = pkg.createPart(prtname, "application/vnd.openxmlformats-officedocument.custom-properties+xml"); | |||
} catch (InvalidFormatException e){ | |||
throw new POIXMLException(e); | |||
} | |||
} | |||
if(extPart != null){ | |||
XmlOptions xmlOptions = new XmlOptions(POIXMLDocumentPart.DEFAULT_XML_OPTIONS); | |||
Map<String, String> map = new HashMap<String, String>(); | |||
map.put("http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes", "vt"); | |||
xmlOptions.setSaveSuggestedPrefixes(map); | |||
OutputStream out = extPart.getOutputStream(); | |||
ext.props.save(out, xmlOptions); | |||
out.close(); | |||
} | |||
if(custPart != null){ | |||
OutputStream out = custPart.getOutputStream(); | |||
cust.props.save(out, POIXMLDocumentPart.DEFAULT_XML_OPTIONS); | |||
out.close(); | |||
} | |||
} | |||
/** | |||
@@ -122,10 +178,6 @@ public class POIXMLProperties { | |||
private org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument props; | |||
private ExtendedProperties(org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument props) { | |||
this.props = props; | |||
if(props.getProperties() == null) { | |||
props.addNewProperties(); | |||
} | |||
} | |||
public org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.CTProperties getUnderlyingProperties() { | |||
@@ -140,10 +192,6 @@ public class POIXMLProperties { | |||
private org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument props; | |||
private CustomProperties(org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument props) { | |||
this.props = props; | |||
if(props.getProperties() == null) { | |||
props.addNewProperties(); | |||
} | |||
} | |||
public org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperties getUnderlyingProperties() { |
@@ -0,0 +1,134 @@ | |||
/* ==================================================================== | |||
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; | |||
import org.apache.poi.xssf.usermodel.XSSFWorkbook; | |||
import org.apache.poi.xssf.XSSFTestDataSamples; | |||
import junit.framework.TestCase; | |||
/** | |||
* Test setting extended and custom OOXML properties | |||
*/ | |||
public class TestPOIXMLProperties extends TestCase { | |||
public void testWorkbookExtendedProperties() throws Exception { | |||
XSSFWorkbook workbook = new XSSFWorkbook(); | |||
POIXMLProperties props = workbook.getProperties(); | |||
assertNotNull(props); | |||
org.apache.poi.POIXMLProperties.ExtendedProperties properties = | |||
props.getExtendedProperties(); | |||
org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.CTProperties | |||
ctProps = properties.getUnderlyingProperties(); | |||
String appVersion = "3.5 beta"; | |||
String application = "POI"; | |||
ctProps.setApplication(application); | |||
ctProps.setAppVersion(appVersion); | |||
ctProps = null; | |||
properties = null; | |||
props = null; | |||
XSSFWorkbook newWorkbook = | |||
XSSFTestDataSamples.writeOutAndReadBack(workbook); | |||
assertTrue(workbook != newWorkbook); | |||
POIXMLProperties newProps = newWorkbook.getProperties(); | |||
assertNotNull(newProps); | |||
org.apache.poi.POIXMLProperties.ExtendedProperties newProperties = | |||
newProps.getExtendedProperties(); | |||
org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.CTProperties | |||
newCtProps = newProperties.getUnderlyingProperties(); | |||
assertEquals(application, newCtProps.getApplication()); | |||
assertEquals(appVersion, newCtProps.getAppVersion()); | |||
} | |||
public void testWorkbookCustomProperties() throws Exception { | |||
XSSFWorkbook workbook = new XSSFWorkbook(); | |||
POIXMLProperties props = workbook.getProperties(); | |||
assertNotNull(props); | |||
org.apache.poi.POIXMLProperties.CustomProperties properties = | |||
props.getCustomProperties(); | |||
org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperties | |||
ctProps = properties.getUnderlyingProperties(); | |||
org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty | |||
property = ctProps.addNewProperty(); | |||
String fmtid = | |||
"{A1A1A1A1A1A1A1A1-A1A1A1A1-A1A1A1A1-A1A1A1A1-A1A1A1A1A1A1A1A1}"; | |||
int pId = 1; | |||
String name = "testProperty"; | |||
String stringValue = "testValue"; | |||
property.setFmtid(fmtid); | |||
property.setPid(pId); | |||
property.setName(name); | |||
property.setBstr(stringValue); | |||
property = null; | |||
ctProps = null; | |||
properties = null; | |||
props = null; | |||
XSSFWorkbook newWorkbook = | |||
XSSFTestDataSamples.writeOutAndReadBack(workbook); | |||
assertTrue(workbook != newWorkbook); | |||
POIXMLProperties newProps = newWorkbook.getProperties(); | |||
assertNotNull(newProps); | |||
org.apache.poi.POIXMLProperties.CustomProperties newProperties = | |||
newProps.getCustomProperties(); | |||
org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperties | |||
newCtProps = newProperties.getUnderlyingProperties(); | |||
assertEquals(1, newCtProps.getPropertyArray().length); | |||
org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty | |||
newpProperty = newCtProps.getPropertyArray()[0]; | |||
assertEquals(fmtid, newpProperty.getFmtid()); | |||
assertEquals(pId, newpProperty.getPid()); | |||
assertEquals(name, newpProperty.getName()); | |||
assertEquals(stringValue, newpProperty.getBstr()); | |||
} | |||
} |