1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
21 #include <sal/log.hxx>
23 #include <vcl/errinf.hxx>
24 #include <com/sun/star/frame/XModel.hpp>
25 #include <com/sun/star/uri/UriReferenceFactory.hpp>
26 #include <com/sun/star/util/MeasureUnit.hpp>
27 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
28 #include <com/sun/star/packages/WrongPasswordException.hpp>
29 #include <com/sun/star/packages/zip/ZipIOException.hpp>
30 #include <com/sun/star/embed/ElementModes.hpp>
31 #include <com/sun/star/sdb/XOfficeDatabaseDocument.hpp>
32 #include "xmlfilter.hxx"
33 #include <vcl/svapp.hxx>
34 #include <vcl/window.hxx>
35 #include <xmloff/xmlnamespace.hxx>
36 #include <xmloff/xmlscripti.hxx>
37 #include <xmloff/xmltoken.hxx>
38 #include <xmloff/namespacemap.hxx>
39 #include <com/sun/star/xml/sax/InputSource.hpp>
40 #include <com/sun/star/xml/sax/SAXParseException.hpp>
41 #include <xmloff/ProgressBarHelper.hxx>
42 #include <sfx2/docfile.hxx>
43 #include <com/sun/star/io/XInputStream.hpp>
44 #include "xmlDatabase.hxx"
45 #include "xmlEnums.hxx"
46 #include <strings.hxx>
47 #include <xmloff/DocumentSettingsContext.hxx>
48 #include "xmlStyleImport.hxx"
49 #include <xmloff/xmluconv.hxx>
50 #include "xmlHelper.hxx"
51 #include <com/sun/star/util/XModifiable.hpp>
52 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
53 #include <svtools/sfxecode.hxx>
54 #include <comphelper/diagnose_ex.hxx>
55 #include <osl/diagnose.h>
56 #include <comphelper/sequence.hxx>
57 #include <comphelper/types.hxx>
58 #include <comphelper/namedvaluecollection.hxx>
59 #include <cppuhelper/exc_hlp.hxx>
60 #include <connectivity/DriversConfig.hxx>
61 #include <rtl/uri.hxx>
63 using namespace ::com::sun::star
;
65 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
66 com_sun_star_comp_sdb_DBFilter_get_implementation(
67 css::uno::XComponentContext
* context
, css::uno::Sequence
<css::uno::Any
> const&)
69 return cppu::acquire(new ::dbaxml::ODBFilter(context
));
75 using namespace ::com::sun::star::util
;
76 /// read a component (file + filter version)
77 static ErrCode
ReadThroughComponent(
78 const uno::Reference
<XInputStream
>& xInputStream
,
79 const uno::Reference
<XComponent
>& xModelComponent
,
80 const uno::Reference
<XComponentContext
> & rxContext
,
83 OSL_ENSURE(xInputStream
.is(), "input stream missing");
84 OSL_ENSURE(xModelComponent
.is(), "document missing");
85 OSL_ENSURE(rxContext
.is(), "factory missing");
87 // prepare ParserInputSource
88 InputSource aParserInput
;
89 aParserInput
.aInputStream
= xInputStream
;
91 // connect model and filter
92 _rFilter
.setTargetDocument( xModelComponent
);
94 // finally, parser the stream
97 _rFilter
.parseStream( aParserInput
);
99 catch (const SAXParseException
&)
101 #if OSL_DEBUG_LEVEL > 0
102 TOOLS_WARN_EXCEPTION("dbaccess", "SAX parse exception caught while importing");
106 catch (const SAXException
&)
110 catch (const packages::zip::ZipIOException
&)
112 return ERRCODE_IO_BROKENPACKAGE
;
114 catch (const Exception
&)
116 DBG_UNHANDLED_EXCEPTION("dbaccess");
124 /// read a component (storage version)
125 static ErrCode
ReadThroughComponent(
126 const uno::Reference
< embed::XStorage
>& xStorage
,
127 const uno::Reference
<XComponent
>& xModelComponent
,
128 const char* pStreamName
,
129 const uno::Reference
<XComponentContext
> & rxContext
,
132 OSL_ENSURE( xStorage
.is(), "Need storage!");
133 OSL_ENSURE(nullptr != pStreamName
, "Please, please, give me a name!");
136 // TODO/LATER: better error handling
139 uno::Reference
< io::XStream
> xDocStream
;
143 // open stream (and set parser input)
144 OUString sStreamName
= OUString::createFromAscii(pStreamName
);
145 if ( !xStorage
->hasByName( sStreamName
) || !xStorage
->isStreamElement( sStreamName
) )
147 // stream name not found! return immediately with OK signal
152 xDocStream
= xStorage
->openStreamElement( sStreamName
, embed::ElementModes::READ
);
154 catch (const packages::WrongPasswordException
&)
156 return ERRCODE_SFX_WRONGPASSWORD
;
158 catch (const uno::Exception
&)
160 return ErrCode(1); // TODO/LATER: error handling
163 uno::Reference
< XInputStream
> xInputStream
= xDocStream
->getInputStream();
164 // read from the stream
165 return ReadThroughComponent( xInputStream
172 ODBFilter::ODBFilter( const uno::Reference
< XComponentContext
>& _rxContext
)
173 : SvXMLImport(_rxContext
, getImplementationName_Static())
174 , m_bNewFormat(false)
177 GetMM100UnitConverter().SetCoreMeasureUnit(util::MeasureUnit::MM_10TH
);
178 GetMM100UnitConverter().SetXMLMeasureUnit(util::MeasureUnit::CM
);
179 GetNamespaceMap().Add( "_db",
180 GetXMLToken(XML_N_DB
),
183 GetNamespaceMap().Add( "__db",
184 GetXMLToken(XML_N_DB_OASIS
),
189 ODBFilter::~ODBFilter() noexcept
195 OUString
ODBFilter::getImplementationName_Static()
197 return "com.sun.star.comp.sdb.DBFilter";
202 class FocusWindowWaitGuard
205 FocusWindowWaitGuard()
207 SolarMutexGuard aGuard
;
208 mpWindow
.set(Application::GetFocusWindow());
210 mpWindow
->EnterWait();
212 ~FocusWindowWaitGuard()
216 SolarMutexGuard aGuard
;
217 mpWindow
->LeaveWait();
221 VclPtr
<vcl::Window
> mpWindow
;
225 sal_Bool SAL_CALL
ODBFilter::filter( const Sequence
< PropertyValue
>& rDescriptor
)
227 FocusWindowWaitGuard aWindowFocusGuard
;
230 if ( GetModel().is() )
231 bRet
= implImport( rDescriptor
);
237 bool ODBFilter::implImport( const Sequence
< PropertyValue
>& rDescriptor
)
240 ::comphelper::NamedValueCollection
aMediaDescriptor( rDescriptor
);
242 uno::Reference
<embed::XStorage
> xStorage
= GetSourceStorage();
247 if (aMediaDescriptor
.has("URL"))
248 sFileName
= aMediaDescriptor
.getOrDefault("URL", OUString());
249 if (sFileName
.isEmpty() && aMediaDescriptor
.has("FileName"))
250 sFileName
= aMediaDescriptor
.getOrDefault("FileName", sFileName
);
252 OSL_ENSURE(!sFileName
.isEmpty(), "ODBFilter::implImport: no URL given!");
253 bRet
= !sFileName
.isEmpty();
259 tools::SvRef
<SfxMedium
> pMedium
;
262 OUString sStreamRelPath
;
263 if (sFileName
.startsWithIgnoreAsciiCase("vnd.sun.star.pkg:"))
265 // In this case the authority contains the real path, and the path is the embedded stream name.
266 auto const uri
= css::uri::UriReferenceFactory::create(GetComponentContext())
268 if (uri
.is() && uri
->isAbsolute()
269 && uri
->hasAuthority() && !uri
->hasQuery() && !uri
->hasFragment())
271 auto const auth
= uri
->getAuthority();
272 auto const decAuth
= rtl::Uri::decode(
273 auth
, rtl_UriDecodeStrict
, RTL_TEXTENCODING_UTF8
);
274 auto path
= uri
->getPath();
275 if (!path
.isEmpty()) {
276 assert(path
[0] == '/');
279 auto const decPath
= rtl::Uri::decode(
280 path
, rtl_UriDecodeStrict
, RTL_TEXTENCODING_UTF8
);
281 //TODO: really decode path?
282 if (auth
.isEmpty() == decAuth
.isEmpty() && path
.isEmpty() == decPath
.isEmpty())
284 // Decoding of auth and path to UTF-8 succeeded:
286 sStreamRelPath
= decPath
;
290 "<" << sFileName
<< "> cannot be parse as vnd.sun.star.pkg URL");
295 "<" << sFileName
<< "> cannot be parse as vnd.sun.star.pkg URL");
299 pMedium
= new SfxMedium(sFileName
, (StreamMode::READ
| StreamMode::NOCREATE
));
302 xStorage
.set(pMedium
->GetStorage(false), UNO_SET_THROW
);
304 if (!sStreamRelPath
.isEmpty())
305 xStorage
= xStorage
->openStorageElement(sStreamRelPath
, embed::ElementModes::READ
);
307 catch (const RuntimeException
&)
311 catch (const Exception
&)
313 Any aError
= ::cppu::getCaughtException();
314 throw lang::WrappedTargetRuntimeException(OUString(), *this, aError
);
318 uno::Reference
<sdb::XOfficeDatabaseDocument
> xOfficeDoc(GetModel(),UNO_QUERY_THROW
);
319 m_xDataSource
.set(xOfficeDoc
->getDataSource(),UNO_QUERY_THROW
);
320 uno::Reference
< XNumberFormatsSupplier
> xNum(m_xDataSource
->getPropertyValue(PROPERTY_NUMBERFORMATSSUPPLIER
),UNO_QUERY
);
321 SetNumberFormatsSupplier(xNum
);
323 uno::Reference
<XComponent
> xModel(GetModel());
324 ErrCode nRet
= ReadThroughComponent( xStorage
327 ,GetComponentContext()
331 if ( nRet
== ERRCODE_NONE
)
332 nRet
= ReadThroughComponent( xStorage
335 ,GetComponentContext()
339 bRet
= nRet
== ERRCODE_NONE
;
343 uno::Reference
< XModifiable
> xModi(GetModel(),UNO_QUERY
);
345 xModi
->setModified(false);
349 if ( nRet
== ERRCODE_IO_BROKENPACKAGE
)
350 ;// TODO/LATER: no way to transport the error outside from the filter!
353 // TODO/LATER: this is completely wrong! Filter code should never call ErrorHandler directly! But for now this is the only way!
354 ErrorHandler::HandleError( nRet
);
355 if( nRet
.IsWarning() )
366 class DBXMLDocumentSettingsContext
: public SvXMLImportContext
369 DBXMLDocumentSettingsContext(SvXMLImport
& rImport
)
370 : SvXMLImportContext(rImport
)
374 virtual uno::Reference
< xml::sax::XFastContextHandler
> SAL_CALL
createFastChildContext(
375 sal_Int32 nElement
, const uno::Reference
< xml::sax::XFastAttributeList
>& /*xAttrList*/ ) override
377 if (nElement
== XML_ELEMENT(OFFICE
, XML_SETTINGS
))
379 return new XMLDocumentSettingsContext(GetImport());
385 class DBXMLDocumentStylesContext
: public SvXMLImportContext
388 DBXMLDocumentStylesContext(SvXMLImport
& rImport
)
389 : SvXMLImportContext(rImport
)
393 virtual uno::Reference
< xml::sax::XFastContextHandler
> SAL_CALL
createFastChildContext(
394 sal_Int32 nElement
, const uno::Reference
< xml::sax::XFastAttributeList
>& /*xAttrList*/ ) override
396 ODBFilter
& rImport(static_cast<ODBFilter
&>(GetImport()));
399 case XML_ELEMENT(OFFICE
, XML_STYLES
):
400 case XML_ELEMENT(OOO
, XML_STYLES
):
401 rImport
.GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP
);
402 return rImport
.CreateStylesContext(false);
403 case XML_ELEMENT(OFFICE
, XML_AUTOMATIC_STYLES
):
404 case XML_ELEMENT(OOO
, XML_AUTOMATIC_STYLES
):
405 rImport
.GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP
);
406 return rImport
.CreateStylesContext(true);
412 class DBXMLDocumentBodyContext
: public SvXMLImportContext
415 DBXMLDocumentBodyContext(SvXMLImport
& rImport
)
416 : SvXMLImportContext(rImport
)
420 virtual uno::Reference
< xml::sax::XFastContextHandler
> SAL_CALL
createFastChildContext(
421 sal_Int32 nElement
, const uno::Reference
< xml::sax::XFastAttributeList
>& /*xAttrList*/ ) override
423 ODBFilter
& rImport(static_cast<ODBFilter
&>(GetImport()));
426 case XML_ELEMENT(OFFICE
, XML_DATABASE
):
427 case XML_ELEMENT(OOO
, XML_DATABASE
):
428 rImport
.GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP
);
429 return new OXMLDatabase(rImport
);
436 class DBXMLDocumentContentContext
: public SvXMLImportContext
439 DBXMLDocumentContentContext(SvXMLImport
& rImport
)
440 : SvXMLImportContext(rImport
)
444 virtual uno::Reference
< xml::sax::XFastContextHandler
> SAL_CALL
createFastChildContext(
445 sal_Int32 nElement
, const uno::Reference
< xml::sax::XFastAttributeList
>& /*xAttrList*/ ) override
447 ODBFilter
& rImport(static_cast<ODBFilter
&>(GetImport()));
450 case XML_ELEMENT(OFFICE
, XML_BODY
):
451 case XML_ELEMENT(OOO
, XML_BODY
):
452 return new DBXMLDocumentBodyContext(rImport
);
453 case XML_ELEMENT(OFFICE
, XML_SCRIPTS
):
454 return new XMLScriptContext(GetImport(), rImport
.GetModel());
455 case XML_ELEMENT(OFFICE
, XML_AUTOMATIC_STYLES
):
456 case XML_ELEMENT(OOO
, XML_AUTOMATIC_STYLES
):
457 rImport
.GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP
);
458 return rImport
.CreateStylesContext(true);
467 SvXMLImportContext
* ODBFilter::CreateFastContext(sal_Int32 nElement
,
468 const ::css::uno::Reference
< ::css::xml::sax::XFastAttributeList
>& /*xAttrList*/ )
470 SvXMLImportContext
*pContext
= nullptr;
474 case XML_ELEMENT(OFFICE
, XML_DOCUMENT_SETTINGS
):
475 case XML_ELEMENT(OOO
, XML_DOCUMENT_SETTINGS
):
476 GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP
);
477 pContext
= new DBXMLDocumentSettingsContext(*this);
479 case XML_ELEMENT(OFFICE
, XML_DOCUMENT_STYLES
):
480 case XML_ELEMENT(OOO
, XML_DOCUMENT_STYLES
):
481 pContext
= new DBXMLDocumentStylesContext(*this);
483 case XML_ELEMENT(OFFICE
, XML_DOCUMENT_CONTENT
):
484 case XML_ELEMENT(OOO
, XML_DOCUMENT_CONTENT
):
485 pContext
= new DBXMLDocumentContentContext(*this);
493 void ODBFilter::SetViewSettings(const Sequence
<PropertyValue
>& aViewProps
)
495 const PropertyValue
*pIter
= aViewProps
.getConstArray();
496 const PropertyValue
*pEnd
= pIter
+ aViewProps
.getLength();
497 for (; pIter
!= pEnd
; ++pIter
)
499 if ( pIter
->Name
== "Queries" )
501 fillPropertyMap(pIter
->Value
,m_aQuerySettings
);
503 else if ( pIter
->Name
== "Tables" )
505 fillPropertyMap(pIter
->Value
,m_aTablesSettings
);
511 void ODBFilter::SetConfigurationSettings(const Sequence
<PropertyValue
>& aConfigProps
)
513 const PropertyValue
*pIter
= aConfigProps
.getConstArray();
514 const PropertyValue
*pEnd
= pIter
+ aConfigProps
.getLength();
515 for (; pIter
!= pEnd
; ++pIter
)
517 if ( pIter
->Name
== "layout-settings" )
519 Sequence
<PropertyValue
> aWindows
;
520 pIter
->Value
>>= aWindows
;
521 uno::Reference
<XPropertySet
> xProp(getDataSource());
523 xProp
->setPropertyValue(PROPERTY_LAYOUTINFORMATION
,Any(aWindows
));
529 void ODBFilter::fillPropertyMap(const Any
& _rValue
,TPropertyNameMap
& _rMap
)
531 Sequence
<PropertyValue
> aWindows
;
532 _rValue
>>= aWindows
;
533 const PropertyValue
*pIter
= aWindows
.getConstArray();
534 const PropertyValue
*pEnd
= pIter
+ aWindows
.getLength();
535 for (; pIter
!= pEnd
; ++pIter
)
537 Sequence
<PropertyValue
> aValue
;
538 pIter
->Value
>>= aValue
;
539 _rMap
.emplace( pIter
->Name
,aValue
);
544 SvXMLImportContext
* ODBFilter::CreateStylesContext( bool bIsAutoStyle
)
546 SvXMLImportContext
*pContext
= new OTableStylesContext(*this, bIsAutoStyle
);
548 SetAutoStyles(static_cast<SvXMLStylesContext
*>(pContext
));
550 SetStyles(static_cast<SvXMLStylesContext
*>(pContext
));
556 rtl::Reference
< XMLPropertySetMapper
> const & ODBFilter::GetTableStylesPropertySetMapper() const
558 if ( !m_xTableStylesPropertySetMapper
.is() )
560 m_xTableStylesPropertySetMapper
= OXMLHelper::GetTableStylesPropertySetMapper( false);
562 return m_xTableStylesPropertySetMapper
;
566 rtl::Reference
< XMLPropertySetMapper
> const & ODBFilter::GetColumnStylesPropertySetMapper() const
568 if ( !m_xColumnStylesPropertySetMapper
.is() )
570 m_xColumnStylesPropertySetMapper
= OXMLHelper::GetColumnStylesPropertySetMapper( false);
572 return m_xColumnStylesPropertySetMapper
;
576 rtl::Reference
< XMLPropertySetMapper
> const & ODBFilter::GetCellStylesPropertySetMapper() const
578 if ( !m_xCellStylesPropertySetMapper
.is() )
580 m_xCellStylesPropertySetMapper
= OXMLHelper::GetCellStylesPropertySetMapper( false);
582 return m_xCellStylesPropertySetMapper
;
586 void ODBFilter::setPropertyInfo()
588 Reference
<XPropertySet
> xDataSource(getDataSource());
589 if ( !xDataSource
.is() )
592 ::connectivity::DriversConfig
aDriverConfig(GetComponentContext());
593 const OUString sURL
= ::comphelper::getString(xDataSource
->getPropertyValue(PROPERTY_URL
));
594 ::comphelper::NamedValueCollection aDataSourceSettings
= aDriverConfig
.getProperties( sURL
);
596 Sequence
<PropertyValue
> aInfo
;
597 if ( !m_aInfoSequence
.empty() )
598 aInfo
= comphelper::containerToSequence(m_aInfoSequence
);
599 aDataSourceSettings
.merge( ::comphelper::NamedValueCollection( aInfo
), true );
601 aDataSourceSettings
>>= aInfo
;
602 if ( aInfo
.hasElements() )
606 xDataSource
->setPropertyValue(PROPERTY_INFO
,Any(aInfo
));
608 catch (const Exception
&)
610 DBG_UNHANDLED_EXCEPTION("dbaccess");
615 } // namespace dbaxml
617 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */