2008-02-04 16:34:44 +00:00
/ * = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
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 ;
2008-09-30 13:57:36 +00:00
import java.io.* ;
2008-05-23 15:05:12 +00:00
import java.util.LinkedList ;
import java.util.List ;
2008-02-04 16:34:44 +00:00
2008-03-08 17:21:29 +00:00
import org.apache.poi.poifs.common.POIFSConstants ;
import org.apache.poi.util.IOUtils ;
2008-03-09 14:21:34 +00:00
import org.apache.xmlbeans.XmlException ;
2008-02-04 16:34:44 +00:00
import org.openxml4j.exceptions.InvalidFormatException ;
import org.openxml4j.exceptions.OpenXML4JException ;
2008-09-30 13:57:36 +00:00
import org.openxml4j.opc.* ;
2008-02-04 16:34:44 +00:00
import org.openxml4j.opc.Package ;
2008-09-30 13:57:36 +00:00
public class POIXMLDocument extends POIXMLDocumentPart {
2008-02-04 16:34:44 +00:00
public static final String CORE_PROPERTIES_REL_TYPE = " http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties " ;
public static final String EXTENDED_PROPERTIES_REL_TYPE = " http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties " ;
2008-08-12 20:58:31 +00:00
public static final String CUSTOM_PROPERTIES_REL_TYPE = " http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties " ;
2008-09-30 13:57:36 +00:00
2008-05-28 13:32:03 +00:00
// OLE embeddings relation name
2008-05-23 15:05:12 +00:00
public static final String OLE_OBJECT_REL_TYPE = " http://schemas.openxmlformats.org/officeDocument/2006/relationships/oleObject " ;
2008-09-30 13:57:36 +00:00
2008-05-28 13:32:03 +00:00
// Embedded OPC documents relation name
public static final String PACK_OBJECT_REL_TYPE = " http://schemas.openxmlformats.org/officeDocument/2006/relationships/package " ;
2008-09-30 13:57:36 +00:00
2008-02-04 16:34:44 +00:00
/** The OPC Package */
private Package pkg ;
/** The OPC core Package Part */
private PackagePart corePart ;
2008-09-30 13:57:36 +00:00
2008-04-09 12:22:23 +00:00
/ * *
* The properties of the OPC package , opened as needed
* /
private POIXMLProperties properties ;
2008-09-30 13:57:36 +00:00
/ * *
* The embedded OLE2 files in the OPC package
* /
protected List < PackagePart > embedds ;
protected POIXMLDocument ( ) {
super ( null , null ) ;
embedds = new LinkedList < PackagePart > ( ) ;
}
2008-03-08 17:39:56 +00:00
protected POIXMLDocument ( Package pkg ) throws IOException {
2008-09-30 13:57:36 +00:00
this ( ) ;
initialize ( pkg ) ;
2008-03-08 17:39:56 +00:00
}
2008-09-30 13:57:36 +00:00
2008-02-04 16:34:44 +00:00
protected POIXMLDocument ( String path ) throws IOException {
2008-09-30 13:57:36 +00:00
this ( openPackage ( path ) ) ;
2008-03-08 17:39:56 +00:00
}
2008-09-30 13:57:36 +00:00
2008-03-08 17:39:56 +00:00
/ * *
* Wrapper to open a package , returning an IOException
* in the event of a problem .
* Works around shortcomings in java ' s this ( ) constructor calls
* /
2008-03-09 14:21:34 +00:00
public static Package openPackage ( String path ) throws IOException {
2008-02-04 16:34:44 +00:00
try {
2008-03-08 17:39:56 +00:00
return Package . open ( path ) ;
2008-02-04 16:34:44 +00:00
} catch ( InvalidFormatException e ) {
throw new IOException ( e . toString ( ) ) ;
}
}
2008-09-30 13:57:36 +00:00
protected void initialize ( Package pkg ) throws IOException {
2008-09-18 07:42:40 +00:00
try {
2008-09-30 13:57:36 +00:00
this . pkg = pkg ;
PackageRelationship coreDocRelationship = this . pkg . getRelationshipsByType (
PackageRelationshipTypes . CORE_DOCUMENT ) . getRelationship ( 0 ) ;
// Get core part
this . corePart = super . packagePart = this . pkg . getPart ( coreDocRelationship ) ;
// Verify it's there
if ( corePart = = null ) {
throw new IllegalArgumentException ( " No core part found for this document! Nothing with " + coreDocRelationship . getRelationshipType ( ) + " present as a relation. " ) ;
}
} catch ( OpenXML4JException e ) {
2008-09-18 07:42:40 +00:00
throw new IOException ( e . toString ( ) ) ;
}
}
2008-09-30 13:57:36 +00:00
public Package getPackage ( ) {
2008-02-04 16:34:44 +00:00
return this . pkg ;
}
2008-09-30 13:57:36 +00:00
2008-02-04 16:34:44 +00:00
protected PackagePart getCorePart ( ) {
return this . corePart ;
}
2008-02-13 13:43:42 +00:00
2008-02-19 17:34:39 +00:00
/ * *
* Get the PackagePart that is the target of a relationship .
2008-09-30 13:57:36 +00:00
*
2008-02-19 17:34:39 +00:00
* @param rel The relationship
* @return The target part
* @throws InvalidFormatException
* /
protected PackagePart getTargetPart ( PackageRelationship rel ) throws InvalidFormatException {
2008-07-29 23:03:25 +00:00
return getTargetPart ( getPackage ( ) , rel ) ;
}
/ * *
* Get the PackagePart that is the target of a relationship .
2008-09-30 13:57:36 +00:00
*
2008-07-29 23:03:25 +00:00
* @param rel The relationship
* @param pkg The package to fetch from
* @return The target part
* @throws InvalidFormatException
* /
public static PackagePart getTargetPart ( Package pkg , PackageRelationship rel ) throws InvalidFormatException {
2008-02-13 13:43:42 +00:00
PackagePartName relName = PackagingURIHelper . createPartName ( rel . getTargetURI ( ) ) ;
2008-07-29 23:03:25 +00:00
PackagePart part = pkg . getPart ( relName ) ;
2008-02-13 13:43:42 +00:00
if ( part = = null ) {
throw new IllegalArgumentException ( " No part found for relationship " + rel ) ;
}
return part ;
}
2008-03-09 14:21:34 +00:00
2008-09-30 13:57:36 +00:00
/ * *
* Fetches the ( single ) PackagePart which is defined as
* the supplied relation content type of the base
* package / container , or null if none found .
* @param relationType The relation content type to search for
* @throws IllegalArgumentException If we find more than one part of that type
* /
protected PackagePart getSinglePartByRelationType ( String relationType ) throws IllegalArgumentException , OpenXML4JException {
PackageRelationshipCollection rels =
pkg . getRelationshipsByType ( relationType ) ;
if ( rels . size ( ) = = 0 ) {
return null ;
}
if ( rels . size ( ) > 1 ) {
throw new IllegalArgumentException ( " Found " + rels . size ( ) + " relations for the type " + relationType + " , should only ever be one! " ) ;
}
PackageRelationship rel = rels . getRelationship ( 0 ) ;
return getTargetPart ( rel ) ;
}
/ * *
* Retrieves all the PackageParts which are defined as
* relationships of the base document with the
* specified content type .
* /
protected PackagePart [ ] getRelatedByType ( String contentType ) throws InvalidFormatException {
PackageRelationshipCollection partsC =
getCorePart ( ) . getRelationshipsByType ( contentType ) ;
PackagePart [ ] parts = new PackagePart [ partsC . size ( ) ] ;
int count = 0 ;
for ( PackageRelationship rel : partsC ) {
parts [ count ] = getTargetPart ( rel ) ;
count + + ;
}
return parts ;
}
2008-03-08 17:13:30 +00:00
/ * *
* Checks that the supplied InputStream ( which MUST
2008-09-30 13:57:36 +00:00
* support mark and reset , or be a PushbackInputStream )
2008-03-08 17:13:30 +00:00
* has a OOXML ( zip ) header at the start of it .
* If your InputStream does not support mark / reset ,
* then wrap it in a PushBackInputStream , then be
* sure to always use that , and not the original !
2008-09-30 13:57:36 +00:00
* @param inp An InputStream which supports either mark / reset , or is a PushbackInputStream
2008-03-08 17:13:30 +00:00
* /
public static boolean hasOOXMLHeader ( InputStream inp ) throws IOException {
2008-09-30 13:57:36 +00:00
// We want to peek at the first 4 bytes
inp . mark ( 4 ) ;
2008-03-08 17:13:30 +00:00
2008-09-30 13:57:36 +00:00
byte [ ] header = new byte [ 4 ] ;
IOUtils . readFully ( inp , header ) ;
2008-03-08 17:13:30 +00:00
// Wind back those 4 bytes
if ( inp instanceof PushbackInputStream ) {
2008-09-30 13:57:36 +00:00
PushbackInputStream pin = ( PushbackInputStream ) inp ;
pin . unread ( header ) ;
2008-03-08 17:13:30 +00:00
} else {
2008-09-30 13:57:36 +00:00
inp . reset ( ) ;
2008-03-08 17:13:30 +00:00
}
2008-09-30 13:57:36 +00:00
// Did it match the ooxml zip signature?
2008-03-08 17:13:30 +00:00
return (
2008-09-30 13:57:36 +00:00
header [ 0 ] = = POIFSConstants . OOXML_FILE_HEADER [ 0 ] & &
header [ 1 ] = = POIFSConstants . OOXML_FILE_HEADER [ 1 ] & &
header [ 2 ] = = POIFSConstants . OOXML_FILE_HEADER [ 2 ] & &
header [ 3 ] = = POIFSConstants . OOXML_FILE_HEADER [ 3 ]
) ;
}
/ * *
* 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 {
if ( properties = = null ) {
properties = new POIXMLProperties ( pkg ) ;
}
return properties ;
2008-03-08 17:13:30 +00:00
}
2008-03-09 14:21:34 +00:00
2008-05-23 15:05:12 +00:00
/ * *
* Get the document ' s embedded files .
* /
public List < PackagePart > getAllEmbedds ( ) throws OpenXML4JException
{
return embedds ;
}
2008-02-04 16:34:44 +00:00
}