LibreOffice Module xmloff (master)  1
XMLEmbeddedObjectImportContext.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <sal/config.h>
21 
22 #include <string_view>
23 
24 #include <sal/log.hxx>
25 #include <com/sun/star/document/XImporter.hpp>
26 #include <com/sun/star/uno/XComponentContext.hpp>
27 #include <com/sun/star/util/XModifiable2.hpp>
28 #include <tools/globname.hxx>
29 #include <comphelper/classids.hxx>
30 #include <xmloff/namespacemap.hxx>
31 #include <xmloff/xmlimp.hxx>
32 #include <xmloff/xmlnamespace.hxx>
33 #include <xmloff/xmltoken.hxx>
34 #include <xmloff/attrlist.hxx>
37 
38 using namespace ::com::sun::star::uno;
39 using namespace ::com::sun::star::util;
40 using namespace ::com::sun::star::beans;
41 using namespace ::com::sun::star::lang;
42 using namespace ::com::sun::star::document;
43 using namespace ::com::sun::star::xml::sax;
44 using namespace ::xmloff::token;
45 
46 namespace {
47 
48 class XMLEmbeddedObjectImportContext_Impl : public SvXMLImportContext
49 {
50  css::uno::Reference< css::xml::sax::XDocumentHandler > xHandler;
51 
52 public:
53 
54  XMLEmbeddedObjectImportContext_Impl( SvXMLImport& rImport, sal_uInt16 nPrfx,
55  const OUString& rLName,
56  const css::uno::Reference< css::xml::sax::XDocumentHandler >& rHandler );
57 
58  virtual SvXMLImportContextRef CreateChildContext( sal_uInt16 nPrefix,
59  const OUString& rLocalName,
60  const css::uno::Reference< css::xml::sax::XAttributeList >& xAttrList ) override;
61 
62  virtual void StartElement( const css::uno::Reference< css::xml::sax::XAttributeList >& xAttrList ) override;
63 
64  virtual void EndElement() override;
65 
66  virtual void Characters( const OUString& rChars ) override;
67 };
68 
69 }
70 
71 XMLEmbeddedObjectImportContext_Impl::XMLEmbeddedObjectImportContext_Impl(
72  SvXMLImport& rImport, sal_uInt16 nPrfx,
73  const OUString& rLName,
74  const Reference< XDocumentHandler >& rHandler ) :
75  SvXMLImportContext( rImport, nPrfx, rLName ),
76  xHandler( rHandler )
77 {
79 }
80 
81 SvXMLImportContextRef XMLEmbeddedObjectImportContext_Impl::CreateChildContext(
82  sal_uInt16 nPrefix,
83  const OUString& rLocalName,
84  const Reference< XAttributeList >& )
85 {
86  return new XMLEmbeddedObjectImportContext_Impl( GetImport(),
87  nPrefix, rLocalName,
88  xHandler );
89 }
90 
91 void XMLEmbeddedObjectImportContext_Impl::StartElement(
92  const Reference< XAttributeList >& xAttrList )
93 {
94  xHandler->startElement( GetImport().GetNamespaceMap().GetQNameByKey(
95  GetPrefix(), GetLocalName() ),
96  xAttrList );
97 }
98 
99 void XMLEmbeddedObjectImportContext_Impl::EndElement()
100 {
101  xHandler->endElement( GetImport().GetNamespaceMap().GetQNameByKey(
102  GetPrefix(), GetLocalName() ) );
103 }
104 
105 void XMLEmbeddedObjectImportContext_Impl::Characters( const OUString& rChars )
106 {
107  xHandler->characters( rChars );
108 }
109 
110 
111 void XMLEmbeddedObjectImportContext::SetComponent( Reference< XComponent > const & rComp )
112 {
113  if( !rComp.is() || sFilterService.isEmpty() )
114  return;
115 
116  Sequence<Any> aArgs( 0 );
117 
118  Reference< XComponentContext > xContext( GetImport().GetComponentContext() );
119 
120  Reference<XInterface> xFilter =
121  xContext->getServiceManager()->createInstanceWithArgumentsAndContext(sFilterService, aArgs, xContext);
122  SAL_WARN_IF(!xFilter, "xmloff", "could not create filter " << sFilterService);
123  if( !xFilter.is() )
124  return;
125 
126  if (SvXMLImport *pFastHandler = dynamic_cast<SvXMLImport*>(xFilter.get()))
127  xHandler.set( new SvXMLLegacyToFastDocHandler( pFastHandler ) );
128  else
129  xHandler.set(xFilter, UNO_QUERY);
130 
131  assert( xHandler );
132 
133  try
134  {
135  Reference < XModifiable2 > xModifiable2( rComp, UNO_QUERY_THROW );
136  xModifiable2->disableSetModified();
137  }
138  catch( Exception& )
139  {
140  }
141 
142  Reference < XImporter > xImporter( xHandler, UNO_QUERY );
143  xImporter->setTargetDocument( rComp );
144 
145  xComp = rComp; // keep ref to component only if there is a handler
146 }
147 
149  SvXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLName,
150  const Reference< XAttributeList >& xAttrList ) :
151  SvXMLImportContext( rImport, nPrfx, rLName )
152 {
154 
155  if( nPrfx == XML_NAMESPACE_MATH &&
156  IsXMLToken( rLName, XML_MATH ) )
157  {
159  aName = SvGlobalName(SO3_SM_CLASSID);
160  }
161  else if( nPrfx == XML_NAMESPACE_OFFICE &&
162  IsXMLToken( rLName, XML_DOCUMENT ) )
163  {
164  OUString sMime;
165 
166  sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
167  for( sal_Int16 i=0; i < nAttrCount; i++ )
168  {
169  const OUString& rAttrName = xAttrList->getNameByIndex( i );
170  OUString aLocalName;
171  sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName, &aLocalName );
172  if( nPrefix == XML_NAMESPACE_OFFICE &&
173  IsXMLToken( aLocalName, XML_MIMETYPE ) )
174  {
175  sMime = xAttrList->getValueByIndex( i );
176  break;
177  }
178  }
179 
180  OUString sClass;
181  static std::u16string_view const prefixes[] = {
182  u"application/vnd.oasis.openoffice.",
183  u"application/x-vnd.oasis.openoffice.",
184  u"application/vnd.oasis.opendocument.",
185  u"application/x-vnd.oasis.opendocument."};
186  for (auto const & p: prefixes)
187  {
188  if (sMime.startsWith(p, &sClass))
189  {
190  break;
191  }
192  }
193 
194  if( !sClass.isEmpty() )
195  {
196  static struct { XMLTokenEnum eClass; std::u16string_view sFilterService;
197  } const aServiceMap[] = {
198  { XML_TEXT, std::u16string_view(u"" XML_IMPORT_FILTER_WRITER) },
199  { XML_ONLINE_TEXT, std::u16string_view(u"" XML_IMPORT_FILTER_WRITER) },
200  { XML_SPREADSHEET, std::u16string_view(u"" XML_IMPORT_FILTER_CALC) },
201  { XML_DRAWING, std::u16string_view(u"" XML_IMPORT_FILTER_DRAW) },
202  { XML_GRAPHICS, std::u16string_view(u"" XML_IMPORT_FILTER_DRAW) },
203  { XML_PRESENTATION, std::u16string_view(u"" XML_IMPORT_FILTER_IMPRESS) },
204  { XML_CHART, std::u16string_view(u"" XML_IMPORT_FILTER_CHART) }};
205  for (auto const & entry: aServiceMap)
206  {
207  if( IsXMLToken( sClass, entry.eClass ) )
208  {
209  sFilterService = entry.sFilterService;
210 
211  switch( entry.eClass )
212  {
213  case XML_TEXT: aName = SvGlobalName(SO3_SW_CLASSID); break;
214  case XML_ONLINE_TEXT: aName = SvGlobalName(SO3_SWWEB_CLASSID); break;
215  case XML_SPREADSHEET: aName = SvGlobalName(SO3_SC_CLASSID); break;
216  case XML_DRAWING:
217  case XML_GRAPHICS:
218  case XML_IMAGE: aName = SvGlobalName(SO3_SDRAW_CLASSID); break;
219  case XML_PRESENTATION: aName = SvGlobalName(SO3_SIMPRESS_CLASSID); break;
220  case XML_CHART: aName = SvGlobalName(SO3_SCH_CLASSID); break;
221  default:
222  break;
223  }
224 
225  break;
226  }
227  }
228  }
229  }
230 
231  sCLSID = aName.GetHexName();
232 }
233 
235 {
236 }
237 
239  sal_uInt16 nPrefix, const OUString& rLocalName,
240  const Reference< XAttributeList >& )
241 {
242  if( xHandler.is() )
243  return new XMLEmbeddedObjectImportContext_Impl( GetImport(),
244  nPrefix, rLocalName,
245  xHandler );
246  return nullptr;
247 }
248 
250  const Reference< XAttributeList >& rAttrList )
251 {
252  if( !xHandler.is() )
253  return;
254 
255  xHandler->startDocument();
256  // #i34042: copy namepspace declarations
257  SvXMLAttributeList *pAttrList = new SvXMLAttributeList( rAttrList );
258  Reference< XAttributeList > xAttrList( pAttrList );
259  const SvXMLNamespaceMap& rNamespaceMap = GetImport().GetNamespaceMap();
260  sal_uInt16 nPos = rNamespaceMap.GetFirstKey();
261  while( USHRT_MAX != nPos )
262  {
263  OUString aAttrName( rNamespaceMap.GetAttrNameByKey( nPos ) );
264  if( xAttrList->getValueByName( aAttrName ).isEmpty() )
265  {
266  pAttrList->AddAttribute( aAttrName,
267  rNamespaceMap.GetNameByKey( nPos ) );
268  }
269  nPos = rNamespaceMap.GetNextKey( nPos );
270  }
271  xHandler->startElement( GetImport().GetNamespaceMap().GetQNameByKey(
272  GetPrefix(), GetLocalName() ),
273  xAttrList );
274 }
275 
277 {
278  if( !xHandler.is() )
279  return;
280 
281  xHandler->endElement( GetImport().GetNamespaceMap().GetQNameByKey(
282  GetPrefix(), GetLocalName() ) );
283  xHandler->endDocument();
284 
285  try
286  {
287  Reference < XModifiable2 > xModifiable2( xComp, UNO_QUERY_THROW );
288  xModifiable2->enableSetModified();
289  xModifiable2->setModified( true ); // trigger new replacement image generation
290  }
291  catch( Exception& )
292  {
293  }
294 }
295 
296 void XMLEmbeddedObjectImportContext::Characters( const OUString& rChars )
297 {
298  if( xHandler.is() )
299  xHandler->characters( rChars );
300 }
301 
302 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
constexpr sal_uInt16 XML_NAMESPACE_MATH
bool IsXMLToken(const OUString &rString, enum XMLTokenEnum eToken)
compare eToken to the string
Definition: xmltoken.cxx:3434
constexpr sal_uInt16 XML_NAMESPACE_OFFICE
virtual void EndElement()
EndElement is called before a context will be destructed, but after an elements context has been pars...
Definition: xmlictxt.cxx:62
#define XML_IMPORT_FILTER_CALC
SvXMLImport & GetImport()
Definition: xmlictxt.hxx:62
sal_uInt16 GetFirstKey() const
css::uno::Reference< css::xml::sax::XDocumentHandler > xHandler
SvXMLNamespaceMap & GetNamespaceMap()
Definition: xmlimp.hxx:402
#define SO3_SW_CLASSID
OUString GetAttrNameByKey(sal_uInt16 nKey) const
virtual void StartElement(const css::uno::Reference< css::xml::sax::XAttributeList > &xAttrList)
StartElement is called after a context has been constructed and before an elements context is parsed...
Definition: xmlictxt.cxx:58
#define SO3_SM_CLASSID
sal_uInt16 GetKeyByAttrName(const OUString &rAttrName, OUString *pPrefix, OUString *pLocalName, OUString *pNamespace) const
#define SO3_SIMPRESS_CLASSID
virtual void Characters(const OUString &rChars) override
This method is called for all characters that are contained in the current element.
virtual void Characters(const OUString &rChars)
This method is called for all characters that are contained in the current element.
Definition: xmlictxt.cxx:66
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
const OUString & GetLocalName() const
Definition: xmlictxt.hxx:69
XMLEmbeddedObjectImportContext(SvXMLImport &rImport, sal_uInt16 nPrfx, const OUString &rLName, const css::uno::Reference< css::xml::sax::XAttributeList > &xAttrList)
XMLTokenEnum
The enumeration of all XML tokens.
Definition: xmltoken.hxx:49
#define XML_IMPORT_FILTER_IMPRESS
const XMLServiceMapEntry_Impl aServiceMap[]
Definition: xmlexp.cxx:138
int i
#define XML_IMPORT_FILTER_DRAW
OUString GetHexName() const
virtual SvXMLImportContextRef CreateChildContext(sal_uInt16 nPrefix, const OUString &rLocalName, const css::uno::Reference< css::xml::sax::XAttributeList > &xAttrList) override
Create a children element context.
float u
virtual void EndElement() override
EndElement is called before a context will be destructed, but after an elements context has been pars...
sal_uInt16 GetNextKey(sal_uInt16 nOldKey) const
const OUString & GetNameByKey(sal_uInt16 nKey) const
#define SO3_SC_CLASSID
This class deliberately does not support XWeak, to improve performance when loading large documents...
Definition: xmlictxt.hxx:44
css::uno::Reference< css::lang::XComponent > xComp
#define SAL_WARN_IF(condition, area, stream)
void SetComponent(css::uno::Reference< css::lang::XComponent > const &rComp)
const o3tl::enumarray< SvxAdjust, unsigned short > aSvxToUnoAdjust USHRT_MAX
Handling of tokens in XML:
virtual void StartElement(const css::uno::Reference< css::xml::sax::XAttributeList > &xAttrList) override
StartElement is called after a context has been constructed and before an elements context is parsed...
OUString aName
#define SO3_SCH_CLASSID
#define XML_IMPORT_FILTER_WRITER
css::uno::Reference< css::xml::sax::XDocumentHandler > xHandler
#define XML_IMPORT_FILTER_MATH
void * p
#define SO3_SWWEB_CLASSID
virtual SvXMLImportContextRef CreateChildContext(sal_uInt16 nPrefix, const OUString &rLocalName, const css::uno::Reference< css::xml::sax::XAttributeList > &xAttrList)
Create a children element context.
Definition: xmlictxt.cxx:51
#define XML_IMPORT_FILTER_CHART
void AddAttribute(const OUString &sName, const OUString &sValue)
Definition: attrlist.cxx:143
sal_uInt16 GetPrefix() const
Definition: xmlictxt.hxx:68
#define SO3_SDRAW_CLASSID
sal_uInt16 nPos