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 <com/sun/star/embed/ElementModes.hpp>
21 #include <com/sun/star/embed/XTransactedObject.hpp>
22 #include <svl/macitem.hxx>
23 #include <svtools/unoevent.hxx>
24 #include <sfx2/docfile.hxx>
25 #include <unotools/streamwrap.hxx>
26 #include <comphelper/componentcontext.hxx>
27 #include <comphelper/processfactory.hxx>
28 #include <com/sun/star/xml/sax/InputSource.hpp>
29 #include <com/sun/star/io/XActiveDataSource.hpp>
30 #include <com/sun/star/xml/sax/Parser.hpp>
31 #include <com/sun/star/xml/sax/Writer.hpp>
32 #include <com/sun/star/document/XStorageBasedDocument.hpp>
35 #include <shellio.hxx>
36 #include <SwXMLTextBlocks.hxx>
37 #include <SwXMLBlockImport.hxx>
38 #include <SwXMLBlockExport.hxx>
39 #include <swevent.hxx>
42 const char XMLN_BLOCKLIST
[] = "BlockList.xml";
44 using namespace ::com::sun::star
;
45 using namespace ::com::sun::star::uno
;
46 using namespace ::com::sun::star::container
;
48 using ::xmloff::token::XML_BLOCK_LIST
;
49 using ::xmloff::token::XML_UNFORMATTED_TEXT
;
50 using ::xmloff::token::GetXMLToken
;
52 sal_uLong
SwXMLTextBlocks::GetDoc( sal_uInt16 nIdx
)
54 String
aFolderName ( GetPackageName ( nIdx
) );
56 if (!IsOnlyTextBlock ( nIdx
) )
60 xRoot
= xBlkRoot
->openStorageElement( aFolderName
, embed::ElementModes::READ
);
61 xMedium
= new SfxMedium( xRoot
, GetBaseURL(), OUString( "writer8" ) );
62 SwReader
aReader( *xMedium
, aFolderName
, pDoc
);
63 ReadXML
->SetBlockMode( sal_True
);
64 aReader
.Read( *ReadXML
);
65 ReadXML
->SetBlockMode( sal_False
);
66 // Ole objects fails to display when inserted into document
67 // because the ObjectReplacement folder ( and contents are missing )
68 OUString
sObjReplacements( "ObjectReplacements" );
69 if ( xRoot
->hasByName( sObjReplacements
) )
71 uno::Reference
< document::XStorageBasedDocument
> xDocStor( pDoc
->GetDocShell()->GetModel(), uno::UNO_QUERY_THROW
);
72 uno::Reference
< embed::XStorage
> xStr( xDocStor
->getDocumentStorage() );
75 xRoot
->copyElementTo( sObjReplacements
, xStr
, sObjReplacements
);
76 uno::Reference
< embed::XTransactedObject
> xTrans( xStr
, uno::UNO_QUERY
);
82 catch( uno::Exception
& )
90 String aStreamName
= aFolderName
+ OUString(".xml");
93 xRoot
= xBlkRoot
->openStorageElement( aFolderName
, embed::ElementModes::READ
);
94 uno::Reference
< io::XStream
> xStream
= xRoot
->openStreamElement( aStreamName
, embed::ElementModes::READ
);
96 uno::Reference
< uno::XComponentContext
> xContext
=
97 comphelper::getProcessComponentContext();
99 xml::sax::InputSource aParserInput
;
100 aParserInput
.sSystemId
= aNames
[nIdx
]->aPackageName
;
102 aParserInput
.aInputStream
= xStream
->getInputStream();
105 // uno::Reference< xml::sax::XDocumentHandler > xFilter = new SwXMLTextBlockImport( *this, aCur, sal_True );
106 uno::Reference
< xml::sax::XDocumentHandler
> xFilter
= new SwXMLTextBlockImport( xContext
, *this, aCur
, sal_True
);
108 // connect parser and filter
109 uno::Reference
< xml::sax::XParser
> xParser
= xml::sax::Parser::create(xContext
);
110 xParser
->setDocumentHandler( xFilter
);
115 xParser
->parseStream( aParserInput
);
117 catch( xml::sax::SAXParseException
& )
121 catch( xml::sax::SAXException
& )
125 catch( io::IOException
& )
130 bInfoChanged
= sal_False
;
133 catch( uno::Exception
& )
142 // event description for autotext events; this constant should really be
143 // taken from unocore/unoevents.cxx or ui/unotxt.cxx
144 const struct SvEventDescription aAutotextEvents
[] =
146 { SW_EVENT_START_INS_GLOSSARY
, "OnInsertStart" },
147 { SW_EVENT_END_INS_GLOSSARY
, "OnInsertDone" },
151 sal_uLong
SwXMLTextBlocks::GetMacroTable( sal_uInt16 nIdx
,
152 SvxMacroTableDtor
& rMacroTbl
,
153 sal_Bool bFileAlreadyOpen
)
155 // set current auto text
157 aShort
= aNames
[nIdx
]->aShort
;
158 aLong
= aNames
[nIdx
]->aLong
;
159 aPackageName
= aNames
[nIdx
]->aPackageName
;
163 // open stream in proper sub-storage
164 if( !bFileAlreadyOpen
)
167 nRet
= OpenFile ( sal_True
);
173 xRoot
= xBlkRoot
->openStorageElement( aPackageName
, embed::ElementModes::READ
);
174 long nTmp
= SOT_FORMATSTR_ID_STARWRITER_60
;
175 bool bOasis
= ( SotStorage::GetVersion( xRoot
) > nTmp
);
177 OUString
sStreamName("atevent.xml");
178 uno::Reference
< io::XStream
> xDocStream
= xRoot
->openStreamElement(
179 sStreamName
, embed::ElementModes::READ
);
180 OSL_ENSURE(xDocStream
.is(), "Can't create stream");
181 if ( xDocStream
.is() )
183 uno::Reference
<io::XInputStream
> xInputStream
= xDocStream
->getInputStream();
185 // prepare ParserInputSrouce
186 xml::sax::InputSource aParserInput
;
187 aParserInput
.sSystemId
= aName
;
188 aParserInput
.aInputStream
= xInputStream
;
190 // get service factory
191 uno::Reference
< uno::XComponentContext
> xContext
=
192 comphelper::getProcessComponentContext();
195 uno::Reference
< xml::sax::XParser
> xParser
= xml::sax::Parser::create( xContext
);
197 // create descriptor and reference to it. Either
198 // both or neither must be kept because of the
199 // reference counting!
200 SvMacroTableEventDescriptor
* pDescriptor
=
201 new SvMacroTableEventDescriptor(aAutotextEvents
);
202 uno::Reference
<XNameReplace
> xReplace
= pDescriptor
;
203 Sequence
<Any
> aFilterArguments( 1 );
204 aFilterArguments
[0] <<= xReplace
;
207 OUString sFilterComponent
= bOasis
208 ? OUString("com.sun.star.comp.Writer.XMLOasisAutotextEventsImporter")
209 : OUString("com.sun.star.comp.Writer.XMLAutotextEventsImporter");
210 uno::Reference
< xml::sax::XDocumentHandler
> xFilter(
211 xContext
->getServiceManager()->createInstanceWithArgumentsAndContext(
212 sFilterComponent
, aFilterArguments
, xContext
),
214 OSL_ENSURE( xFilter
.is(),
215 "can't instantiate atevents filter");
218 // connect parser and filter
219 xParser
->setDocumentHandler( xFilter
);
221 // connect model and filter
222 uno::Reference
<document::XImporter
> xImporter( xFilter
,
225 // we don't need a model
226 // xImporter->setTargetDocument( xModelComponent );
231 xParser
->parseStream( aParserInput
);
233 catch( xml::sax::SAXParseException
& )
235 // workaround for #83452#: SetSize doesn't work
236 // nRet = ERR_SWG_READ_ERROR;
238 catch( xml::sax::SAXException
& )
240 nRet
= ERR_SWG_READ_ERROR
;
242 catch( io::IOException
& )
244 nRet
= ERR_SWG_READ_ERROR
;
247 // and finally, copy macro into table
249 pDescriptor
->copyMacrosIntoTable(rMacroTbl
);
252 nRet
= ERR_SWG_READ_ERROR
;
255 nRet
= ERR_SWG_READ_ERROR
;
257 catch( uno::Exception
& )
259 nRet
= ERR_SWG_READ_ERROR
;
263 nRet
= ERR_SWG_READ_ERROR
;
270 sal_uLong
SwXMLTextBlocks::GetBlockText( const String
& rShort
, String
& rText
)
273 sal_Bool bTextOnly
= sal_True
;
274 String aFolderName
= GeneratePackageName ( rShort
);
275 String aStreamName
= aFolderName
+ OUString(".xml");
280 xRoot
= xBlkRoot
->openStorageElement( aFolderName
, embed::ElementModes::READ
);
281 uno::Reference
< container::XNameAccess
> xAccess( xRoot
, uno::UNO_QUERY
);
282 if ( !xAccess
->hasByName( aStreamName
) || !xRoot
->isStreamElement( aStreamName
) )
284 bTextOnly
= sal_False
;
285 aStreamName
= OUString("content.xml");
288 uno::Reference
< io::XStream
> xContents
= xRoot
->openStreamElement( aStreamName
, embed::ElementModes::READ
);
289 uno::Reference
< uno::XComponentContext
> xContext
=
290 comphelper::getProcessComponentContext();
292 xml::sax::InputSource aParserInput
;
293 aParserInput
.sSystemId
= aName
;
294 aParserInput
.aInputStream
= xContents
->getInputStream();
298 // uno::Reference< xml::sax::XDocumentHandler > xFilter = new SwXMLTextBlockImport( *this, rText, bTextOnly );
299 uno::Reference
< xml::sax::XDocumentHandler
> xFilter
= new SwXMLTextBlockImport( xContext
, *this, rText
, bTextOnly
);
301 // connect parser and filter
302 uno::Reference
< xml::sax::XParser
> xParser
= xml::sax::Parser::create(xContext
);
303 xParser
->setDocumentHandler( xFilter
);
308 xParser
->parseStream( aParserInput
);
310 catch( xml::sax::SAXParseException
& )
314 catch( xml::sax::SAXException
& )
318 catch( io::IOException
& )
325 catch ( uno::Exception
& )
327 OSL_FAIL( "Tried to open non-existent folder or stream!");
333 sal_uLong
SwXMLTextBlocks::PutBlockText( const String
& rShort
, const String
& ,
334 const String
& rText
, const String
& rPackageName
)
338 if (xBlkRoot->IsContained ( rPackageName ) )
340 xBlkRoot->Remove ( rPackageName );
341 xBlkRoot->Commit ( );
344 String
aFolderName( rPackageName
);
345 String aStreamName
= aFolderName
+ OUString(".xml");
347 uno::Reference
< uno::XComponentContext
> xContext
=
348 comphelper::getProcessComponentContext();
350 uno::Reference
< xml::sax::XWriter
> xWriter
= xml::sax::Writer::create(xContext
);
355 xRoot
= xBlkRoot
->openStorageElement( aFolderName
, embed::ElementModes::WRITE
);
356 uno::Reference
< io::XStream
> xDocStream
= xRoot
->openStreamElement( aStreamName
,
357 embed::ElementModes::WRITE
| embed::ElementModes::TRUNCATE
);
359 uno::Reference
< beans::XPropertySet
> xSet( xDocStream
, uno::UNO_QUERY
);
360 OUString
aMime ( "text/xml" );
363 xSet
->setPropertyValue( OUString("MediaType"), aAny
);
364 uno::Reference
< io::XOutputStream
> xOut
= xDocStream
->getOutputStream();
365 uno::Reference
<io::XActiveDataSource
> xSrc(xWriter
, uno::UNO_QUERY
);
366 xSrc
->setOutputStream(xOut
);
368 uno::Reference
<xml::sax::XDocumentHandler
> xHandler(xWriter
,
371 SwXMLTextBlockExport
aExp( xContext
, *this, GetXMLToken ( XML_UNFORMATTED_TEXT
), xHandler
);
373 aExp
.exportDoc( rText
);
375 uno::Reference
< embed::XTransactedObject
> xTrans( xRoot
, uno::UNO_QUERY
);
379 if (! (nFlags
& SWXML_NOROOTCOMMIT
) )
381 uno::Reference
< embed::XTransactedObject
> xTmpTrans( xBlkRoot
, uno::UNO_QUERY
);
382 if ( xTmpTrans
.is() )
386 catch ( uno::Exception
& )
388 nRes
= ERR_SWG_WRITE_ERROR
;
393 //TODO/LATER: error handling
395 sal_uLong nErr = xBlkRoot->GetError();
397 if( nErr == SVSTREAM_DISK_FULL )
398 nRes = ERR_W4W_WRITE_FULL;
399 else if( nErr != SVSTREAM_OK )
400 nRes = ERR_SWG_WRITE_ERROR;
402 if( !nRes
) // damit ueber GetText & nCur aufs Doc zugegriffen
403 MakeBlockText( rText
);
408 void SwXMLTextBlocks::ReadInfo( void )
412 const OUString
sDocName( XMLN_BLOCKLIST
);
413 uno::Reference
< container::XNameAccess
> xAccess( xBlkRoot
, uno::UNO_QUERY
);
414 if ( xAccess
.is() && xAccess
->hasByName( sDocName
) && xBlkRoot
->isStreamElement( sDocName
) )
416 uno::Reference
< uno::XComponentContext
> xContext
=
417 comphelper::getProcessComponentContext();
419 xml::sax::InputSource aParserInput
;
420 aParserInput
.sSystemId
= sDocName
;
422 uno::Reference
< io::XStream
> xDocStream
= xBlkRoot
->openStreamElement( sDocName
, embed::ElementModes::READ
);
423 aParserInput
.aInputStream
= xDocStream
->getInputStream();
426 uno::Reference
< xml::sax::XDocumentHandler
> xFilter
= new SwXMLBlockListImport( xContext
, *this );
428 // connect parser and filter
429 uno::Reference
< xml::sax::XParser
> xParser
= xml::sax::Parser::create( xContext
);
430 xParser
->setDocumentHandler( xFilter
);
435 xParser
->parseStream( aParserInput
);
437 catch( xml::sax::SAXParseException
& )
441 catch( xml::sax::SAXException
& )
445 catch( io::IOException
& )
451 catch ( uno::Exception
& )
455 void SwXMLTextBlocks::WriteInfo( void )
457 if ( xBlkRoot
.is() || 0 == OpenFile ( sal_False
) )
459 uno::Reference
< uno::XComponentContext
> xContext
=
460 comphelper::getProcessComponentContext();
462 uno::Reference
< xml::sax::XWriter
> xWriter
= xml::sax::Writer::create(xContext
);
463 OUString
sDocName( XMLN_BLOCKLIST
);
466 if ( xBlkRoot->IsContained( sDocName) )
468 xBlkRoot->Remove ( sDocName );
475 uno::Reference
< io::XStream
> xDocStream
= xBlkRoot
->openStreamElement( sDocName
,
476 embed::ElementModes::WRITE
| embed::ElementModes::TRUNCATE
);
478 uno::Reference
< beans::XPropertySet
> xSet( xDocStream
, uno::UNO_QUERY
);
479 OUString
aMime ( "text/xml" );
482 xSet
->setPropertyValue( OUString("MediaType"), aAny
);
483 uno::Reference
< io::XOutputStream
> xOut
= xDocStream
->getOutputStream();
484 uno::Reference
<io::XActiveDataSource
> xSrc(xWriter
, uno::UNO_QUERY
);
485 xSrc
->setOutputStream(xOut
);
487 uno::Reference
<xml::sax::XDocumentHandler
> xHandler(xWriter
, uno::UNO_QUERY
);
489 SwXMLBlockListExport
aExp( xContext
, *this, OUString(XMLN_BLOCKLIST
), xHandler
);
491 aExp
.exportDoc( XML_BLOCK_LIST
);
493 uno::Reference
< embed::XTransactedObject
> xTrans( xBlkRoot
, uno::UNO_QUERY
);
497 catch ( uno::Exception
& )
501 bInfoChanged
= sal_False
;
506 sal_uLong
SwXMLTextBlocks::SetMacroTable(
508 const SvxMacroTableDtor
& rMacroTbl
,
509 sal_Bool bFileAlreadyOpen
)
511 // set current autotext
512 aShort
= aNames
[nIdx
]->aShort
;
513 aLong
= aNames
[nIdx
]->aLong
;
514 aPackageName
= aNames
[nIdx
]->aPackageName
;
516 // start XML autotext event export
519 uno::Reference
< uno::XComponentContext
> xContext
=
520 comphelper::getProcessComponentContext();
523 uno::Reference
< lang::XComponent
> xModelComp(
524 pDoc
->GetDocShell()->GetModel(), UNO_QUERY
);
525 OSL_ENSURE( xModelComp
.is(), "XMLWriter::Write: got no model" );
526 if( !xModelComp
.is() )
527 return ERR_SWG_WRITE_ERROR
;
529 // open stream in proper sub-storage
530 if( !bFileAlreadyOpen
)
532 CloseFile(); // close (it may be open in read-only-mode)
533 nRes
= OpenFile ( sal_False
);
540 xRoot
= xBlkRoot
->openStorageElement( aPackageName
, embed::ElementModes::WRITE
);
541 OUString
sStreamName("atevent.xml" );
542 long nTmp
= SOT_FORMATSTR_ID_STARWRITER_60
;
543 bool bOasis
= ( SotStorage::GetVersion( xRoot
) > nTmp
);
545 uno::Reference
< io::XStream
> xDocStream
= xRoot
->openStreamElement( sStreamName
,
546 embed::ElementModes::WRITE
| embed::ElementModes::TRUNCATE
);
548 uno::Reference
< beans::XPropertySet
> xSet( xDocStream
, uno::UNO_QUERY
);
549 OUString
aMime( "text/xml" );
552 xSet
->setPropertyValue( OUString("MediaType"), aAny
);
553 uno::Reference
< io::XOutputStream
> xOutputStream
= xDocStream
->getOutputStream();
556 uno::Reference
< xml::sax::XWriter
> xSaxWriter
=
557 xml::sax::Writer::create( xContext
);
559 // connect XML writer to output stream
560 xSaxWriter
->setOutputStream( xOutputStream
);
561 uno::Reference
<xml::sax::XDocumentHandler
> xDocHandler(
562 xSaxWriter
, UNO_QUERY
);
564 // construct events object
565 uno::Reference
<XNameAccess
> xEvents
=
566 new SvMacroTableEventDescriptor(rMacroTbl
,aAutotextEvents
);
568 // prepare arguments (prepend doc handler to given arguments)
569 Sequence
<Any
> aParams(2);
570 aParams
[0] <<= xDocHandler
;
571 aParams
[1] <<= xEvents
;
574 // get filter component
575 OUString sFilterComponent
= bOasis
576 ? OUString("com.sun.star.comp.Writer.XMLOasisAutotextEventsExporter")
577 : OUString("com.sun.star.comp.Writer.XMLAutotextEventsExporter");
578 uno::Reference
< document::XExporter
> xExporter(
579 xContext
->getServiceManager()->createInstanceWithArgumentsAndContext(
580 sFilterComponent
, aParams
, xContext
), UNO_QUERY
);
581 OSL_ENSURE( xExporter
.is(),
582 "can't instantiate export filter component" );
585 // connect model and filter
586 xExporter
->setSourceDocument( xModelComp
);
589 Sequence
<beans::PropertyValue
> aFilterProps( 0 );
590 uno::Reference
< document::XFilter
> xFilter( xExporter
,
592 xFilter
->filter( aFilterProps
);
595 nRes
= ERR_SWG_WRITE_ERROR
;
597 // finally, commit stream, sub-storage and storage
598 uno::Reference
< embed::XTransactedObject
> xTmpTrans( xRoot
, uno::UNO_QUERY
);
599 if ( xTmpTrans
.is() )
602 if ( !bFileAlreadyOpen
)
604 uno::Reference
< embed::XTransactedObject
> xTrans( xBlkRoot
, uno::UNO_QUERY
);
611 catch ( uno::Exception
& )
613 nRes
= ERR_SWG_WRITE_ERROR
;
616 if( !bFileAlreadyOpen
)
620 nRes
= ERR_SWG_WRITE_ERROR
;
625 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */