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 <com/sun/star/document/XImporter.hpp>
21 #include <com/sun/star/uno/XComponentContext.hpp>
22 #include <com/sun/star/util/XModifiable2.hpp>
23 #include <tools/globname.hxx>
24 #include <comphelper/classids.hxx>
25 #include <xmloff/nmspmap.hxx>
26 #include <xmloff/xmlimp.hxx>
27 #include <xmloff/xmlnmspe.hxx>
28 #include <xmloff/xmltoken.hxx>
29 #include <xmloff/attrlist.hxx>
32 
33 using namespace ::com::sun::star::uno;
34 using namespace ::com::sun::star::util;
35 using namespace ::com::sun::star::beans;
36 using namespace ::com::sun::star::lang;
37 using namespace ::com::sun::star::document;
38 using namespace ::com::sun::star::xml::sax;
39 using namespace ::xmloff::token;
40 
41 namespace {
42 
43 class XMLEmbeddedObjectImportContext_Impl : public SvXMLImportContext
44 {
45  css::uno::Reference< css::xml::sax::XDocumentHandler > xHandler;
46 
47 public:
48 
49  XMLEmbeddedObjectImportContext_Impl( SvXMLImport& rImport, sal_uInt16 nPrfx,
50  const OUString& rLName,
51  const css::uno::Reference< css::xml::sax::XDocumentHandler >& rHandler );
52 
53  virtual SvXMLImportContextRef CreateChildContext( sal_uInt16 nPrefix,
54  const OUString& rLocalName,
55  const css::uno::Reference< css::xml::sax::XAttributeList >& xAttrList ) override;
56 
57  virtual void StartElement( const css::uno::Reference< css::xml::sax::XAttributeList >& xAttrList ) override;
58 
59  virtual void EndElement() override;
60 
61  virtual void Characters( const OUString& rChars ) override;
62 };
63 
64 }
65 
66 XMLEmbeddedObjectImportContext_Impl::XMLEmbeddedObjectImportContext_Impl(
67  SvXMLImport& rImport, sal_uInt16 nPrfx,
68  const OUString& rLName,
69  const Reference< XDocumentHandler >& rHandler ) :
70  SvXMLImportContext( rImport, nPrfx, rLName ),
71  xHandler( rHandler )
72 {
73 }
74 
75 SvXMLImportContextRef XMLEmbeddedObjectImportContext_Impl::CreateChildContext(
76  sal_uInt16 nPrefix,
77  const OUString& rLocalName,
78  const Reference< XAttributeList >& )
79 {
80  return new XMLEmbeddedObjectImportContext_Impl( GetImport(),
81  nPrefix, rLocalName,
82  xHandler );
83 }
84 
85 void XMLEmbeddedObjectImportContext_Impl::StartElement(
86  const Reference< XAttributeList >& xAttrList )
87 {
88  xHandler->startElement( GetImport().GetNamespaceMap().GetQNameByKey(
89  GetPrefix(), GetLocalName() ),
90  xAttrList );
91 }
92 
93 void XMLEmbeddedObjectImportContext_Impl::EndElement()
94 {
95  xHandler->endElement( GetImport().GetNamespaceMap().GetQNameByKey(
96  GetPrefix(), GetLocalName() ) );
97 }
98 
99 void XMLEmbeddedObjectImportContext_Impl::Characters( const OUString& rChars )
100 {
101  xHandler->characters( rChars );
102 }
103 
104 
105 void XMLEmbeddedObjectImportContext::SetComponent( Reference< XComponent > const & rComp )
106 {
107  if( !rComp.is() || sFilterService.isEmpty() )
108  return;
109 
110  Sequence<Any> aArgs( 0 );
111 
112  Reference< XComponentContext > xContext( GetImport().GetComponentContext() );
113 
114  xHandler.set(
115  xContext->getServiceManager()->createInstanceWithArgumentsAndContext(sFilterService, aArgs, xContext),
116  UNO_QUERY);
117 
118  if( !xHandler.is() )
119  return;
120 
121  if (SvXMLImport *pFastHandler = dynamic_cast<SvXMLImport*>(xHandler.get()))
122  xHandler.set( new SvXMLLegacyToFastDocHandler( pFastHandler ) );
123 
124  try
125  {
126  Reference < XModifiable2 > xModifiable2( rComp, UNO_QUERY_THROW );
127  xModifiable2->disableSetModified();
128  }
129  catch( Exception& )
130  {
131  }
132 
133  Reference < XImporter > xImporter( xHandler, UNO_QUERY );
134  xImporter->setTargetDocument( rComp );
135 
136  xComp = rComp; // keep ref to component only if there is a handler
137 }
138 
140  SvXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLName,
141  const Reference< XAttributeList >& xAttrList ) :
142  SvXMLImportContext( rImport, nPrfx, rLName )
143 {
145 
146  if( nPrfx == XML_NAMESPACE_MATH &&
147  IsXMLToken( rLName, XML_MATH ) )
148  {
150  aName = SvGlobalName(SO3_SM_CLASSID);
151  }
152  else if( nPrfx == XML_NAMESPACE_OFFICE &&
153  IsXMLToken( rLName, XML_DOCUMENT ) )
154  {
155  OUString sMime;
156 
157  sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
158  for( sal_Int16 i=0; i < nAttrCount; i++ )
159  {
160  const OUString& rAttrName = xAttrList->getNameByIndex( i );
161  OUString aLocalName;
162  sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName, &aLocalName );
163  if( nPrefix == XML_NAMESPACE_OFFICE &&
164  IsXMLToken( aLocalName, XML_MIMETYPE ) )
165  {
166  sMime = xAttrList->getValueByIndex( i );
167  break;
168  }
169  }
170 
171  OUString sClass;
172  static OUStringLiteral const prefixes[] = {
173  "application/vnd.oasis.openoffice.",
174  "application/x-vnd.oasis.openoffice.",
175  "application/vnd.oasis.opendocument.",
176  "application/x-vnd.oasis.opendocument."};
177  for (auto const & p: prefixes)
178  {
179  if (sMime.startsWith(p, &sClass))
180  {
181  break;
182  }
183  }
184 
185  if( !sClass.isEmpty() )
186  {
187  static struct { XMLTokenEnum eClass; OUStringLiteral sFilterService;
188  } const aServiceMap[] = {
189  { XML_TEXT, OUStringLiteral(XML_IMPORT_FILTER_WRITER) },
190  { XML_ONLINE_TEXT, OUStringLiteral(XML_IMPORT_FILTER_WRITER) },
191  { XML_SPREADSHEET, OUStringLiteral(XML_IMPORT_FILTER_CALC) },
192  { XML_DRAWING, OUStringLiteral(XML_IMPORT_FILTER_DRAW) },
193  { XML_GRAPHICS, OUStringLiteral(XML_IMPORT_FILTER_DRAW) },
194  { XML_PRESENTATION, OUStringLiteral(XML_IMPORT_FILTER_IMPRESS) },
195  { XML_CHART, OUStringLiteral(XML_IMPORT_FILTER_CHART) }};
196  for (auto const & entry: aServiceMap)
197  {
198  if( IsXMLToken( sClass, entry.eClass ) )
199  {
200  sFilterService = entry.sFilterService;
201 
202  switch( entry.eClass )
203  {
204  case XML_TEXT: aName = SvGlobalName(SO3_SW_CLASSID); break;
205  case XML_ONLINE_TEXT: aName = SvGlobalName(SO3_SWWEB_CLASSID); break;
206  case XML_SPREADSHEET: aName = SvGlobalName(SO3_SC_CLASSID); break;
207  case XML_DRAWING:
208  case XML_GRAPHICS:
209  case XML_IMAGE: aName = SvGlobalName(SO3_SDRAW_CLASSID); break;
210  case XML_PRESENTATION: aName = SvGlobalName(SO3_SIMPRESS_CLASSID); break;
211  case XML_CHART: aName = SvGlobalName(SO3_SCH_CLASSID); break;
212  default:
213  break;
214  }
215 
216  break;
217  }
218  }
219  }
220  }
221 
222  sCLSID = aName.GetHexName();
223 }
224 
226 {
227 }
228 
230  sal_uInt16 nPrefix, const OUString& rLocalName,
231  const Reference< XAttributeList >& )
232 {
233  if( xHandler.is() )
234  return new XMLEmbeddedObjectImportContext_Impl( GetImport(),
235  nPrefix, rLocalName,
236  xHandler );
237  return nullptr;
238 }
239 
241  const Reference< XAttributeList >& rAttrList )
242 {
243  if( xHandler.is() )
244  {
245  xHandler->startDocument();
246  // #i34042: copy namepspace declarations
247  SvXMLAttributeList *pAttrList = new SvXMLAttributeList( rAttrList );
248  Reference< XAttributeList > xAttrList( pAttrList );
249  const SvXMLNamespaceMap& rNamespaceMap = GetImport().GetNamespaceMap();
250  sal_uInt16 nPos = rNamespaceMap.GetFirstKey();
251  while( USHRT_MAX != nPos )
252  {
253  OUString aAttrName( rNamespaceMap.GetAttrNameByKey( nPos ) );
254  if( xAttrList->getValueByName( aAttrName ).isEmpty() )
255  {
256  pAttrList->AddAttribute( aAttrName,
257  rNamespaceMap.GetNameByKey( nPos ) );
258  }
259  nPos = rNamespaceMap.GetNextKey( nPos );
260  }
261  xHandler->startElement( GetImport().GetNamespaceMap().GetQNameByKey(
262  GetPrefix(), GetLocalName() ),
263  xAttrList );
264  }
265 }
266 
268 {
269  if( xHandler.is() )
270  {
271  xHandler->endElement( GetImport().GetNamespaceMap().GetQNameByKey(
272  GetPrefix(), GetLocalName() ) );
273  xHandler->endDocument();
274 
275  try
276  {
277  Reference < XModifiable2 > xModifiable2( xComp, UNO_QUERY_THROW );
278  xModifiable2->enableSetModified();
279  xModifiable2->setModified( true ); // trigger new replacement image generation
280  }
281  catch( Exception& )
282  {
283  }
284  }
285 }
286 
287 void XMLEmbeddedObjectImportContext::Characters( const OUString& rChars )
288 {
289  if( xHandler.is() )
290  xHandler->characters( rChars );
291 }
292 
293 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool IsXMLToken(const OUString &rString, enum XMLTokenEnum eToken)
compare eToken to the string
Definition: xmltoken.cxx:3422
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
Definition: nmspmap.cxx:360
css::uno::Reference< css::xml::sax::XDocumentHandler > xHandler
SvXMLNamespaceMap & GetNamespaceMap()
Definition: xmlimp.hxx:397
#define SO3_SW_CLASSID
OUString GetAttrNameByKey(sal_uInt16 nKey) const
Definition: nmspmap.cxx:174
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
Definition: nmspmap.cxx:437
#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
constexpr sal_uInt16 XML_NAMESPACE_MATH
Definition: xmlnmspe.hxx:43
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:47
#define XML_IMPORT_FILTER_IMPRESS
const XMLServiceMapEntry_Impl aServiceMap[]
Definition: xmlexp.cxx:140
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.
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
Definition: nmspmap.cxx:365
const OUString & GetNameByKey(sal_uInt16 nKey) const
Definition: nmspmap.cxx:168
#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
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
#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
constexpr sal_uInt16 XML_NAMESPACE_OFFICE
Definition: xmlnmspe.hxx:29