LanguageTool: don't crash if REST protocol isn't set
[LibreOffice.git] / sfx2 / source / doc / doctempl.cxx
blobedb401aa73638e6f5b395c3a464a6d1ab7cedb78
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
21 #include <limits.h>
22 #include <string_view>
24 #include <com/sun/star/uno/Any.h>
25 #include <osl/mutex.hxx>
26 #include <sal/log.hxx>
28 #include <unotools/pathoptions.hxx>
29 #include <tools/urlobj.hxx>
30 #include <tools/debug.hxx>
31 #include <tools/diagnose_ex.h>
32 #include <comphelper/processfactory.hxx>
33 #include <comphelper/propertyvalue.hxx>
34 #include <ucbhelper/content.hxx>
35 #include <com/sun/star/beans/PropertyValue.hpp>
36 #include <com/sun/star/beans/XPropertySet.hpp>
37 #include <com/sun/star/beans/XPropertySetInfo.hpp>
38 #include <com/sun/star/document/XTypeDetection.hpp>
39 #include <com/sun/star/document/DocumentProperties.hpp>
40 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
41 #include <com/sun/star/frame/Desktop.hpp>
42 #include <com/sun/star/frame/DocumentTemplates.hpp>
43 #include <com/sun/star/frame/XDocumentTemplates.hpp>
44 #include <com/sun/star/io/IOException.hpp>
45 #include <com/sun/star/io/XPersist.hpp>
46 #include <com/sun/star/lang/XLocalizable.hpp>
47 #include <com/sun/star/sdbc/XResultSet.hpp>
48 #include <com/sun/star/sdbc/XRow.hpp>
49 #include <com/sun/star/ucb/ContentCreationException.hpp>
50 #include <com/sun/star/ucb/NameClash.hpp>
51 #include <com/sun/star/ucb/TransferInfo.hpp>
52 #include <com/sun/star/ucb/XContent.hpp>
53 #include <com/sun/star/ucb/XContentAccess.hpp>
54 #include <com/sun/star/ucb/AnyCompareFactory.hpp>
55 #include <com/sun/star/ucb/NumberedSortingInfo.hpp>
57 #include "doctemplateslocal.hxx"
58 #include <sfxurlrelocator.hxx>
60 using namespace ::com::sun::star;
61 using namespace ::com::sun::star::beans;
62 using namespace ::com::sun::star::frame;
63 using namespace ::com::sun::star::io;
64 using namespace ::com::sun::star::lang;
65 using namespace ::com::sun::star::sdbc;
66 using namespace ::com::sun::star::uno;
67 using namespace ::com::sun::star::ucb;
68 using namespace ::com::sun::star::document;
69 using namespace ::rtl;
70 using namespace ::ucbhelper;
73 #include <sfx2/doctempl.hxx>
74 #include <sfx2/objsh.hxx>
75 #include <sfx2/sfxresid.hxx>
76 #include <sfx2/strings.hrc>
77 #include <strings.hxx>
78 #include <svtools/templatefoldercache.hxx>
80 #include <memory>
81 #include <vector>
84 constexpr OUStringLiteral TITLE = u"Title";
85 constexpr OUStringLiteral TARGET_URL = u"TargetURL";
87 constexpr OUStringLiteral COMMAND_TRANSFER = u"transfer";
89 namespace {
91 class RegionData_Impl;
95 namespace DocTempl {
97 namespace {
99 class DocTempl_EntryData_Impl
101 RegionData_Impl* mpParent;
103 // the following member must be SfxObjectShellLock since it controls that SfxObjectShell lifetime by design
104 // and users of this class expect it to be so.
105 SfxObjectShellLock mxObjShell;
107 OUString maTitle;
108 OUString maOwnURL;
109 OUString maTargetURL;
111 public:
112 DocTempl_EntryData_Impl( RegionData_Impl* pParent,
113 const OUString& rTitle );
115 const OUString& GetTitle() const { return maTitle; }
116 const OUString& GetTargetURL();
117 const OUString& GetHierarchyURL();
119 void SetTitle( const OUString& rTitle ) { maTitle = rTitle; }
120 void SetTargetURL( const OUString& rURL ) { maTargetURL = rURL; }
121 void SetHierarchyURL( const OUString& rURL) { maOwnURL = rURL; }
123 int Compare( std::u16string_view rTitle ) const;
130 using namespace ::DocTempl;
132 namespace {
134 class RegionData_Impl
136 const SfxDocTemplate_Impl* mpParent;
137 std::vector<std::unique_ptr<DocTempl_EntryData_Impl>> maEntries;
138 OUString maTitle;
139 OUString maOwnURL;
141 private:
142 size_t GetEntryPos( std::u16string_view rTitle,
143 bool& rFound ) const;
145 public:
146 RegionData_Impl( const SfxDocTemplate_Impl* pParent,
147 const OUString& rTitle );
149 void SetHierarchyURL( const OUString& rURL) { maOwnURL = rURL; }
151 DocTempl_EntryData_Impl* GetEntry( size_t nIndex ) const;
152 DocTempl_EntryData_Impl* GetEntry( std::u16string_view rName ) const;
154 const OUString& GetTitle() const { return maTitle; }
155 const OUString& GetHierarchyURL();
157 size_t GetCount() const;
159 void SetTitle( const OUString& rTitle ) { maTitle = rTitle; }
161 void AddEntry( const OUString& rTitle,
162 const OUString& rTargetURL,
163 const size_t *pPos );
164 void DeleteEntry( size_t nIndex );
166 int Compare( RegionData_Impl const * pCompareWith ) const;
171 class SfxDocTemplate_Impl : public SvRefBase
173 uno::Reference< XPersist > mxInfo;
174 uno::Reference< XDocumentTemplates > mxTemplates;
176 ::osl::Mutex maMutex;
177 OUString maRootURL;
178 OUString maStandardGroup;
179 std::vector<std::unique_ptr<RegionData_Impl>> maRegions;
180 bool mbConstructed;
182 uno::Reference< XAnyCompareFactory > m_rCompareFactory;
184 // the following member is intended to prevent clearing of the global data when it is in use
185 // TODO/LATER: it still does not make the implementation complete thread-safe
186 sal_Int32 mnLockCounter;
188 private:
189 void Clear();
191 public:
192 SfxDocTemplate_Impl();
193 virtual ~SfxDocTemplate_Impl() override;
195 void IncrementLock();
196 void DecrementLock();
198 bool Construct( );
199 void CreateFromHierarchy( Content &rTemplRoot );
200 void ReInitFromComponent();
201 void AddRegion( const OUString& rTitle,
202 Content& rContent );
204 void Rescan();
206 void DeleteRegion( size_t nIndex );
208 size_t GetRegionCount() const
209 { return maRegions.size(); }
210 RegionData_Impl* GetRegion( std::u16string_view rName ) const;
211 RegionData_Impl* GetRegion( size_t nIndex ) const;
213 bool GetTitleFromURL( const OUString& rURL, OUString& aTitle );
214 bool InsertRegion( std::unique_ptr<RegionData_Impl> pData, size_t nPos );
215 const OUString& GetRootURL() const { return maRootURL; }
217 const uno::Reference< XDocumentTemplates >& getDocTemplates() const { return mxTemplates; }
220 namespace {
222 class DocTemplLocker_Impl
224 SfxDocTemplate_Impl& m_aDocTempl;
225 public:
226 explicit DocTemplLocker_Impl( SfxDocTemplate_Impl& aDocTempl )
227 : m_aDocTempl( aDocTempl )
229 m_aDocTempl.IncrementLock();
232 ~DocTemplLocker_Impl()
234 m_aDocTempl.DecrementLock();
240 static SfxDocTemplate_Impl *gpTemplateData = nullptr;
243 static bool getTextProperty_Impl( Content& rContent,
244 const OUString& rPropName,
245 OUString& rPropValue );
248 OUString SfxDocumentTemplates::GetFullRegionName
250 sal_uInt16 nIdx // Region Index
251 ) const
253 /* [Description]
255 Returns the logical name of a region and its path
257 [Return value] Reference to the Region name
262 // First: find the RegionData for the index
264 DocTemplLocker_Impl aLocker( *pImp );
266 if ( pImp->Construct() )
268 RegionData_Impl *pData1 = pImp->GetRegion( nIdx );
270 if ( pData1 )
271 return pData1->GetTitle();
273 // --**-- here was some code which appended the path to the
274 // group if there was more than one with the same name.
275 // this should not happen anymore
278 return OUString();
282 OUString SfxDocumentTemplates::GetRegionName
284 sal_uInt16 nIdx // Region Index
285 ) const
287 /* [Description]
289 Returns the logical name of a region
291 [Return value]
293 const String& Reference to the Region name
297 DocTemplLocker_Impl aLocker( *pImp );
299 if ( pImp->Construct() )
301 RegionData_Impl *pData = pImp->GetRegion( nIdx );
303 if ( pData )
304 return pData->GetTitle();
307 return OUString();
311 sal_uInt16 SfxDocumentTemplates::GetRegionCount() const
313 /* [Description]
315 Returns the number of Regions
317 [Return value]
319 sal_uInt16 Number of Regions
322 DocTemplLocker_Impl aLocker( *pImp );
324 if ( !pImp->Construct() )
325 return 0;
327 return pImp->GetRegionCount();
331 sal_uInt16 SfxDocumentTemplates::GetCount
333 sal_uInt16 nRegion /* Region index whose number is
334 to be determined */
336 ) const
338 /* [Description]
340 Number of entries in Region
342 [Return value] Number of entries
346 DocTemplLocker_Impl aLocker( *pImp );
348 if ( !pImp->Construct() )
349 return 0;
351 RegionData_Impl *pData = pImp->GetRegion( nRegion );
353 if ( !pData )
354 return 0;
356 return pData->GetCount();
360 OUString SfxDocumentTemplates::GetName
362 sal_uInt16 nRegion, // Region Index, in which the entry lies
363 sal_uInt16 nIdx // Index of the entry
364 ) const
366 /* [Description]
368 Returns the logical name of an entry in Region
370 [Return value]
372 const String& Entry Name
376 DocTemplLocker_Impl aLocker( *pImp );
378 if ( pImp->Construct() )
380 RegionData_Impl *pRegion = pImp->GetRegion( nRegion );
382 if ( pRegion )
384 DocTempl_EntryData_Impl *pEntry = pRegion->GetEntry( nIdx );
385 if ( pEntry )
386 return pEntry->GetTitle();
390 return OUString();
394 OUString SfxDocumentTemplates::GetPath
396 sal_uInt16 nRegion, // Region Index, in which the entry lies
397 sal_uInt16 nIdx // Index of the entry
398 ) const
400 /* [Description]
402 Returns the file name with full path to the file assigned to an entry
404 [Return value]
406 String File name with full path
409 DocTemplLocker_Impl aLocker( *pImp );
411 if ( !pImp->Construct() )
412 return OUString();
414 RegionData_Impl *pRegion = pImp->GetRegion( nRegion );
416 if ( pRegion )
418 DocTempl_EntryData_Impl *pEntry = pRegion->GetEntry( nIdx );
419 if ( pEntry )
420 return pEntry->GetTargetURL();
423 return OUString();
427 OUString SfxDocumentTemplates::GetTemplateTargetURLFromComponent( std::u16string_view aGroupName,
428 std::u16string_view aTitle )
430 DocTemplLocker_Impl aLocker( *pImp );
432 INetURLObject aTemplateObj( pImp->GetRootURL() );
434 aTemplateObj.insertName( aGroupName, false,
435 INetURLObject::LAST_SEGMENT,
436 INetURLObject::EncodeMechanism::All );
438 aTemplateObj.insertName( aTitle, false,
439 INetURLObject::LAST_SEGMENT,
440 INetURLObject::EncodeMechanism::All );
443 Content aTemplate;
444 uno::Reference< XCommandEnvironment > aCmdEnv;
445 if ( Content::create( aTemplateObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ), aCmdEnv, comphelper::getProcessComponentContext(), aTemplate ) )
447 OUString aResult;
448 getTextProperty_Impl( aTemplate, TARGET_URL, aResult );
449 return SvtPathOptions().SubstituteVariable( aResult );
452 return OUString();
456 /** Convert a template name to its localised pair if it exists.
457 @param rString
458 Name to be translated.
459 @return
460 The localised pair of rString or rString if the former does not exist.
462 OUString SfxDocumentTemplates::ConvertResourceString(const OUString& rString)
464 static const std::u16string_view aTemplateNames[] =
466 u"" STR_TEMPLATE_NAME1_DEF,
467 u"" STR_TEMPLATE_NAME2_DEF,
468 u"" STR_TEMPLATE_NAME3_DEF,
469 u"" STR_TEMPLATE_NAME4_DEF,
470 u"" STR_TEMPLATE_NAME5_DEF,
471 u"" STR_TEMPLATE_NAME6_DEF,
472 u"" STR_TEMPLATE_NAME7_DEF,
473 u"" STR_TEMPLATE_NAME8_DEF,
474 u"" STR_TEMPLATE_NAME9_DEF,
475 u"" STR_TEMPLATE_NAME10_DEF,
476 u"" STR_TEMPLATE_NAME11_DEF,
477 u"" STR_TEMPLATE_NAME12_DEF,
478 u"" STR_TEMPLATE_NAME13_DEF,
479 u"" STR_TEMPLATE_NAME14_DEF,
480 u"" STR_TEMPLATE_NAME15_DEF,
481 u"" STR_TEMPLATE_NAME16_DEF,
482 u"" STR_TEMPLATE_NAME17_DEF,
483 u"" STR_TEMPLATE_NAME18_DEF,
484 u"" STR_TEMPLATE_NAME19_DEF,
485 u"" STR_TEMPLATE_NAME20_DEF,
486 u"" STR_TEMPLATE_NAME21_DEF,
487 u"" STR_TEMPLATE_NAME22_DEF,
488 u"" STR_TEMPLATE_NAME23_DEF,
489 u"" STR_TEMPLATE_NAME24_DEF,
490 u"" STR_TEMPLATE_NAME25_DEF,
491 u"" STR_TEMPLATE_NAME26_DEF,
492 u"" STR_TEMPLATE_NAME27_DEF,
493 u"" STR_TEMPLATE_NAME28_DEF,
494 u"" STR_TEMPLATE_NAME29_DEF,
495 u"" STR_TEMPLATE_NAME30_DEF,
496 u"" STR_TEMPLATE_NAME31_DEF,
497 u"" STR_TEMPLATE_NAME32_DEF,
500 TranslateId STR_TEMPLATE_NAME[] =
502 STR_TEMPLATE_NAME1,
503 STR_TEMPLATE_NAME2,
504 STR_TEMPLATE_NAME3,
505 STR_TEMPLATE_NAME4,
506 STR_TEMPLATE_NAME5,
507 STR_TEMPLATE_NAME6,
508 STR_TEMPLATE_NAME7,
509 STR_TEMPLATE_NAME8,
510 STR_TEMPLATE_NAME9,
511 STR_TEMPLATE_NAME10,
512 STR_TEMPLATE_NAME11,
513 STR_TEMPLATE_NAME12,
514 STR_TEMPLATE_NAME13,
515 STR_TEMPLATE_NAME14,
516 STR_TEMPLATE_NAME15,
517 STR_TEMPLATE_NAME16,
518 STR_TEMPLATE_NAME17,
519 STR_TEMPLATE_NAME18,
520 STR_TEMPLATE_NAME19,
521 STR_TEMPLATE_NAME20,
522 STR_TEMPLATE_NAME21,
523 STR_TEMPLATE_NAME22,
524 STR_TEMPLATE_NAME23,
525 STR_TEMPLATE_NAME24,
526 STR_TEMPLATE_NAME25,
527 STR_TEMPLATE_NAME26,
528 STR_TEMPLATE_NAME27,
529 STR_TEMPLATE_NAME28,
530 STR_TEMPLATE_NAME29,
531 STR_TEMPLATE_NAME30,
532 STR_TEMPLATE_NAME31,
533 STR_TEMPLATE_NAME32,
536 static_assert(SAL_N_ELEMENTS(aTemplateNames) == SAL_N_ELEMENTS(STR_TEMPLATE_NAME));
538 for (size_t i = 0; i < SAL_N_ELEMENTS(STR_TEMPLATE_NAME); ++i)
540 if (rString == aTemplateNames[i])
541 return SfxResId(STR_TEMPLATE_NAME[i]);
543 return rString;
547 bool SfxDocumentTemplates::CopyOrMove
549 sal_uInt16 nTargetRegion, // Target Region Index
550 sal_uInt16 nTargetIdx, // Target position Index
551 sal_uInt16 nSourceRegion, // Source Region Index
552 sal_uInt16 nSourceIdx, /* Index to be copied / to moved template */
553 bool bMove // Copy / Move
556 /* [Description]
558 Copy or move a document template
560 [Return value]
562 sal_Bool sal_True, Action could be performed
563 sal_False, Action could not be performed
565 [Cross-references]
567 <SfxDocumentTemplates::Move(sal_uInt16,sal_uInt16,sal_uInt16,sal_uInt16)>
568 <SfxDocumentTemplates::Copy(sal_uInt16,sal_uInt16,sal_uInt16,sal_uInt16)>
572 /* to perform a copy or move, we need to send a transfer command to
573 the destination folder with the URL of the source as parameter.
574 ( If the destination content doesn't support the transfer command,
575 we could try a copy ( and delete ) instead. )
576 We need two transfers ( one for the real template and one for its
577 representation in the hierarchy )
581 DocTemplLocker_Impl aLocker( *pImp );
583 if ( !pImp->Construct() )
584 return false;
586 // Don't copy or move any folders
587 if( nSourceIdx == USHRT_MAX )
588 return false ;
590 if ( nSourceRegion == nTargetRegion )
592 SAL_WARN( "sfx.doc", "Don't know, what to do!" );
593 return false;
596 RegionData_Impl *pSourceRgn = pImp->GetRegion( nSourceRegion );
597 if ( !pSourceRgn )
598 return false;
600 DocTempl_EntryData_Impl *pSource = pSourceRgn->GetEntry( nSourceIdx );
601 if ( !pSource )
602 return false;
604 RegionData_Impl *pTargetRgn = pImp->GetRegion( nTargetRegion );
605 if ( !pTargetRgn )
606 return false;
608 const OUString aTitle = pSource->GetTitle();
610 uno::Reference< XDocumentTemplates > xTemplates = pImp->getDocTemplates();
612 if ( xTemplates->addTemplate( pTargetRgn->GetTitle(),
613 aTitle,
614 pSource->GetTargetURL() ) )
616 const OUString aNewTargetURL = GetTemplateTargetURLFromComponent( pTargetRgn->GetTitle(), aTitle );
617 if ( aNewTargetURL.isEmpty() )
618 return false;
620 if ( bMove )
622 // --**-- delete the original file
623 bool bDeleted = xTemplates->removeTemplate( pSourceRgn->GetTitle(),
624 pSource->GetTitle() );
625 if ( bDeleted )
626 pSourceRgn->DeleteEntry( nSourceIdx );
627 else
629 if ( xTemplates->removeTemplate( pTargetRgn->GetTitle(), aTitle ) )
630 return false; // will trigger retry with copy instead of move
632 // if it is not possible to remove just created template ( must be possible! )
633 // it is better to report success here, since at least the copy has succeeded
634 // TODO/LATER: solve it more gracefully in future
638 // todo: fix SfxDocumentTemplates to handle size_t instead of sal_uInt16
639 size_t temp_nTargetIdx = nTargetIdx;
640 pTargetRgn->AddEntry( aTitle, aNewTargetURL, &temp_nTargetIdx );
642 return true;
645 // --**-- if the current file is opened,
646 // it must be re-opened afterwards.
648 return false;
652 bool SfxDocumentTemplates::Move
654 sal_uInt16 nTargetRegion, // Target Region Index
655 sal_uInt16 nTargetIdx, // Target position Index
656 sal_uInt16 nSourceRegion, // Source Region Index
657 sal_uInt16 nSourceIdx /* Index to be copied / to moved template */
660 /* [Description]
662 Moving a template
664 [Return value]
666 sal_Bool sal_True, Action could be performed
667 sal_False, Action could not be performed
669 [Cross-references]
671 <SfxDocumentTemplates::CopyOrMove(sal_uInt16,sal_uInt16,sal_uInt16,sal_uInt16,sal_Bool)>
674 DocTemplLocker_Impl aLocker( *pImp );
676 return CopyOrMove( nTargetRegion, nTargetIdx,
677 nSourceRegion, nSourceIdx, true );
681 bool SfxDocumentTemplates::Copy
683 sal_uInt16 nTargetRegion, // Target Region Index
684 sal_uInt16 nTargetIdx, // Target position Index
685 sal_uInt16 nSourceRegion, // Source Region Index
686 sal_uInt16 nSourceIdx /* Index to be copied / to moved template */
689 /* [Description]
691 Copying a template
693 [Return value]
695 sal_Bool sal_True, Action could be performed
696 sal_False, Action could not be performed
698 [Cross-references]
700 <SfxDocumentTemplates::CopyOrMove(sal_uInt16,sal_uInt16,sal_uInt16,sal_uInt16,sal_Bool)>
704 DocTemplLocker_Impl aLocker( *pImp );
706 return CopyOrMove( nTargetRegion, nTargetIdx,
707 nSourceRegion, nSourceIdx, false );
711 bool SfxDocumentTemplates::CopyTo
713 sal_uInt16 nRegion, // Region of the template to be exported
714 sal_uInt16 nIdx, // Index of the template to be exported
715 const OUString& rName /* File name under which the template is to
716 be created */
717 ) const
719 /* [Description]
721 Exporting a template into the file system
723 [Return value]
725 sal_Bool sal_True, Action could be performed
726 sal_False, Action could not be performed
728 [Cross-references]
730 <SfxDocumentTemplates::CopyFrom(sal_uInt16,sal_uInt16,String&)>
734 DocTemplLocker_Impl aLocker( *pImp );
736 if ( ! pImp->Construct() )
737 return false;
739 RegionData_Impl *pSourceRgn = pImp->GetRegion( nRegion );
740 if ( !pSourceRgn )
741 return false;
743 DocTempl_EntryData_Impl *pSource = pSourceRgn->GetEntry( nIdx );
744 if ( !pSource )
745 return false;
747 INetURLObject aTargetURL( rName );
749 const OUString aTitle( aTargetURL.getName( INetURLObject::LAST_SEGMENT, true,
750 INetURLObject::DecodeMechanism::WithCharset ) );
751 aTargetURL.removeSegment();
753 const OUString aParentURL = aTargetURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
755 uno::Reference< XCommandEnvironment > aCmdEnv;
756 Content aTarget;
760 aTarget = Content( aParentURL, aCmdEnv, comphelper::getProcessComponentContext() );
762 TransferInfo aTransferInfo;
763 aTransferInfo.MoveData = false;
764 aTransferInfo.SourceURL = pSource->GetTargetURL();
765 aTransferInfo.NewTitle = aTitle;
766 aTransferInfo.NameClash = NameClash::RENAME;
768 Any aArg = makeAny( aTransferInfo );
769 aTarget.executeCommand( COMMAND_TRANSFER, aArg );
771 catch ( ContentCreationException& )
772 { return false; }
773 catch ( Exception& )
774 { return false; }
776 return true;
780 bool SfxDocumentTemplates::CopyFrom
782 sal_uInt16 nRegion, /* Region in which the template is to be
783 imported */
784 sal_uInt16 nIdx, // Index of the new template in this Region
785 OUString& rName /* File name of the template to be imported
786 as an out parameter of the (automatically
787 generated from the file name) logical name
788 of the template */
791 /* [Description]
793 Import a template from the file system
795 [Return value] Success (sal_True) or serfpTargetDirectory->GetContent());
797 sal_Bool sal_True, Action could be performed
798 sal_False, Action could not be performed
800 [Cross-references]
802 <SfxDocumentTemplates::CopyTo(sal_uInt16,sal_uInt16,const String&)>
806 DocTemplLocker_Impl aLocker( *pImp );
808 if ( ! pImp->Construct() )
809 return false;
811 RegionData_Impl *pTargetRgn = pImp->GetRegion( nRegion );
813 if ( !pTargetRgn )
814 return false;
816 uno::Reference< XDocumentTemplates > xTemplates = pImp->getDocTemplates();
817 if ( !xTemplates.is() )
818 return false;
820 OUString aTitle;
821 bool bTemplateAdded = false;
823 if( pImp->GetTitleFromURL( rName, aTitle ) )
825 bTemplateAdded = xTemplates->addTemplate( pTargetRgn->GetTitle(), aTitle, rName );
827 else
829 uno::Reference< XDesktop2 > xDesktop = Desktop::create( ::comphelper::getProcessComponentContext() );
831 Sequence< PropertyValue > aArgs{ comphelper::makePropertyValue("Hidden", true) };
833 INetURLObject aTemplURL( rName );
834 uno::Reference< XDocumentPropertiesSupplier > xDocPropsSupplier;
835 uno::Reference< XStorable > xStorable;
838 xStorable.set(
839 xDesktop->loadComponentFromURL( aTemplURL.GetMainURL(INetURLObject::DecodeMechanism::NONE),
840 "_blank",
842 aArgs ),
843 UNO_QUERY );
845 xDocPropsSupplier.set( xStorable, UNO_QUERY );
847 catch( Exception& )
851 if( xStorable.is() )
853 // get Title from XDocumentPropertiesSupplier
854 if( xDocPropsSupplier.is() )
856 uno::Reference< XDocumentProperties > xDocProps
857 = xDocPropsSupplier->getDocumentProperties();
858 if (xDocProps.is() ) {
859 aTitle = xDocProps->getTitle();
863 if( aTitle.isEmpty() )
865 INetURLObject aURL( aTemplURL );
866 aURL.CutExtension();
867 aTitle = aURL.getName( INetURLObject::LAST_SEGMENT, true,
868 INetURLObject::DecodeMechanism::WithCharset );
871 // write a template using XStorable interface
872 bTemplateAdded = xTemplates->storeTemplate( pTargetRgn->GetTitle(), aTitle, xStorable );
877 if( bTemplateAdded )
879 INetURLObject aTemplObj( pTargetRgn->GetHierarchyURL() );
880 aTemplObj.insertName( aTitle, false,
881 INetURLObject::LAST_SEGMENT,
882 INetURLObject::EncodeMechanism::All );
883 const OUString aTemplURL = aTemplObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
885 uno::Reference< XCommandEnvironment > aCmdEnv;
886 Content aTemplCont;
888 if( Content::create( aTemplURL, aCmdEnv, comphelper::getProcessComponentContext(), aTemplCont ) )
890 OUString aTemplName;
891 if( getTextProperty_Impl( aTemplCont, TARGET_URL, aTemplName ) )
893 if ( nIdx == USHRT_MAX )
894 nIdx = 0;
895 else
896 ++nIdx;
898 // todo: fix SfxDocumentTemplates to handle size_t instead of sal_uInt16
899 size_t temp_nIdx = nIdx;
900 pTargetRgn->AddEntry( aTitle, aTemplName, &temp_nIdx );
901 rName = aTitle;
902 return true;
904 else
906 SAL_WARN( "sfx.doc", "CopyFrom(): The content should contain target URL!" );
909 else
911 SAL_WARN( "sfx.doc", "CopyFrom(): The content just was created!" );
915 return false;
919 bool SfxDocumentTemplates::Delete
921 sal_uInt16 nRegion, // Region Index
922 sal_uInt16 nIdx /* Index of the entry or USHRT_MAX,
923 if a directory is meant. */
926 /* [Description]
928 Deleting an entry or a directory
930 [Return value]
932 sal_Bool sal_True, Action could be performed
933 sal_False, Action could not be performed
935 [Cross-references]
937 <SfxDocumentTemplates::InsertDir(const String&,sal_uInt16)>
938 <SfxDocumentTemplates::KillDir(SfxTemplateDir&)>
942 DocTemplLocker_Impl aLocker( *pImp );
944 /* delete the template or folder in the hierarchy and in the
945 template folder by sending a delete command to the content.
946 Then remove the data from the lists
948 if ( ! pImp->Construct() )
949 return false;
951 RegionData_Impl *pRegion = pImp->GetRegion( nRegion );
953 if ( !pRegion )
954 return false;
956 bool bRet;
957 uno::Reference< XDocumentTemplates > xTemplates = pImp->getDocTemplates();
959 if ( nIdx == USHRT_MAX )
961 bRet = xTemplates->removeGroup( pRegion->GetTitle() );
962 if ( bRet )
963 pImp->DeleteRegion( nRegion );
965 else
967 DocTempl_EntryData_Impl *pEntry = pRegion->GetEntry( nIdx );
969 if ( !pEntry )
970 return false;
972 bRet = xTemplates->removeTemplate( pRegion->GetTitle(),
973 pEntry->GetTitle() );
974 if( bRet )
975 pRegion->DeleteEntry( nIdx );
978 return bRet;
982 bool SfxDocumentTemplates::InsertDir
984 const OUString& rText, // the logical name of the new Region
985 sal_uInt16 nRegion // Region Index
988 /* [Description]
990 Insert an index
992 [Return value]
994 sal_Bool sal_True, Action could be performed
995 sal_False, Action could not be performed
997 [Cross-references]
999 <SfxDocumentTemplates::KillDir(SfxTemplateDir&)>
1002 DocTemplLocker_Impl aLocker( *pImp );
1004 if ( ! pImp->Construct() )
1005 return false;
1007 RegionData_Impl *pRegion = pImp->GetRegion( rText );
1009 if ( pRegion )
1010 return false;
1012 uno::Reference< XDocumentTemplates > xTemplates = pImp->getDocTemplates();
1014 if ( xTemplates->addGroup( rText ) )
1016 return pImp->InsertRegion( std::make_unique<RegionData_Impl>( pImp.get(), rText ), nRegion );
1019 return false;
1022 bool SfxDocumentTemplates::InsertTemplate(sal_uInt16 nSourceRegion, sal_uInt16 nIdx, const OUString &rName, const OUString &rPath)
1024 DocTemplLocker_Impl aLocker( *pImp );
1026 if ( ! pImp->Construct() )
1027 return false;
1029 RegionData_Impl *pRegion = pImp->GetRegion( nSourceRegion );
1031 if ( !pRegion )
1032 return false;
1034 size_t pos = nIdx;
1035 pRegion->AddEntry( rName, rPath, &pos );
1037 return true;
1040 bool SfxDocumentTemplates::SetName( const OUString& rName, sal_uInt16 nRegion, sal_uInt16 nIdx )
1043 DocTemplLocker_Impl aLocker( *pImp );
1045 if ( ! pImp->Construct() )
1046 return false;
1048 RegionData_Impl *pRegion = pImp->GetRegion( nRegion );
1050 if ( !pRegion )
1051 return false;
1053 uno::Reference< XDocumentTemplates > xTemplates = pImp->getDocTemplates();
1055 if ( nIdx == USHRT_MAX )
1057 if ( pRegion->GetTitle() == rName )
1058 return true;
1060 // we have to rename a region
1061 if ( xTemplates->renameGroup( pRegion->GetTitle(), rName ) )
1063 pRegion->SetTitle( rName );
1064 pRegion->SetHierarchyURL( "" );
1065 return true;
1068 else
1070 DocTempl_EntryData_Impl *pEntry = pRegion->GetEntry( nIdx );
1072 if ( !pEntry )
1073 return false;
1075 if ( pEntry->GetTitle() == rName )
1076 return true;
1078 if ( xTemplates->renameTemplate( pRegion->GetTitle(),
1079 pEntry->GetTitle(),
1080 rName ) )
1082 pEntry->SetTitle( rName );
1083 pEntry->SetTargetURL( "" );
1084 pEntry->SetHierarchyURL( "" );
1085 return true;
1089 return false;
1093 bool SfxDocumentTemplates::GetFull
1095 std::u16string_view rRegion, // Region Name
1096 std::u16string_view rName, // Template Name
1097 OUString &rPath // Out: Path + File name
1100 /* [Description]
1102 Returns Path + File name of the template specified by rRegion and rName.
1104 [Return value]
1106 sal_Bool sal_True, Action could be performed
1107 sal_False, Action could not be performed
1109 [Cross-references]
1111 <SfxDocumentTemplates::GetLogicNames(const String&,String&,String&)>
1115 DocTemplLocker_Impl aLocker( *pImp );
1117 // We don't search for empty names!
1118 if ( rName.empty() )
1119 return false;
1121 if ( ! pImp->Construct() )
1122 return false;
1124 DocTempl_EntryData_Impl* pEntry = nullptr;
1125 const sal_uInt16 nCount = GetRegionCount();
1127 for ( sal_uInt16 i = 0; i < nCount; ++i )
1129 RegionData_Impl *pRegion = pImp->GetRegion( i );
1131 if( pRegion &&
1132 ( rRegion.empty() || ( rRegion == pRegion->GetTitle() ) ) )
1134 pEntry = pRegion->GetEntry( rName );
1136 if ( pEntry )
1138 rPath = pEntry->GetTargetURL();
1139 break;
1144 return ( pEntry != nullptr );
1148 bool SfxDocumentTemplates::GetLogicNames
1150 const OUString &rPath, // Full Path to the template
1151 OUString &rRegion, // Out: Region name
1152 OUString &rName // Out: Template name
1153 ) const
1155 /* [Description]
1157 Returns and logical path name to the template specified by rPath
1159 [Return value]
1161 sal_Bool sal_True, Action could be performed
1162 sal_False, Action could not be performed
1164 [Cross-references]
1166 <SfxDocumentTemplates::GetFull(const String&,const String&,DirEntry&)>
1170 DocTemplLocker_Impl aLocker( *pImp );
1172 if ( ! pImp->Construct() )
1173 return false;
1175 INetURLObject aFullPath;
1177 aFullPath.SetSmartProtocol( INetProtocol::File );
1178 aFullPath.SetURL( rPath );
1179 const OUString aPath( aFullPath.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
1181 const sal_uInt16 nCount = GetRegionCount();
1183 for ( sal_uInt16 i=0; i<nCount; ++i )
1185 RegionData_Impl *pData = pImp->GetRegion( i );
1186 if ( pData )
1188 const sal_uInt16 nChildCount = pData->GetCount();
1190 for ( sal_uInt16 j=0; j<nChildCount; ++j )
1192 DocTempl_EntryData_Impl *pEntry = pData->GetEntry( j );
1193 if ( pEntry && pEntry->GetTargetURL() == aPath )
1195 rRegion = pData->GetTitle();
1196 rName = pEntry->GetTitle();
1197 return true;
1203 return false;
1207 SfxDocumentTemplates::SfxDocumentTemplates()
1209 /* [Description]
1211 Constructor
1214 if ( !gpTemplateData )
1215 gpTemplateData = new SfxDocTemplate_Impl;
1217 pImp = gpTemplateData;
1221 SfxDocumentTemplates::~SfxDocumentTemplates()
1223 /* [Description]
1225 Destructor
1226 Release of administrative data
1230 pImp = nullptr;
1233 void SfxDocumentTemplates::Update( )
1235 if ( ::svt::TemplateFolderCache( true ).needsUpdate() ) // update is really necessary
1237 if ( pImp->Construct() )
1238 pImp->Rescan();
1242 void SfxDocumentTemplates::ReInitFromComponent()
1244 pImp->ReInitFromComponent();
1247 DocTempl_EntryData_Impl::DocTempl_EntryData_Impl( RegionData_Impl* pParent,
1248 const OUString& rTitle )
1250 mpParent = pParent;
1251 maTitle = SfxDocumentTemplates::ConvertResourceString(rTitle);
1255 int DocTempl_EntryData_Impl::Compare( std::u16string_view rTitle ) const
1257 return maTitle.compareTo( rTitle );
1261 const OUString& DocTempl_EntryData_Impl::GetHierarchyURL()
1263 if ( maOwnURL.isEmpty() )
1265 INetURLObject aTemplateObj( mpParent->GetHierarchyURL() );
1267 aTemplateObj.insertName( GetTitle(), false,
1268 INetURLObject::LAST_SEGMENT,
1269 INetURLObject::EncodeMechanism::All );
1271 maOwnURL = aTemplateObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1272 DBG_ASSERT( !maOwnURL.isEmpty(), "GetHierarchyURL(): Could not create URL!" );
1275 return maOwnURL;
1279 const OUString& DocTempl_EntryData_Impl::GetTargetURL()
1281 if ( maTargetURL.isEmpty() )
1283 uno::Reference< XCommandEnvironment > aCmdEnv;
1284 Content aRegion;
1286 if ( Content::create( GetHierarchyURL(), aCmdEnv, comphelper::getProcessComponentContext(), aRegion ) )
1288 getTextProperty_Impl( aRegion, TARGET_URL, maTargetURL );
1290 else
1292 SAL_WARN( "sfx.doc", "GetTargetURL(): Could not create hierarchy content!" );
1296 return maTargetURL;
1300 RegionData_Impl::RegionData_Impl( const SfxDocTemplate_Impl* pParent,
1301 const OUString& rTitle )
1302 : mpParent(pParent), maTitle(rTitle)
1307 size_t RegionData_Impl::GetEntryPos( std::u16string_view rTitle, bool& rFound ) const
1309 const size_t nCount = maEntries.size();
1311 for ( size_t i=0; i<nCount; ++i )
1313 auto &pData = maEntries[ i ];
1315 if ( pData->Compare( rTitle ) == 0 )
1317 rFound = true;
1318 return i;
1322 rFound = false;
1323 return nCount;
1327 void RegionData_Impl::AddEntry( const OUString& rTitle,
1328 const OUString& rTargetURL,
1329 const size_t *pPos )
1331 INetURLObject aLinkObj( GetHierarchyURL() );
1332 aLinkObj.insertName( rTitle, false,
1333 INetURLObject::LAST_SEGMENT,
1334 INetURLObject::EncodeMechanism::All );
1335 const OUString aLinkURL = aLinkObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1337 bool bFound = false;
1338 size_t nPos = GetEntryPos( rTitle, bFound );
1340 if ( bFound )
1341 return;
1343 if ( pPos )
1344 nPos = *pPos;
1346 auto pEntry = std::make_unique<DocTempl_EntryData_Impl>(
1347 this, rTitle );
1348 pEntry->SetTargetURL( rTargetURL );
1349 pEntry->SetHierarchyURL( aLinkURL );
1350 if ( nPos < maEntries.size() ) {
1351 auto it = maEntries.begin();
1352 std::advance( it, nPos );
1353 maEntries.insert( it, std::move(pEntry) );
1355 else
1356 maEntries.push_back( std::move(pEntry) );
1360 size_t RegionData_Impl::GetCount() const
1362 return maEntries.size();
1366 const OUString& RegionData_Impl::GetHierarchyURL()
1368 if ( maOwnURL.isEmpty() )
1370 INetURLObject aRegionObj( mpParent->GetRootURL() );
1372 aRegionObj.insertName( GetTitle(), false,
1373 INetURLObject::LAST_SEGMENT,
1374 INetURLObject::EncodeMechanism::All );
1376 maOwnURL = aRegionObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1377 DBG_ASSERT( !maOwnURL.isEmpty(), "GetHierarchyURL(): Could not create URL!" );
1380 return maOwnURL;
1384 DocTempl_EntryData_Impl* RegionData_Impl::GetEntry( std::u16string_view rName ) const
1386 bool bFound = false;
1387 tools::Long nPos = GetEntryPos( rName, bFound );
1389 if ( bFound )
1390 return maEntries[ nPos ].get();
1391 return nullptr;
1395 DocTempl_EntryData_Impl* RegionData_Impl::GetEntry( size_t nIndex ) const
1397 if ( nIndex < maEntries.size() )
1398 return maEntries[ nIndex ].get();
1399 return nullptr;
1403 void RegionData_Impl::DeleteEntry( size_t nIndex )
1405 if ( nIndex < maEntries.size() )
1407 auto it = maEntries.begin();
1408 std::advance( it, nIndex );
1409 maEntries.erase( it );
1414 int RegionData_Impl::Compare( RegionData_Impl const * pCompare ) const
1416 return maTitle.compareTo( pCompare->maTitle );
1420 SfxDocTemplate_Impl::SfxDocTemplate_Impl()
1421 : mbConstructed( false )
1422 , mnLockCounter( 0 )
1427 SfxDocTemplate_Impl::~SfxDocTemplate_Impl()
1429 gpTemplateData = nullptr;
1433 void SfxDocTemplate_Impl::IncrementLock()
1435 ::osl::MutexGuard aGuard( maMutex );
1436 mnLockCounter++;
1440 void SfxDocTemplate_Impl::DecrementLock()
1442 ::osl::MutexGuard aGuard( maMutex );
1443 if ( mnLockCounter )
1444 mnLockCounter--;
1448 RegionData_Impl* SfxDocTemplate_Impl::GetRegion( size_t nIndex ) const
1450 if ( nIndex < maRegions.size() )
1451 return maRegions[ nIndex ].get();
1452 return nullptr;
1456 RegionData_Impl* SfxDocTemplate_Impl::GetRegion( std::u16string_view rName )
1457 const
1459 for (auto& pData : maRegions)
1461 if( pData->GetTitle() == rName )
1462 return pData.get();
1464 return nullptr;
1468 void SfxDocTemplate_Impl::DeleteRegion( size_t nIndex )
1470 if ( nIndex < maRegions.size() )
1472 auto it = maRegions.begin();
1473 std::advance( it, nIndex );
1474 maRegions.erase( it );
1479 /* AddRegion adds a Region to the RegionList
1481 void SfxDocTemplate_Impl::AddRegion( const OUString& rTitle,
1482 Content& rContent )
1484 auto pRegion = std::make_unique<RegionData_Impl>( this, rTitle );
1485 auto pRegionTmp = pRegion.get();
1487 if ( ! InsertRegion( std::move(pRegion), size_t(-1) ) )
1489 return;
1492 // now get the content of the region
1493 uno::Reference< XResultSet > xResultSet;
1497 xResultSet = rContent.createSortedCursor( { TITLE, TARGET_URL }, { { 1, true } }, m_rCompareFactory, INCLUDE_DOCUMENTS_ONLY );
1499 catch ( Exception& ) {}
1501 if ( !xResultSet.is() )
1502 return;
1504 uno::Reference< XRow > xRow( xResultSet, UNO_QUERY );
1508 while ( xResultSet->next() )
1510 pRegionTmp->AddEntry( xRow->getString( 1 ), xRow->getString( 2 ), nullptr );
1513 catch ( Exception& ) {}
1517 void SfxDocTemplate_Impl::CreateFromHierarchy( Content &rTemplRoot )
1519 uno::Reference< XResultSet > xResultSet;
1520 Sequence< OUString > aProps { TITLE };
1524 Sequence< NumberedSortingInfo > aSortingInfo(1);
1525 aSortingInfo.getArray()->ColumnIndex = 1;
1526 aSortingInfo.getArray()->Ascending = true;
1527 xResultSet = rTemplRoot.createSortedCursor( aProps, aSortingInfo, m_rCompareFactory, INCLUDE_FOLDERS_ONLY );
1529 catch ( Exception& ) {}
1531 if ( !xResultSet.is() )
1532 return;
1534 uno::Reference< XCommandEnvironment > aCmdEnv;
1535 uno::Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY );
1536 uno::Reference< XRow > xRow( xResultSet, UNO_QUERY );
1540 while ( xResultSet->next() )
1542 const OUString aId = xContentAccess->queryContentIdentifierString();
1543 Content aContent( aId, aCmdEnv, comphelper::getProcessComponentContext() );
1545 AddRegion( xRow->getString( 1 ), aContent );
1548 catch ( Exception& ) {}
1552 bool SfxDocTemplate_Impl::Construct( )
1554 ::osl::MutexGuard aGuard( maMutex );
1556 if ( mbConstructed )
1557 return true;
1559 uno::Reference< XComponentContext > xContext = ::comphelper::getProcessComponentContext();
1561 uno::Reference< XPersist > xInfo( document::DocumentProperties::create(xContext), UNO_QUERY );
1562 mxInfo = xInfo;
1564 mxTemplates = frame::DocumentTemplates::create(xContext);
1566 uno::Reference< XLocalizable > xLocalizable( mxTemplates, UNO_QUERY );
1568 m_rCompareFactory = AnyCompareFactory::createWithLocale(xContext, xLocalizable->getLocale());
1570 uno::Reference < XContent > aRootContent = mxTemplates->getContent();
1571 uno::Reference < XCommandEnvironment > aCmdEnv;
1573 if ( ! aRootContent.is() )
1574 return false;
1576 mbConstructed = true;
1577 maRootURL = aRootContent->getIdentifier()->getContentIdentifier();
1579 maStandardGroup = DocTemplLocaleHelper::GetStandardGroupString();
1580 Content aTemplRoot( aRootContent, aCmdEnv, xContext );
1581 CreateFromHierarchy( aTemplRoot );
1583 return true;
1587 void SfxDocTemplate_Impl::ReInitFromComponent()
1589 uno::Reference< XDocumentTemplates > xTemplates = getDocTemplates();
1590 if ( xTemplates.is() )
1592 uno::Reference < XContent > aRootContent = xTemplates->getContent();
1593 uno::Reference < XCommandEnvironment > aCmdEnv;
1594 Content aTemplRoot( aRootContent, aCmdEnv, comphelper::getProcessComponentContext() );
1595 Clear();
1596 CreateFromHierarchy( aTemplRoot );
1601 bool SfxDocTemplate_Impl::InsertRegion( std::unique_ptr<RegionData_Impl> pNew, size_t nPos )
1603 ::osl::MutexGuard aGuard( maMutex );
1605 // return false (not inserted) if the entry already exists
1606 for (auto const& pRegion : maRegions)
1607 if ( pRegion->Compare( pNew.get() ) == 0 )
1608 return false;
1610 size_t newPos = nPos;
1611 if ( pNew->GetTitle() == maStandardGroup )
1612 newPos = 0;
1614 if ( newPos < maRegions.size() )
1616 auto it = maRegions.begin();
1617 std::advance( it, newPos );
1618 maRegions.emplace( it, std::move(pNew) );
1620 else
1621 maRegions.emplace_back( std::move(pNew) );
1623 return true;
1627 void SfxDocTemplate_Impl::Rescan()
1629 Clear();
1633 uno::Reference< XDocumentTemplates > xTemplates = getDocTemplates();
1634 DBG_ASSERT( xTemplates.is(), "SfxDocTemplate_Impl::Rescan:invalid template instance!" );
1635 if ( xTemplates.is() )
1637 xTemplates->update();
1639 uno::Reference < XContent > aRootContent = xTemplates->getContent();
1640 uno::Reference < XCommandEnvironment > aCmdEnv;
1642 Content aTemplRoot( aRootContent, aCmdEnv, comphelper::getProcessComponentContext() );
1643 CreateFromHierarchy( aTemplRoot );
1646 catch( const Exception& )
1648 TOOLS_WARN_EXCEPTION( "sfx.doc", "SfxDocTemplate_Impl::Rescan: caught an exception while doing the update" );
1653 bool SfxDocTemplate_Impl::GetTitleFromURL( const OUString& rURL,
1654 OUString& aTitle )
1656 if ( mxInfo.is() )
1660 mxInfo->read( rURL );
1662 catch ( Exception& )
1664 // the document is not a StarOffice document
1665 return false;
1671 uno::Reference< XPropertySet > aPropSet( mxInfo, UNO_QUERY );
1672 if ( aPropSet.is() )
1674 Any aValue = aPropSet->getPropertyValue( TITLE );
1675 aValue >>= aTitle;
1678 catch ( IOException& ) {}
1679 catch ( UnknownPropertyException& ) {}
1680 catch ( Exception& ) {}
1683 if ( aTitle.isEmpty() )
1685 INetURLObject aURL( rURL );
1686 aURL.CutExtension();
1687 aTitle = aURL.getName( INetURLObject::LAST_SEGMENT, true,
1688 INetURLObject::DecodeMechanism::WithCharset );
1691 return true;
1695 void SfxDocTemplate_Impl::Clear()
1697 ::osl::MutexGuard aGuard( maMutex );
1698 if ( mnLockCounter )
1699 return;
1700 maRegions.clear();
1704 bool getTextProperty_Impl( Content& rContent,
1705 const OUString& rPropName,
1706 OUString& rPropValue )
1708 bool bGotProperty = false;
1710 // Get the property
1713 uno::Reference< XPropertySetInfo > aPropInfo = rContent.getProperties();
1715 // check, whether or not the property exists
1716 if ( !aPropInfo.is() || !aPropInfo->hasPropertyByName( rPropName ) )
1718 return false;
1721 // now get the property
1722 Any aAnyValue = rContent.getPropertyValue( rPropName );
1723 aAnyValue >>= rPropValue;
1725 if ( SfxURLRelocator_Impl::propertyCanContainOfficeDir( rPropName ) )
1727 SfxURLRelocator_Impl aRelocImpl( ::comphelper::getProcessComponentContext() );
1728 aRelocImpl.makeAbsoluteURL( rPropValue );
1731 bGotProperty = true;
1733 catch ( RuntimeException& ) {}
1734 catch ( Exception& ) {}
1736 return bGotProperty;
1739 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */