1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ooxmldocpropimport.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #include <com/sun/star/embed/XStorage.hpp>
32 #include <com/sun/star/embed/XHierarchicalStorageAccess.hpp>
33 #include <com/sun/star/embed/XRelationshipAccess.hpp>
34 #include <com/sun/star/embed/ElementModes.hpp>
35 #include <com/sun/star/xml/sax/XFastParser.hpp>
36 #include <com/sun/star/xml/sax/XFastTokenHandler.hpp>
37 #include <com/sun/star/xml/sax/XFastDocumentHandler.hpp>
39 #include <cppuhelper/factory.hxx>
40 #include <cppuhelper/implementationentry.hxx>
42 #include <oox/core/namespaces.hxx>
43 #include "docprophandler.hxx"
44 #include "ooxmldocpropimport.hxx"
46 using namespace ::com::sun::star
;
51 // -----------------------------------------------------------
52 ::rtl::OUString SAL_CALL
OOXMLDocPropImportImpl_getImplementationName()
54 return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
55 "com.sun.star.comp.oox.docprop.OOXMLDocumentPropertiesImporter"));
58 // -----------------------------------------------------------
59 uno::Sequence
< ::rtl::OUString
> SAL_CALL
OOXMLDocPropImportImpl_getSupportedServiceNames()
61 uno::Sequence
< ::rtl::OUString
> s(1);
62 s
[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
63 "com.sun.star.document.OOXMLDocumentPropertiesImporter"));
67 // -----------------------------------------------------------
68 uno::Reference
< uno::XInterface
> SAL_CALL
OOXMLDocPropImportImpl_createInstance(
69 const uno::Reference
< uno::XComponentContext
> & context
)
70 SAL_THROW((uno::Exception
))
72 return static_cast< ::cppu::OWeakObject
* >(new OOXMLDocPropImportImpl(context
));
76 // -----------------------------------------------------------
77 OOXMLDocPropImportImpl::OOXMLDocPropImportImpl(uno::Reference
< uno::XComponentContext
> const & xContext
) :
78 m_xContext( xContext
)
81 // -----------------------------------------------------------
82 uno::Sequence
< xml::sax::InputSource
> OOXMLDocPropImportImpl::GetRelatedStreams( const uno::Reference
< embed::XStorage
> xStorage
, const ::rtl::OUString
& aStreamType
)
85 throw uno::RuntimeException();
87 uno::Reference
< embed::XRelationshipAccess
> xRelation( xStorage
, uno::UNO_QUERY_THROW
);
88 uno::Reference
< embed::XHierarchicalStorageAccess
> xHierarchy( xStorage
, uno::UNO_QUERY_THROW
);
90 uno::Sequence
< uno::Sequence
< beans::StringPair
> > aPropsInfo
= xRelation
->getRelationshipsByType( aStreamType
);
92 sal_Int32 nLength
= 0;
93 uno::Sequence
< xml::sax::InputSource
> aResult( aPropsInfo
.getLength() );
94 if ( aPropsInfo
.getLength() )
96 for ( sal_Int32 nInd
= 0; nInd
< aPropsInfo
.getLength(); nInd
++ )
97 for ( sal_Int32 nEntryInd
= 0; nEntryInd
< aPropsInfo
[nInd
].getLength(); nEntryInd
++ )
98 if ( aPropsInfo
[nInd
][nEntryInd
].First
.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Target" ) ) ) )
100 uno::Reference
< embed::XExtendedStorageStream
> xExtStream
= xHierarchy
->openStreamElementByHierarchicalName( aPropsInfo
[nInd
][nEntryInd
].Second
, embed::ElementModes::READ
);
101 if ( !xExtStream
.is() )
102 throw uno::RuntimeException();
104 aResult
[nLength
].sSystemId
= aPropsInfo
[nInd
][nEntryInd
].Second
;
105 aResult
[nLength
++].aInputStream
= xExtStream
->getInputStream();
109 aResult
.realloc( nLength
);
115 // com.sun.star.uno.XServiceInfo:
116 // -----------------------------------------------------------
117 ::rtl::OUString SAL_CALL
OOXMLDocPropImportImpl::getImplementationName() throw (uno::RuntimeException
)
119 return OOXMLDocPropImportImpl_getImplementationName();
122 // -----------------------------------------------------------
123 ::sal_Bool SAL_CALL
OOXMLDocPropImportImpl::supportsService(::rtl::OUString
const & serviceName
) throw (uno::RuntimeException
)
125 uno::Sequence
< ::rtl::OUString
> serviceNames
= OOXMLDocPropImportImpl_getSupportedServiceNames();
126 for (::sal_Int32 i
= 0; i
< serviceNames
.getLength(); ++i
)
128 if (serviceNames
[i
] == serviceName
)
135 // -----------------------------------------------------------
136 uno::Sequence
< ::rtl::OUString
> SAL_CALL
OOXMLDocPropImportImpl::getSupportedServiceNames() throw (uno::RuntimeException
)
138 return OOXMLDocPropImportImpl_getSupportedServiceNames();
141 // -----------------------------------------------------------
142 // ::com::sun::star::document::XOOXMLDocumentPropertiesImporter:
143 void SAL_CALL
OOXMLDocPropImportImpl::importProperties(const uno::Reference
< embed::XStorage
> & xSource
, const uno::Reference
< document::XDocumentProperties
> & xDocumentProperties
) throw (uno::RuntimeException
, lang::IllegalArgumentException
, xml::sax::SAXException
, uno::Exception
)
145 // TODO: Insert your implementation for "importProperties" here.
146 if ( !m_xContext
.is() )
147 throw uno::RuntimeException();
149 if ( !xSource
.is() || !xDocumentProperties
.is() )
150 throw lang::IllegalArgumentException();
152 // the MS Office seems to have a bug, so we have to do similar handling
153 ::rtl::OUString
aCoreType( RTL_CONSTASCII_USTRINGPARAM( "http://schemas.openxmlformats.org/officedocument/2006/relationships/metadata/core-properties" ) );
154 ::rtl::OUString
aCoreWorkaroundType( RTL_CONSTASCII_USTRINGPARAM( "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" ) );
156 ::rtl::OUString
aExtType( RTL_CONSTASCII_USTRINGPARAM( "http://schemas.openxmlformats.org/officedocument/2006/relationships/extended-properties" ) );
157 ::rtl::OUString
aCustomType( RTL_CONSTASCII_USTRINGPARAM( "http://schemas.openxmlformats.org/officedocument/2006/relationships/custom-properties" ) );
159 uno::Sequence
< xml::sax::InputSource
> aCoreStreams
= GetRelatedStreams( xSource
, aCoreType
);
160 if ( !aCoreStreams
.getLength() )
161 aCoreStreams
= GetRelatedStreams( xSource
, aCoreWorkaroundType
);
163 uno::Sequence
< xml::sax::InputSource
> aExtStreams
= GetRelatedStreams( xSource
, aExtType
);
164 uno::Sequence
< xml::sax::InputSource
> aCustomStreams
= GetRelatedStreams( xSource
, aCustomType
);
166 if ( aCoreStreams
.getLength() || aExtStreams
.getLength() || aCustomStreams
.getLength() )
168 if ( aCoreStreams
.getLength() > 1 )
169 throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unexpected core properties stream!" ) ), uno::Reference
< uno::XInterface
>() );
171 uno::Reference
< lang::XMultiComponentFactory
> xFactory( m_xContext
->getServiceManager(), uno::UNO_QUERY_THROW
);
173 uno::Reference
< xml::sax::XFastParser
> xParser(
174 xFactory
->createInstanceWithContext(
175 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.xml.sax.FastParser" ) ),
177 uno::UNO_QUERY_THROW
);
179 uno::Reference
< xml::sax::XFastTokenHandler
> xTokenHandler(
180 xFactory
->createInstanceWithContext(
181 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.oox.FastTokenHandlerService" ) ),
183 uno::UNO_QUERY_THROW
);
185 uno::Reference
< xml::sax::XFastDocumentHandler
> xDocHandler( static_cast< xml::sax::XFastDocumentHandler
* >( new OOXMLDocPropHandler( m_xContext
, xDocumentProperties
) ) );
187 xParser
->setFastDocumentHandler( xDocHandler
);
188 xParser
->setTokenHandler( xTokenHandler
);
190 xParser
->registerNamespace( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "http://schemas.openxmlformats.org/package/2006/metadata/core-properties" ) ), NMSP_COREPR
);
191 xParser
->registerNamespace( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "http://purl.org/dc/elements/1.1/" ) ), NMSP_DC
);
192 xParser
->registerNamespace( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "http://purl.org/dc/terms/" ) ), NMSP_DCTERMS
);
193 xParser
->registerNamespace( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties" ) ), NMSP_EXTPR
);
194 xParser
->registerNamespace( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "http://schemas.openxmlformats.org/officeDocument/2006/custom-properties" ) ), NMSP_CUSTPR
);
195 xParser
->registerNamespace( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes" ) ), NMSP_VT
);
197 // #158414# XFastParser::parseStream() throws on invalid XML
198 if ( aCoreStreams
.getLength() ) try
200 if ( aCoreStreams
[0].aInputStream
.is() )
202 xParser
->parseStream( aCoreStreams
[0] );
203 aCoreStreams
[0].aInputStream
->closeInput();
206 catch( uno::Exception
& )
211 for ( nInd
= 0; nInd
< aExtStreams
.getLength(); nInd
++ )
213 xParser
->parseStream( aExtStreams
[nInd
] );
214 if ( aExtStreams
[nInd
].aInputStream
.is() )
215 aExtStreams
[nInd
].aInputStream
->closeInput();
218 for ( nInd
= 0; nInd
< aCustomStreams
.getLength(); nInd
++ )
220 xParser
->parseStream( aCustomStreams
[nInd
] );
221 if ( aCustomStreams
[nInd
].aInputStream
.is() )
222 aCustomStreams
[nInd
].aInputStream
->closeInput();
227 } // namespace docprop