1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include "doctemplates.hxx"
31 #include <osl/mutex.hxx>
32 #include <tools/debug.hxx>
33 #include <tools/diagnose_ex.h>
34 #include <tools/urlobj.hxx>
35 #include <rtl/ustring.hxx>
36 #include <rtl/ustrbuf.hxx>
37 #include <tools/resary.hxx>
38 #include <vcl/svapp.hxx>
39 #include <vcl/wrkwin.hxx>
40 #include <unotools/pathoptions.hxx>
41 #include <comphelper/componentcontext.hxx>
42 #include <comphelper/processfactory.hxx>
43 #include <comphelper/sequenceashashmap.hxx>
44 #include <comphelper/string.hxx>
45 #include <com/sun/star/beans/PropertyAttribute.hpp>
46 #include <com/sun/star/beans/XPropertySet.hpp>
47 #include <com/sun/star/beans/XPropertySetInfo.hpp>
48 #include <com/sun/star/beans/XPropertyContainer.hpp>
49 #include <com/sun/star/beans/StringPair.hpp>
50 #include <com/sun/star/util/XMacroExpander.hpp>
51 #include <com/sun/star/container/XContainerQuery.hpp>
52 #include <com/sun/star/document/XTypeDetection.hpp>
53 #include <com/sun/star/document/XStandaloneDocumentInfo.hpp>
54 #include <com/sun/star/sdbc/XResultSet.hpp>
55 #include <com/sun/star/sdbc/XRow.hpp>
56 #include <com/sun/star/ucb/NameClash.hpp>
57 #include <com/sun/star/ucb/NameClashException.hpp>
58 #include <com/sun/star/ucb/TransferInfo.hpp>
59 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
60 #include <com/sun/star/ucb/XContentAccess.hpp>
61 #include <com/sun/star/frame/XModuleManager.hpp>
62 #include <com/sun/star/uno/Exception.hpp>
64 #include <svtools/templatefoldercache.hxx>
65 #include <unotools/configmgr.hxx>
66 #include <unotools/ucbhelper.hxx>
68 #include "sfx2/sfxresid.hxx"
69 #include "sfxurlrelocator.hxx"
70 #include "doctemplateslocal.hxx"
71 #include <sfx2/docfac.hxx>
72 #include <sfx2/docfile.hxx>
77 //-----------------------------------------------------------------------------
79 //=============================================================================
81 #define TEMPLATE_SERVICE_NAME "com.sun.star.frame.DocumentTemplates"
82 #define TEMPLATE_IMPLEMENTATION_NAME "com.sun.star.comp.sfx2.DocumentTemplates"
84 #define SERVICENAME_TYPEDETECTION "com.sun.star.document.TypeDetection"
85 #define SERVICENAME_DOCINFO "com.sun.star.document.StandaloneDocumentInfo"
87 #define TEMPLATE_ROOT_URL "vnd.sun.star.hier:/templates"
89 #define IS_FOLDER "IsFolder"
90 #define IS_DOCUMENT "IsDocument"
91 #define TARGET_URL "TargetURL"
92 #define TEMPLATE_VERSION "TemplateComponentVersion"
93 #define TEMPLATE_VERSION_VALUE "2"
94 #define TYPE_FOLDER "application/vnd.sun.star.hier-folder"
95 #define TYPE_LINK "application/vnd.sun.star.hier-link"
96 #define TYPE_FSYS_FOLDER "application/vnd.sun.staroffice.fsys-folder"
97 #define TYPE_FSYS_FILE "application/vnd.sun.staroffice.fsys-file"
99 #define PROPERTY_DIRLIST "DirectoryList"
100 #define PROPERTY_NEEDSUPDATE "NeedsUpdate"
101 #define PROPERTY_TYPE "TypeDescription"
103 #define TARGET_DIR_URL "TargetDirURL"
104 #define COMMAND_DELETE "delete"
105 #define COMMAND_TRANSFER "transfer"
107 #define STANDARD_FOLDER "standard"
111 //=============================================================================
113 using namespace ::com::sun::star
;
114 using namespace ::com::sun::star::beans
;
115 using namespace ::com::sun::star::document
;
116 using namespace ::com::sun::star::io
;
117 using namespace ::com::sun::star::lang
;
118 using namespace ::com::sun::star::sdbc
;
119 using namespace ::com::sun::star::ucb
;
120 using namespace ::com::sun::star::uno
;
121 using namespace ::com::sun::star::container
;
122 using namespace ::com::sun::star::util
;
124 using namespace ::rtl
;
125 using namespace ::ucbhelper
;
126 using namespace ::comphelper
;
130 //=============================================================================
132 class WaitWindow_Impl
: public WorkWindow
135 sal_uInt16 _nTextStyle
;
141 virtual void Paint( const Rectangle
& rRect
);
147 //=============================================================================
151 OUString maShortName
;
156 class DocTemplates_EntryData_Impl
;
157 class GroupData_Impl
;
159 typedef vector
< NamePair_Impl
* > NameList_Impl
;
160 typedef vector
< GroupData_Impl
* > GroupList_Impl
;
162 //=============================================================================
163 #include <com/sun/star/task/XInteractionHandler.hpp>
164 #include <com/sun/star/ucb/XProgressHandler.hpp>
166 class TplTaskEnvironment
: public ::cppu::WeakImplHelper1
< ucb::XCommandEnvironment
>
168 uno::Reference
< task::XInteractionHandler
> m_xInteractionHandler
;
169 uno::Reference
< ucb::XProgressHandler
> m_xProgressHandler
;
172 TplTaskEnvironment( const uno::Reference
< task::XInteractionHandler
>& rxInteractionHandler
)
173 : m_xInteractionHandler( rxInteractionHandler
)
176 virtual uno::Reference
<task::XInteractionHandler
> SAL_CALL
getInteractionHandler() throw (uno::RuntimeException
)
177 { return m_xInteractionHandler
; }
179 virtual uno::Reference
<ucb::XProgressHandler
> SAL_CALL
getProgressHandler() throw (uno::RuntimeException
)
180 { return m_xProgressHandler
; }
183 class SfxDocTplService_Impl
185 uno::Reference
< XMultiServiceFactory
> mxFactory
;
186 uno::Reference
< XCommandEnvironment
> maCmdEnv
;
187 uno::Reference
< XStandaloneDocumentInfo
> mxInfo
;
188 uno::Reference
< XTypeDetection
> mxType
;
190 ::osl::Mutex maMutex
;
191 Sequence
< OUString
> maTemplateDirs
;
193 NameList_Impl maNames
;
195 Content maRootContent
;
196 Updater_Impl
* mpUpdater
;
197 sal_Bool mbIsInitialized
: 1;
198 sal_Bool mbLocaleSet
: 1;
200 SfxURLRelocator_Impl maRelocator
;
203 void getDefaultLocale();
205 void readFolderList();
206 sal_Bool
needsUpdate();
207 OUString
getLongName( const OUString
& rShortName
);
208 sal_Bool
setTitleForURL( const OUString
& rURL
, const OUString
& aTitle
);
209 sal_Bool
getTitleFromURL( const OUString
& rURL
, OUString
& aTitle
, OUString
& aType
, sal_Bool
& bDocHasTitle
);
211 sal_Bool
addEntry( Content
& rParentFolder
,
212 const OUString
& rTitle
,
213 const OUString
& rTargetURL
,
214 const OUString
& rType
);
216 sal_Bool
createFolder( const OUString
& rNewFolderURL
,
217 sal_Bool bCreateParent
,
218 sal_Bool bFsysFolder
,
219 Content
&rNewFolder
);
221 sal_Bool
CreateNewUniqueFolderWithPrefix( const ::rtl::OUString
& aPath
,
222 const ::rtl::OUString
& aPrefix
,
223 ::rtl::OUString
& aNewFolderName
,
224 ::rtl::OUString
& aNewFolderURL
,
225 Content
& aNewFolder
);
226 ::rtl::OUString
CreateNewUniqueFileWithPrefix( const ::rtl::OUString
& aPath
,
227 const ::rtl::OUString
& aPrefix
,
228 const ::rtl::OUString
& aExt
);
230 uno::Sequence
< beans::StringPair
> ReadUINamesForTemplateDir_Impl( const ::rtl::OUString
& aUserPath
);
231 sal_Bool
UpdateUINamesForTemplateDir_Impl( const ::rtl::OUString
& aUserPath
,
232 const ::rtl::OUString
& aGroupName
,
233 const ::rtl::OUString
& aNewFolderName
);
234 sal_Bool
ReplaceUINamesForTemplateDir_Impl( const ::rtl::OUString
& aUserPath
,
235 const ::rtl::OUString
& aFsysGroupName
,
236 const ::rtl::OUString
& aOldGroupName
,
237 const ::rtl::OUString
& aNewGroupName
);
238 sal_Bool
RemoveUINamesForTemplateDir_Impl( const ::rtl::OUString
& aUserPath
,
239 const ::rtl::OUString
& aGroupName
);
240 sal_Bool
WriteUINamesForTemplateDir_Impl( const ::rtl::OUString
& aUserPath
,
241 const uno::Sequence
< beans::StringPair
>& aUINames
);
243 ::rtl::OUString
CreateNewGroupFsys( const ::rtl::OUString
& rGroupName
, Content
& aGroup
);
245 sal_Bool
removeContent( Content
& rContent
);
246 sal_Bool
removeContent( const OUString
& rContentURL
);
248 sal_Bool
setProperty( Content
& rContent
,
249 const OUString
& rPropName
,
250 const Any
& rPropValue
);
251 sal_Bool
getProperty( Content
& rContent
,
252 const OUString
& rPropName
,
255 void createFromContent( GroupList_Impl
& rList
,
258 sal_Bool bWriteableContent
= sal_False
);
259 void addHierGroup( GroupList_Impl
& rList
,
260 const OUString
& rTitle
,
261 const OUString
& rOwnURL
);
262 void addFsysGroup( GroupList_Impl
& rList
,
263 const OUString
& rTitle
,
264 const OUString
& rUITitle
,
265 const OUString
& rOwnURL
,
266 sal_Bool bWriteableGroup
= sal_False
);
267 void removeFromHierarchy( DocTemplates_EntryData_Impl
*pData
);
268 void addToHierarchy( GroupData_Impl
*pGroup
,
269 DocTemplates_EntryData_Impl
*pData
);
271 void removeFromHierarchy( GroupData_Impl
*pGroup
);
272 void addGroupToHierarchy( GroupData_Impl
*pGroup
);
274 void updateData( DocTemplates_EntryData_Impl
*pData
);
277 SfxDocTplService_Impl( uno::Reference
< XMultiServiceFactory
> xFactory
);
278 ~SfxDocTplService_Impl();
280 sal_Bool
init() { if ( !mbIsInitialized
) init_Impl(); return mbIsInitialized
; }
281 Content
getContent() const { return maRootContent
; }
283 void setLocale( const Locale
& rLocale
);
286 sal_Bool
storeTemplate( const OUString
& rGroupName
,
287 const OUString
& rTemplateName
,
288 const uno::Reference
< XSTORABLE
>& rStorable
);
290 sal_Bool
addTemplate( const OUString
& rGroupName
,
291 const OUString
& rTemplateName
,
292 const OUString
& rSourceURL
);
293 sal_Bool
removeTemplate( const OUString
& rGroupName
,
294 const OUString
& rTemplateName
);
295 sal_Bool
renameTemplate( const OUString
& rGroupName
,
296 const OUString
& rOldName
,
297 const OUString
& rNewName
);
299 sal_Bool
addGroup( const OUString
& rGroupName
);
300 sal_Bool
removeGroup( const OUString
& rGroupName
);
301 sal_Bool
renameGroup( const OUString
& rOldName
,
302 const OUString
& rNewName
);
304 void update( sal_Bool bUpdateNow
);
306 void finished() { mpUpdater
= NULL
; }
309 //=============================================================================
311 class Updater_Impl
: public ::osl::Thread
314 SfxDocTplService_Impl
*mpDocTemplates
;
317 Updater_Impl( SfxDocTplService_Impl
* pTemplates
);
320 virtual void SAL_CALL
run();
321 virtual void SAL_CALL
onTerminated();
324 //=============================================================================
326 class DocTemplates_EntryData_Impl
330 OUString maTargetURL
;
331 OUString maHierarchyURL
;
333 sal_Bool mbInHierarchy
: 1;
334 sal_Bool mbInUse
: 1;
335 sal_Bool mbUpdateType
: 1;
336 sal_Bool mbUpdateLink
: 1;
339 DocTemplates_EntryData_Impl( const OUString
& rTitle
);
341 void setInUse() { mbInUse
= sal_True
; }
342 void setHierarchy( sal_Bool bInHierarchy
) { mbInHierarchy
= bInHierarchy
; }
343 void setUpdateLink( sal_Bool bUpdateLink
) { mbUpdateLink
= bUpdateLink
; }
344 void setUpdateType( sal_Bool bUpdateType
) { mbUpdateType
= bUpdateType
; }
346 sal_Bool
getInUse() const { return mbInUse
; }
347 sal_Bool
getInHierarchy() const { return mbInHierarchy
; }
348 sal_Bool
getUpdateLink() const { return mbUpdateLink
; }
349 sal_Bool
getUpdateType() const { return mbUpdateType
; }
351 const OUString
& getHierarchyURL() const { return maHierarchyURL
; }
352 const OUString
& getTargetURL() const { return maTargetURL
; }
353 const OUString
& getTitle() const { return maTitle
; }
354 const OUString
& getType() const { return maType
; }
356 void setHierarchyURL( const OUString
& rURL
) { maHierarchyURL
= rURL
; }
357 void setTargetURL( const OUString
& rURL
) { maTargetURL
= rURL
; }
358 void setType( const OUString
& rType
) { maType
= rType
; }
361 //=============================================================================
365 vector
< DocTemplates_EntryData_Impl
* > maEntries
;
367 OUString maHierarchyURL
;
368 OUString maTargetURL
;
369 sal_Bool mbInUse
: 1;
370 sal_Bool mbInHierarchy
: 1;
373 GroupData_Impl( const OUString
& rTitle
);
376 void setInUse() { mbInUse
= sal_True
; }
377 void setHierarchy( sal_Bool bInHierarchy
) { mbInHierarchy
= bInHierarchy
; }
378 void setHierarchyURL( const OUString
& rURL
) { maHierarchyURL
= rURL
; }
379 void setTargetURL( const OUString
& rURL
) { maTargetURL
= rURL
; }
381 sal_Bool
getInUse() const { return mbInUse
; }
382 sal_Bool
getInHierarchy() const { return mbInHierarchy
; }
383 const OUString
& getHierarchyURL() const { return maHierarchyURL
; }
384 const OUString
& getTargetURL() const { return maTargetURL
; }
385 const OUString
& getTitle() const { return maTitle
; }
387 DocTemplates_EntryData_Impl
* addEntry( const OUString
& rTitle
,
388 const OUString
& rTargetURL
,
389 const OUString
& rType
,
390 const OUString
& rHierURL
);
391 size_t count() { return maEntries
.size(); }
392 DocTemplates_EntryData_Impl
* getEntry( size_t nPos
) { return maEntries
[ nPos
]; }
395 //-----------------------------------------------------------------------------
396 // private SfxDocTplService_Impl
397 //-----------------------------------------------------------------------------
398 void SfxDocTplService_Impl::init_Impl()
400 uno::Reference
< lang::XMultiServiceFactory
> xFactory
= ::comphelper::getProcessServiceFactory();
403 uno::Reference
< task::XInteractionHandler
> xInteractionHandler( xFactory
->createInstance( DEFINE_CONST_UNICODE("com.sun.star.task.InteractionHandler") ), uno::UNO_QUERY
);
404 maCmdEnv
= new TplTaskEnvironment( xInteractionHandler
);
407 ::osl::ClearableMutexGuard
aGuard( maMutex
);
408 sal_Bool bIsInitialized
= sal_False
;
409 sal_Bool bNeedsUpdate
= sal_False
;
414 // convert locale to string
415 OUString aLang
= maLocale
.Language
;
416 aLang
+= String( '-' );
417 aLang
+= maLocale
.Country
;
419 // set maRootContent to the root of the templates hierarchy. Create the
420 // entry if necessary
422 maRootURL
= OUString( TEMPLATE_ROOT_URL
);
423 maRootURL
+= String( '/' );
426 ::rtl::OUString
aTemplVersPropName( TEMPLATE_VERSION
);
427 ::rtl::OUString
aTemplVers( TEMPLATE_VERSION_VALUE
);
428 if ( Content::create( maRootURL
, maCmdEnv
, maRootContent
) )
431 ::rtl::OUString aPropValue
;
432 if ( getProperty( maRootContent
, aTemplVersPropName
, aValue
)
433 && ( aValue
>>= aPropValue
)
434 && aPropValue
.equals( aTemplVers
) )
436 bIsInitialized
= sal_True
;
439 removeContent( maRootContent
);
442 if ( !bIsInitialized
)
444 if ( createFolder( maRootURL
, sal_True
, sal_False
, maRootContent
)
445 && setProperty( maRootContent
, aTemplVersPropName
, uno::makeAny( aTemplVers
) ) )
446 bIsInitialized
= sal_True
;
448 bNeedsUpdate
= sal_True
;
451 if ( bIsInitialized
)
453 OUString
aService( SERVICENAME_DOCINFO
);
455 mxInfo
= uno::Reference
< XStandaloneDocumentInfo
> (
456 mxFactory
->createInstance( aService
), UNO_QUERY
);
457 } catch (uno::RuntimeException
&) {
458 OSL_FAIL("SfxDocTplService_Impl::init_Impl: "
459 "cannot create DocumentProperties service");
462 aService
= OUString( SERVICENAME_TYPEDETECTION
);
463 mxType
= uno::Reference
< XTypeDetection
> ( mxFactory
->createInstance( aService
), UNO_QUERY
);
471 SolarMutexClearableGuard aSolarGuard
;
473 WaitWindow_Impl
* pWin
= new WaitWindow_Impl();
476 ::osl::ClearableMutexGuard
anotherGuard( maMutex
);
480 anotherGuard
.clear();
481 SolarMutexGuard aSecondSolarGuard
;
485 else if ( needsUpdate() )
486 // the UI should be shown only on the first update
491 SAL_WARN( "sfx2.doc", "init_Impl(): Could not create root" );
494 mbIsInitialized
= bIsInitialized
;
497 //-----------------------------------------------------------------------------
498 void SfxDocTplService_Impl::getDefaultLocale()
502 ::osl::MutexGuard
aGuard( maMutex
);
505 rtl::OUString
aLocale( utl::ConfigManager::getLocale() );
506 if ( !aLocale
.isEmpty() )
508 sal_Int32 nPos
= aLocale
.indexOf( sal_Unicode( '-' ) );
511 maLocale
.Language
= aLocale
.copy( 0, nPos
);
512 nPos
= aLocale
.indexOf( sal_Unicode( '_' ), nPos
+ 1 );
516 = aLocale
.copy( maLocale
.Language
.getLength() + 1,
517 nPos
- maLocale
.Language
.getLength() - 1 );
519 = aLocale
.copy( nPos
+ 1 );
524 = aLocale
.copy( maLocale
.Language
.getLength() + 1 );
530 mbLocaleSet
= sal_True
;
535 // -----------------------------------------------------------------------
536 void SfxDocTplService_Impl::readFolderList()
538 SolarMutexGuard aGuard
;
540 ResStringArray
aShortNames( SfxResId( TEMPLATE_SHORT_NAMES_ARY
) );
541 ResStringArray
aLongNames( SfxResId( TEMPLATE_LONG_NAMES_ARY
) );
543 NamePair_Impl
* pPair
;
545 sal_uInt16 nCount
= (sal_uInt16
)( Min( aShortNames
.Count(), aLongNames
.Count() ) );
547 for ( sal_uInt16 i
=0; i
<nCount
; i
++ )
549 pPair
= new NamePair_Impl
;
550 pPair
->maShortName
= aShortNames
.GetString( i
);
551 pPair
->maLongName
= aLongNames
.GetString( i
);
553 maNames
.push_back( pPair
);
557 // -----------------------------------------------------------------------
558 OUString
SfxDocTplService_Impl::getLongName( const OUString
& rShortName
)
562 for ( size_t i
= 0, n
= maNames
.size(); i
< n
; ++i
)
564 NamePair_Impl
* pPair
= maNames
[ i
];
565 if ( pPair
->maShortName
== rShortName
)
567 aRet
= pPair
->maLongName
;
572 if ( aRet
.isEmpty() )
578 //-----------------------------------------------------------------------------
579 void SfxDocTplService_Impl::getDirList()
581 OUString
aPropName( PROPERTY_DIRLIST
);
584 // Get the template dir list
585 // TODO/LATER: let use service, register listener
587 String aDirs
= SvtPathOptions().GetTemplatePath();
588 sal_uInt16 nCount
= comphelper::string::getTokenCount(aDirs
, C_DELIM
);
590 maTemplateDirs
= Sequence
< OUString
>( nCount
);
592 uno::Reference
< XComponentContext
> xCtx
;
593 uno::Reference
< util::XMacroExpander
> xExpander
;
594 uno::Reference
< XPropertySet
> xPropSet( mxFactory
, UNO_QUERY
);
595 const rtl::OUString
aPrefix(
596 "vnd.sun.star.expand:" );
600 xPropSet
->getPropertyValue(
608 xCtx
->getValueByName(
609 rtl::OUString( "/singletons/com.sun.star.util.theMacroExpander" ) )
612 OSL_ENSURE( xExpander
.is(),
613 "Unable to obtain macro expander singleton!" );
616 for ( sal_uInt16 i
=0; i
<nCount
; i
++ )
618 aURL
.SetSmartProtocol( INET_PROT_FILE
);
619 aURL
.SetURL( aDirs
.GetToken( i
, C_DELIM
) );
620 maTemplateDirs
[i
] = aURL
.GetMainURL( INetURLObject::NO_DECODE
);
622 sal_Int32 nIndex
= maTemplateDirs
[i
].indexOf( aPrefix
);
623 if ( nIndex
!= -1 && xExpander
.is() )
625 maTemplateDirs
[i
] = maTemplateDirs
[i
].replaceAt(nIndex
,
628 maTemplateDirs
[i
] = xExpander
->expandMacros( maTemplateDirs
[i
] );
632 aValue
<<= maTemplateDirs
;
634 // Store the template dir list
635 setProperty( maRootContent
, aPropName
, aValue
);
638 //-----------------------------------------------------------------------------
639 sal_Bool
SfxDocTplService_Impl::needsUpdate()
641 OUString
aPropName( PROPERTY_NEEDSUPDATE
);
642 sal_Bool bHasProperty
= sal_False
;
643 sal_Bool bNeedsUpdate
= sal_True
;
646 // Get the template dir list
647 bHasProperty
= getProperty( maRootContent
, aPropName
, aValue
);
650 aValue
>>= bNeedsUpdate
;
652 // the old template component also checks this state, but it is initialized from this component
653 // so if this componend was already updated the old component does not need such an update
654 ::svt::TemplateFolderCache aTempCache
;
656 bNeedsUpdate
= aTempCache
.needsUpdate();
659 aTempCache
.storeState();
664 // -----------------------------------------------------------------------
665 sal_Bool
SfxDocTplService_Impl::setTitleForURL( const OUString
& rURL
, const OUString
& aTitle
)
667 sal_Bool bResult
= sal_False
;
672 mxInfo
->loadFromURL( rURL
);
673 uno::Reference
< XPropertySet
> xPropSet( mxInfo
, UNO_QUERY_THROW
);
674 OUString
aPropName( TITLE
);
675 xPropSet
->setPropertyValue( aPropName
, uno::makeAny( aTitle
) );
676 mxInfo
->storeIntoURL( rURL
);
687 // -----------------------------------------------------------------------
688 sal_Bool
SfxDocTplService_Impl::getTitleFromURL( const OUString
& rURL
, OUString
& aTitle
, OUString
& aType
, sal_Bool
& bDocHasTitle
)
690 bDocHasTitle
= sal_False
;
696 mxInfo
->loadFromURL( rURL
);
700 // the document is not a StarOffice document
706 uno::Reference
< XPropertySet
> aPropSet( mxInfo
, UNO_QUERY
);
709 OUString
aPropName( TITLE
);
710 Any aValue
= aPropSet
->getPropertyValue( aPropName
);
713 aPropName
= OUString( "MIMEType" );
714 aValue
= aPropSet
->getPropertyValue( aPropName
);
718 catch ( UnknownPropertyException
& ) {}
719 catch ( Exception
& ) {}
722 if ( aType
.isEmpty() && mxType
.is() )
724 ::rtl::OUString aDocType
= mxType
->queryTypeByURL( rURL
);
725 if ( !aDocType
.isEmpty() )
728 uno::Reference
< container::XNameAccess
> xTypeDetection( mxType
, uno::UNO_QUERY_THROW
);
729 SequenceAsHashMap
aTypeProps( xTypeDetection
->getByName( aDocType
) );
730 aType
= aTypeProps
.getUnpackedValueOrDefault(
731 ::rtl::OUString("MediaType"),
734 catch( uno::Exception
& )
738 if ( aTitle
.isEmpty() )
740 INetURLObject
aURL( rURL
);
742 aTitle
= aURL
.getName( INetURLObject::LAST_SEGMENT
, true,
743 INetURLObject::DECODE_WITH_CHARSET
);
746 bDocHasTitle
= sal_True
;
751 // -----------------------------------------------------------------------
752 sal_Bool
SfxDocTplService_Impl::addEntry( Content
& rParentFolder
,
753 const OUString
& rTitle
,
754 const OUString
& rTargetURL
,
755 const OUString
& rType
)
757 sal_Bool bAddedEntry
= sal_False
;
759 INetURLObject
aLinkObj( rParentFolder
.getURL() );
760 aLinkObj
.insertName( rTitle
, false,
761 INetURLObject::LAST_SEGMENT
, true,
762 INetURLObject::ENCODE_ALL
);
763 OUString aLinkURL
= aLinkObj
.GetMainURL( INetURLObject::NO_DECODE
);
767 if ( ! Content::create( aLinkURL
, maCmdEnv
, aLink
) )
769 Sequence
< OUString
> aNames(3);
770 aNames
[0] = OUString( TITLE
);
771 aNames
[1] = OUString( IS_FOLDER
);
772 aNames
[2] = OUString( TARGET_URL
);
774 Sequence
< Any
> aValues(3);
775 aValues
[0] = makeAny( rTitle
);
776 aValues
[1] = makeAny( sal_Bool( sal_False
) );
777 aValues
[2] = makeAny( rTargetURL
);
779 OUString
aType( TYPE_LINK
);
780 OUString
aAdditionalProp( PROPERTY_TYPE
);
784 rParentFolder
.insertNewContent( aType
, aNames
, aValues
, aLink
);
785 setProperty( aLink
, aAdditionalProp
, makeAny( rType
) );
786 bAddedEntry
= sal_True
;
794 // -----------------------------------------------------------------------
795 sal_Bool
SfxDocTplService_Impl::createFolder( const OUString
& rNewFolderURL
,
796 sal_Bool bCreateParent
,
797 sal_Bool bFsysFolder
,
798 Content
&rNewFolder
)
801 sal_Bool bCreatedFolder
= sal_False
;
802 INetURLObject
aParentURL( rNewFolderURL
);
803 OUString aFolderName
= aParentURL
.getName( INetURLObject::LAST_SEGMENT
, true,
804 INetURLObject::DECODE_WITH_CHARSET
);
806 // compute the parent folder url from the new folder url
807 // and remove the final slash, because Content::create doesn't
809 aParentURL
.removeSegment();
810 if ( aParentURL
.getSegmentCount() >= 1 )
811 aParentURL
.removeFinalSlash();
813 // if the parent exists, we can continue with the creation of the
814 // new folder, we have to create the parent otherwise ( as long as
815 // bCreateParent is set to true )
816 if ( Content::create( aParentURL
.GetMainURL( INetURLObject::NO_DECODE
), maCmdEnv
, aParent
) )
820 Sequence
< OUString
> aNames(2);
821 aNames
[0] = OUString( TITLE
);
822 aNames
[1] = OUString( IS_FOLDER
);
824 Sequence
< Any
> aValues(2);
825 aValues
[0] = makeAny( aFolderName
);
826 aValues
[1] = makeAny( sal_Bool( sal_True
) );
831 aType
= OUString( TYPE_FSYS_FOLDER
);
833 aType
= OUString( TYPE_FOLDER
);
835 aParent
.insertNewContent( aType
, aNames
, aValues
, rNewFolder
);
836 bCreatedFolder
= sal_True
;
838 catch( RuntimeException
& )
840 SAL_WARN( "sfx2.doc", "createFolder(): got runtime exception" );
844 SAL_WARN( "sfx2.doc", "createFolder(): Could not create new folder" );
847 else if ( bCreateParent
)
849 // if the parent doesn't exists and bCreateParent is set to true,
850 // we try to create the parent and if this was successful, we
851 // try to create the new folder again ( but this time, we set
852 // bCreateParent to false to avoid endless recusions )
853 if ( ( aParentURL
.getSegmentCount() >= 1 ) &&
854 createFolder( aParentURL
.GetMainURL( INetURLObject::NO_DECODE
), bCreateParent
, bFsysFolder
, aParent
) )
856 bCreatedFolder
= createFolder( rNewFolderURL
, sal_False
, bFsysFolder
, rNewFolder
);
860 return bCreatedFolder
;
863 // -----------------------------------------------------------------------
864 sal_Bool
SfxDocTplService_Impl::CreateNewUniqueFolderWithPrefix( const ::rtl::OUString
& aPath
,
865 const ::rtl::OUString
& aPrefix
,
866 ::rtl::OUString
& aNewFolderName
,
867 ::rtl::OUString
& aNewFolderURL
,
868 Content
& aNewFolder
)
870 sal_Bool bCreated
= sal_False
;
871 INetURLObject
aDirPath( aPath
);
874 uno::Reference
< XCommandEnvironment
> aQuietEnv
;
875 if ( Content::create( aDirPath
.GetMainURL( INetURLObject::NO_DECODE
), aQuietEnv
, aParent
) )
877 for ( sal_Int32 nInd
= 0; nInd
< 32000; nInd
++ )
879 ::rtl::OUString aTryName
= aPrefix
;
881 aTryName
+= ::rtl::OUString::valueOf( nInd
);
885 Sequence
< OUString
> aNames(2);
886 aNames
[0] = OUString( TITLE
);
887 aNames
[1] = OUString( IS_FOLDER
);
889 Sequence
< Any
> aValues(2);
890 aValues
[0] = makeAny( aTryName
);
891 aValues
[1] = makeAny( sal_Bool( sal_True
) );
893 OUString
aType( TYPE_FSYS_FOLDER
);
895 bCreated
= aParent
.insertNewContent( aType
, aNames
, aValues
, aNewFolder
);
897 catch( ucb::NameClashException
& )
899 // if there is already an element, retry
903 INetURLObject
aObjPath( aDirPath
);
904 aObjPath
.insertName( aTryName
, false,
905 INetURLObject::LAST_SEGMENT
, true,
906 INetURLObject::ENCODE_ALL
);
907 // if there is already an element, retry
908 // if there was another error, do not try any more
909 if ( !::utl::UCBContentHelper::Exists( aObjPath
.GetMainURL( INetURLObject::NO_DECODE
) ) )
915 aNewFolderName
= aTryName
;
916 aNewFolderURL
= aNewFolder
.get()->getIdentifier()->getContentIdentifier();
925 // -----------------------------------------------------------------------
926 ::rtl::OUString
SfxDocTplService_Impl::CreateNewUniqueFileWithPrefix( const ::rtl::OUString
& aPath
,
927 const ::rtl::OUString
& aPrefix
,
928 const ::rtl::OUString
& aExt
)
930 ::rtl::OUString aNewFileURL
;
931 INetURLObject
aDirPath( aPath
);
935 uno::Reference
< XCommandEnvironment
> aQuietEnv
;
936 if ( Content::create( aDirPath
.GetMainURL( INetURLObject::NO_DECODE
), aQuietEnv
, aParent
) )
938 for ( sal_Int32 nInd
= 0; nInd
< 32000; nInd
++ )
941 sal_Bool bCreated
= sal_False
;
942 ::rtl::OUString aTryName
= aPrefix
;
944 aTryName
+= ::rtl::OUString::valueOf( nInd
);
945 if ( aExt
.toChar() != '.' )
946 aTryName
+= ::rtl::OUString( "." );
951 Sequence
< OUString
> aNames(2);
952 aNames
[0] = OUString( TITLE
);
953 aNames
[1] = OUString( IS_DOCUMENT
);
955 Sequence
< Any
> aValues(2);
956 aValues
[0] = makeAny( aTryName
);
957 aValues
[1] = makeAny( sal_Bool( sal_True
) );
959 OUString
aType( TYPE_FSYS_FILE
);
961 bCreated
= aParent
.insertNewContent( aType
, aNames
, aValues
, aNewFile
);
963 catch( ucb::NameClashException
& )
965 // if there is already an element, retry
969 INetURLObject
aObjPath( aPath
);
970 aObjPath
.insertName( aTryName
, false,
971 INetURLObject::LAST_SEGMENT
, true,
972 INetURLObject::ENCODE_ALL
);
973 // if there is already an element, retry
974 // if there was another error, do not try any more
975 if ( !::utl::UCBContentHelper::Exists( aObjPath
.GetMainURL( INetURLObject::NO_DECODE
) ) )
981 aNewFileURL
= aNewFile
.get()->getIdentifier()->getContentIdentifier();
990 // -----------------------------------------------------------------------
991 sal_Bool
SfxDocTplService_Impl::removeContent( Content
& rContent
)
993 sal_Bool bRemoved
= sal_False
;
996 OUString
aCmd( COMMAND_DELETE
);
997 Any aArg
= makeAny( sal_Bool( sal_True
) );
999 rContent
.executeCommand( aCmd
, aArg
);
1000 bRemoved
= sal_True
;
1002 catch ( RuntimeException
& ) {}
1003 catch ( Exception
& ) {}
1008 // -----------------------------------------------------------------------
1009 sal_Bool
SfxDocTplService_Impl::removeContent( const OUString
& rContentURL
)
1013 if ( Content::create( rContentURL
, maCmdEnv
, aContent
) )
1014 return removeContent( aContent
);
1019 // -----------------------------------------------------------------------
1020 sal_Bool
SfxDocTplService_Impl::setProperty( Content
& rContent
,
1021 const OUString
& rPropName
,
1022 const Any
& rPropValue
)
1024 sal_Bool bPropertySet
= sal_False
;
1026 // Store the property
1029 Any
aPropValue( rPropValue
);
1030 uno::Reference
< XPropertySetInfo
> aPropInfo
= rContent
.getProperties();
1032 // check, whether or not the property exists, create it, when not
1033 if ( !aPropInfo
.is() || !aPropInfo
->hasPropertyByName( rPropName
) )
1035 uno::Reference
< XPropertyContainer
> xProperties( rContent
.get(), UNO_QUERY
);
1036 if ( xProperties
.is() )
1040 xProperties
->addProperty( rPropName
, PropertyAttribute::MAYBEVOID
, rPropValue
);
1042 catch( PropertyExistException
& ) {}
1043 catch( IllegalTypeException
& ) {
1044 SAL_WARN( "sfx2.doc", "IllegalTypeException" );
1046 catch( IllegalArgumentException
& ) {
1047 SAL_WARN( "sfx2.doc", "IllegalArgumentException" );
1052 // To ensure a reloctable office installation, the path to the
1053 // office installtion directory must never be stored directly.
1054 if ( SfxURLRelocator_Impl::propertyCanContainOfficeDir( rPropName
) )
1057 if ( rPropValue
>>= aValue
)
1059 maRelocator
.makeRelocatableURL( aValue
);
1060 aPropValue
= makeAny( aValue
);
1064 Sequence
< OUString
> aValues
;
1065 if ( rPropValue
>>= aValues
)
1067 for ( sal_Int32 n
= 0; n
< aValues
.getLength(); n
++ )
1069 maRelocator
.makeRelocatableURL( aValues
[ n
] );
1071 aPropValue
= makeAny( aValues
);
1075 OSL_FAIL( "Unsupported property value type" );
1080 // now set the property
1082 rContent
.setPropertyValue( rPropName
, aPropValue
);
1083 bPropertySet
= sal_True
;
1085 catch ( RuntimeException
& ) {}
1086 catch ( Exception
& ) {}
1088 return bPropertySet
;
1091 // -----------------------------------------------------------------------
1092 sal_Bool
SfxDocTplService_Impl::getProperty( Content
& rContent
,
1093 const OUString
& rPropName
,
1096 sal_Bool bGotProperty
= sal_False
;
1101 uno::Reference
< XPropertySetInfo
> aPropInfo
= rContent
.getProperties();
1103 // check, whether or not the property exists
1104 if ( !aPropInfo
.is() || !aPropInfo
->hasPropertyByName( rPropName
) )
1109 // now get the property
1111 rPropValue
= rContent
.getPropertyValue( rPropName
);
1113 // To ensure a reloctable office installation, the path to the
1114 // office installtion directory must never be stored directly.
1115 if ( SfxURLRelocator_Impl::propertyCanContainOfficeDir( rPropName
) )
1118 if ( rPropValue
>>= aValue
)
1120 maRelocator
.makeAbsoluteURL( aValue
);
1121 rPropValue
= makeAny( aValue
);
1125 Sequence
< OUString
> aValues
;
1126 if ( rPropValue
>>= aValues
)
1128 for ( sal_Int32 n
= 0; n
< aValues
.getLength(); n
++ )
1130 maRelocator
.makeAbsoluteURL( aValues
[ n
] );
1132 rPropValue
= makeAny( aValues
);
1136 OSL_FAIL( "Unsupported property value type" );
1141 bGotProperty
= sal_True
;
1143 catch ( RuntimeException
& ) {}
1144 catch ( Exception
& ) {}
1146 return bGotProperty
;
1149 // -----------------------------------------------------------------------
1151 bool SfxURLRelocator_Impl::propertyCanContainOfficeDir(
1152 const rtl::OUString
& rPropName
)
1154 // Note: TargetURL is handled by UCB itself (because it is a property
1155 // with a predefined semantic). Additional Core properties introduced
1156 // be a client app must be handled by the client app itself, because
1157 // the UCB does not know the semantics of those properties.
1158 return ( rPropName
== TARGET_DIR_URL
|| rPropName
== PROPERTY_DIRLIST
);
1161 //-----------------------------------------------------------------------------
1162 // public SfxDocTplService_Impl
1163 //-----------------------------------------------------------------------------
1165 SfxDocTplService_Impl::SfxDocTplService_Impl( uno::Reference
< XMultiServiceFactory
> xFactory
)
1166 : maRelocator( xFactory
)
1168 mxFactory
= xFactory
;
1170 mbIsInitialized
= sal_False
;
1171 mbLocaleSet
= sal_False
;
1174 //-----------------------------------------------------------------------------
1175 SfxDocTplService_Impl::~SfxDocTplService_Impl()
1177 ::osl::MutexGuard
aGuard( maMutex
);
1181 mpUpdater
->terminate();
1186 for ( size_t i
= 0, n
= maNames
.size(); i
< n
; ++i
)
1187 delete maNames
[ i
];
1191 //-----------------------------------------------------------------------------
1192 Locale
SfxDocTplService_Impl::getLocale()
1194 ::osl::MutexGuard
aGuard( maMutex
);
1202 //-----------------------------------------------------------------------------
1203 void SfxDocTplService_Impl::setLocale( const Locale
&rLocale
)
1205 ::osl::MutexGuard
aGuard( maMutex
);
1208 ( maLocale
.Language
!= rLocale
.Language
) &&
1209 ( maLocale
.Country
!= rLocale
.Country
) )
1210 mbIsInitialized
= sal_False
;
1213 mbLocaleSet
= sal_True
;
1216 //-----------------------------------------------------------------------------
1217 void SfxDocTplService_Impl::update( sal_Bool bUpdateNow
)
1219 ::osl::MutexGuard
aGuard( maMutex
);
1225 mpUpdater
= new Updater_Impl( this );
1226 mpUpdater
->create();
1230 //-----------------------------------------------------------------------------
1231 void SfxDocTplService_Impl::doUpdate()
1233 ::osl::MutexGuard
aGuard( maMutex
);
1235 OUString
aPropName( PROPERTY_NEEDSUPDATE
);
1238 aValue
<<= sal_True
;
1239 setProperty( maRootContent
, aPropName
, aValue
);
1241 GroupList_Impl aGroupList
;
1243 // get the entries from the hierarchy
1244 createFromContent( aGroupList
, maRootContent
, sal_True
);
1246 // get the entries from the template directories
1247 sal_Int32 nCountDir
= maTemplateDirs
.getLength();
1248 OUString
* pDirs
= maTemplateDirs
.getArray();
1249 Content aDirContent
;
1251 // the last directory in the list must be writable
1252 sal_Bool bWriteableDirectory
= sal_True
;
1254 // the target folder might not exist, for this reason no interaction handler should be used
1255 uno::Reference
< XCommandEnvironment
> aQuietEnv
;
1260 if ( Content::create( pDirs
[ nCountDir
], aQuietEnv
, aDirContent
) )
1262 createFromContent( aGroupList
, aDirContent
, sal_False
, bWriteableDirectory
);
1265 bWriteableDirectory
= sal_False
;
1268 // now check the list
1269 for( size_t j
= 0, n
= aGroupList
.size(); j
< n
; ++j
)
1271 GroupData_Impl
*pGroup
= aGroupList
[ j
];
1272 if ( pGroup
->getInUse() )
1274 if ( pGroup
->getInHierarchy() )
1277 if ( Content::create( pGroup
->getHierarchyURL(), maCmdEnv
, aGroup
) )
1278 setProperty( aGroup
,
1279 OUString( TARGET_DIR_URL
),
1280 makeAny( pGroup
->getTargetURL() ) );
1282 size_t nCount
= pGroup
->count();
1283 for ( size_t i
=0; i
<nCount
; i
++ )
1285 DocTemplates_EntryData_Impl
*pData
= pGroup
->getEntry( i
);
1286 if ( ! pData
->getInUse() )
1288 if ( pData
->getInHierarchy() )
1289 removeFromHierarchy( pData
); // delete entry in hierarchy
1291 addToHierarchy( pGroup
, pData
); // add entry to hierarchy
1293 else if ( pData
->getUpdateType() ||
1294 pData
->getUpdateLink() )
1296 updateData( pData
);
1302 addGroupToHierarchy( pGroup
); // add group to hierarchy
1306 removeFromHierarchy( pGroup
); // delete group from hierarchy
1312 aValue
<<= sal_False
;
1313 setProperty( maRootContent
, aPropName
, aValue
);
1316 //-----------------------------------------------------------------------------
1317 uno::Sequence
< beans::StringPair
> SfxDocTplService_Impl::ReadUINamesForTemplateDir_Impl( const ::rtl::OUString
& aUserPath
)
1319 INetURLObject
aLocObj( aUserPath
);
1320 aLocObj
.insertName( ::rtl::OUString( "groupuinames.xml" ), false,
1321 INetURLObject::LAST_SEGMENT
, true,
1322 INetURLObject::ENCODE_ALL
);
1323 Content aLocContent
;
1325 // TODO/LATER: Use hashmap in future
1326 uno::Sequence
< beans::StringPair
> aUINames
;
1327 if ( Content::create( aLocObj
.GetMainURL( INetURLObject::NO_DECODE
), uno::Reference
< ucb::XCommandEnvironment
>(), aLocContent
) )
1331 uno::Reference
< io::XInputStream
> xLocStream
= aLocContent
.openStream();
1332 if ( xLocStream
.is() )
1333 aUINames
= DocTemplLocaleHelper::ReadGroupLocalizationSequence( xLocStream
, mxFactory
);
1335 catch( uno::Exception
& )
1342 //-----------------------------------------------------------------------------
1343 sal_Bool
SfxDocTplService_Impl::UpdateUINamesForTemplateDir_Impl( const ::rtl::OUString
& aUserPath
,
1344 const ::rtl::OUString
& aGroupName
,
1345 const ::rtl::OUString
& aNewFolderName
)
1347 uno::Sequence
< beans::StringPair
> aUINames
= ReadUINamesForTemplateDir_Impl( aUserPath
);
1348 sal_Int32 nLen
= aUINames
.getLength();
1350 // it is possible that the name is used already, but it should be checked before
1351 for ( sal_Int32 nInd
= 0; nInd
< nLen
; nInd
++ )
1352 if ( aUINames
[nInd
].First
.equals( aNewFolderName
) )
1355 aUINames
.realloc( ++nLen
);
1356 aUINames
[nLen
-1].First
= aNewFolderName
;
1357 aUINames
[nLen
-1].Second
= aGroupName
;
1359 return WriteUINamesForTemplateDir_Impl( aUserPath
, aUINames
);
1362 //-----------------------------------------------------------------------------
1363 sal_Bool
SfxDocTplService_Impl::ReplaceUINamesForTemplateDir_Impl( const ::rtl::OUString
& aUserPath
,
1364 const ::rtl::OUString
& aDefaultFsysGroupName
,
1365 const ::rtl::OUString
& aOldGroupName
,
1366 const ::rtl::OUString
& aNewGroupName
)
1368 uno::Sequence
< beans::StringPair
> aUINames
= ReadUINamesForTemplateDir_Impl( aUserPath
);
1369 sal_Int32 nLen
= aUINames
.getLength();
1371 sal_Bool bChanged
= sal_False
;
1372 for ( sal_Int32 nInd
= 0; nInd
< nLen
; nInd
++ )
1373 if ( aUINames
[nInd
].Second
.equals( aOldGroupName
) )
1375 aUINames
[nInd
].Second
= aNewGroupName
;
1376 bChanged
= sal_True
;
1381 aUINames
.realloc( ++nLen
);
1382 aUINames
[nLen
-1].First
= aDefaultFsysGroupName
;
1383 aUINames
[nLen
-1].Second
= aNewGroupName
;
1385 return WriteUINamesForTemplateDir_Impl( aUserPath
, aUINames
);
1388 //-----------------------------------------------------------------------------
1389 sal_Bool
SfxDocTplService_Impl::RemoveUINamesForTemplateDir_Impl( const ::rtl::OUString
& aUserPath
,
1390 const ::rtl::OUString
& aGroupName
)
1392 uno::Sequence
< beans::StringPair
> aUINames
= ReadUINamesForTemplateDir_Impl( aUserPath
);
1393 sal_Int32 nLen
= aUINames
.getLength();
1394 uno::Sequence
< beans::StringPair
> aNewUINames( nLen
);
1395 sal_Int32 nNewLen
= 0;
1397 sal_Bool bChanged
= sal_False
;
1398 for ( sal_Int32 nInd
= 0; nInd
< nLen
; nInd
++ )
1399 if ( aUINames
[nInd
].Second
.equals( aGroupName
) )
1400 bChanged
= sal_True
;
1404 aNewUINames
[nNewLen
-1].First
= aUINames
[nInd
].First
;
1405 aNewUINames
[nNewLen
-1].Second
= aUINames
[nInd
].Second
;
1408 aNewUINames
.realloc( nNewLen
);
1410 return bChanged
? WriteUINamesForTemplateDir_Impl( aUserPath
, aNewUINames
) : sal_True
;
1414 //-----------------------------------------------------------------------------
1415 sal_Bool
SfxDocTplService_Impl::WriteUINamesForTemplateDir_Impl( const ::rtl::OUString
& aUserPath
,
1416 const uno::Sequence
< beans::StringPair
>& aUINames
)
1418 sal_Bool bResult
= sal_False
;
1420 uno::Reference
< beans::XPropertySet
> xTempFile(
1421 mxFactory
->createInstance( ::rtl::OUString("com.sun.star.io.TempFile") ),
1422 uno::UNO_QUERY_THROW
);
1424 ::rtl::OUString aTempURL
;
1425 uno::Any aUrl
= xTempFile
->getPropertyValue( ::rtl::OUString("Uri") );
1428 uno::Reference
< io::XStream
> xStream( xTempFile
, uno::UNO_QUERY_THROW
);
1429 uno::Reference
< io::XOutputStream
> xOutStream
= xStream
->getOutputStream();
1430 if ( !xOutStream
.is() )
1431 throw uno::RuntimeException();
1433 DocTemplLocaleHelper::WriteGroupLocalizationSequence( xOutStream
, aUINames
, mxFactory
);
1435 // the SAX writer might close the stream
1436 xOutStream
->closeOutput();
1437 } catch( uno::Exception
& )
1440 Content
aTargetContent( aUserPath
, maCmdEnv
);
1441 Content
aSourceContent( aTempURL
, maCmdEnv
);
1442 aTargetContent
.transferContent( aSourceContent
,
1443 InsertOperation_COPY
,
1444 ::rtl::OUString( "groupuinames.xml" ),
1445 ucb::NameClash::OVERWRITE
);
1448 catch ( uno::Exception
& )
1455 //-----------------------------------------------------------------------------
1456 ::rtl::OUString
SfxDocTplService_Impl::CreateNewGroupFsys( const ::rtl::OUString
& rGroupName
, Content
& aGroup
)
1458 ::rtl::OUString aResultURL
;
1460 if ( maTemplateDirs
.getLength() )
1462 ::rtl::OUString aTargetPath
= maTemplateDirs
[ maTemplateDirs
.getLength() - 1 ];
1464 // create a new folder with the given name
1466 ::rtl::OUString aNewFolderName
;
1468 // the Fsys name instead of GroupName should be used, the groupuinames must be added also
1469 if ( !CreateNewUniqueFolderWithPrefix( aTargetPath
,
1474 && !CreateNewUniqueFolderWithPrefix( aTargetPath
,
1475 ::rtl::OUString( "UserGroup" ),
1480 return ::rtl::OUString();
1482 if ( !UpdateUINamesForTemplateDir_Impl( aTargetPath
, rGroupName
, aNewFolderName
) )
1484 // we could not create the groupuinames for the folder, so we delete the group in the
1485 // the folder and return
1486 removeContent( aNewFolder
);
1487 return ::rtl::OUString();
1490 // Now set the target url for this group and we are done
1491 OUString
aPropName( TARGET_DIR_URL
);
1492 Any aValue
= makeAny( aResultURL
);
1494 if ( ! setProperty( aGroup
, aPropName
, aValue
) )
1496 removeContent( aNewFolder
);
1497 return ::rtl::OUString();
1504 //-----------------------------------------------------------------------------
1505 sal_Bool
SfxDocTplService_Impl::addGroup( const OUString
& rGroupName
)
1507 ::osl::MutexGuard
aGuard( maMutex
);
1509 // Check, whether or not there is a group with this name
1511 OUString aNewGroupURL
;
1512 INetURLObject
aNewGroupObj( maRootURL
);
1514 aNewGroupObj
.insertName( rGroupName
, false,
1515 INetURLObject::LAST_SEGMENT
, true,
1516 INetURLObject::ENCODE_ALL
);
1518 aNewGroupURL
= aNewGroupObj
.GetMainURL( INetURLObject::NO_DECODE
);
1520 if ( Content::create( aNewGroupURL
, maCmdEnv
, aNewGroup
) ||
1521 ! createFolder( aNewGroupURL
, sal_False
, sal_False
, aNewGroup
) )
1523 // if there already was a group with this name or the new group
1524 // could not be created, we return here
1528 // Get the user template path entry ( new group will always
1529 // be added in the user template path )
1533 nIndex
= maTemplateDirs
.getLength();
1537 return sal_False
; // We don't know where to add the group
1539 aUserPath
= maTemplateDirs
[ nIndex
];
1541 // create a new folder with the given name
1543 OUString aNewFolderName
;
1544 OUString aNewFolderURL
;
1546 // the Fsys name instead of GroupName should be used, the groupuinames must be added also
1547 if ( !CreateNewUniqueFolderWithPrefix( aUserPath
,
1552 && !CreateNewUniqueFolderWithPrefix( aUserPath
,
1553 ::rtl::OUString( "UserGroup" ),
1558 // we could not create the folder, so we delete the group in the
1559 // hierarchy and return
1560 removeContent( aNewGroup
);
1564 if ( !UpdateUINamesForTemplateDir_Impl( aUserPath
, rGroupName
, aNewFolderName
) )
1566 // we could not create the groupuinames for the folder, so we delete the group in the
1567 // hierarchy, the folder and return
1568 removeContent( aNewGroup
);
1569 removeContent( aNewFolder
);
1573 // Now set the target url for this group and we are done
1574 OUString
aPropName( TARGET_DIR_URL
);
1575 Any aValue
= makeAny( aNewFolderURL
);
1577 if ( ! setProperty( aNewGroup
, aPropName
, aValue
) )
1579 removeContent( aNewGroup
);
1580 removeContent( aNewFolder
);
1587 //-----------------------------------------------------------------------------
1588 sal_Bool
SfxDocTplService_Impl::removeGroup( const OUString
& rGroupName
)
1590 // remove all the elements that have the prefix aTargetURL
1591 // if the group does not have other elements remove it
1593 ::osl::MutexGuard
aGuard( maMutex
);
1595 sal_Bool bResult
= sal_False
;
1597 // create the group url
1598 INetURLObject
aGroupObj( maRootURL
);
1599 aGroupObj
.insertName( rGroupName
, false,
1600 INetURLObject::LAST_SEGMENT
, true,
1601 INetURLObject::ENCODE_ALL
);
1603 // Get the target url
1605 OUString aGroupURL
= aGroupObj
.GetMainURL( INetURLObject::NO_DECODE
);
1607 if ( Content::create( aGroupURL
, maCmdEnv
, aGroup
) )
1609 OUString
aPropName( TARGET_DIR_URL
);
1612 OUString aGroupTargetURL
;
1613 if ( getProperty( aGroup
, aPropName
, aValue
) )
1614 aValue
>>= aGroupTargetURL
;
1616 if ( aGroupTargetURL
.isEmpty() )
1617 return sal_False
; // nothing is allowed to be removed
1619 if ( !maTemplateDirs
.getLength() )
1621 ::rtl::OUString aGeneralTempPath
= maTemplateDirs
[ maTemplateDirs
.getLength() - 1 ];
1623 // check that the fs location is in writeble folder and this is not a "My templates" folder
1624 INetURLObject
aGroupParentFolder( aGroupTargetURL
);
1625 if ( !aGroupParentFolder
.removeSegment()
1626 || !::utl::UCBContentHelper::IsSubPath( aGeneralTempPath
,
1627 aGroupParentFolder
.GetMainURL( INetURLObject::NO_DECODE
) ) )
1630 // now get the content of the Group
1631 uno::Reference
< XResultSet
> xResultSet
;
1632 Sequence
< OUString
> aProps( 1 );
1634 aProps
[0] = OUString(TARGET_URL
);
1638 sal_Bool bHasNonRemovable
= sal_False
;
1639 sal_Bool bHasShared
= sal_False
;
1641 ResultSetInclude eInclude
= INCLUDE_DOCUMENTS_ONLY
;
1642 xResultSet
= aGroup
.createCursor( aProps
, eInclude
);
1644 if ( xResultSet
.is() )
1646 uno::Reference
< XContentAccess
> xContentAccess( xResultSet
, UNO_QUERY_THROW
);
1647 uno::Reference
< XRow
> xRow( xResultSet
, UNO_QUERY_THROW
);
1649 while ( xResultSet
->next() )
1651 OUString
aTemplTargetURL( xRow
->getString( 1 ) );
1652 OUString aHierURL
= xContentAccess
->queryContentIdentifierString();
1654 if ( ::utl::UCBContentHelper::IsSubPath( aGroupTargetURL
, aTemplTargetURL
) )
1656 // this is a user template, and it can be removed
1657 if ( removeContent( aTemplTargetURL
) )
1658 removeContent( aHierURL
);
1660 bHasNonRemovable
= sal_True
;
1663 bHasShared
= sal_True
;
1666 if ( !bHasNonRemovable
&& !bHasShared
)
1668 if ( removeContent( aGroupTargetURL
)
1669 || !::utl::UCBContentHelper::Exists( aGroupTargetURL
) )
1671 removeContent( aGroupURL
);
1672 RemoveUINamesForTemplateDir_Impl( aGeneralTempPath
, rGroupName
);
1673 bResult
= sal_True
; // the operation is successful only if the whole group is removed
1676 else if ( !bHasNonRemovable
)
1678 if ( removeContent( aGroupTargetURL
)
1679 || !::utl::UCBContentHelper::Exists( aGroupTargetURL
) )
1681 RemoveUINamesForTemplateDir_Impl( aGeneralTempPath
, rGroupName
);
1682 setProperty( aGroup
, aPropName
, uno::makeAny( ::rtl::OUString() ) );
1687 catch ( Exception
& ) {}
1693 //-----------------------------------------------------------------------------
1694 sal_Bool
SfxDocTplService_Impl::renameGroup( const OUString
& rOldName
,
1695 const OUString
& rNewName
)
1697 ::osl::MutexGuard
aGuard( maMutex
);
1699 // create the group url
1701 INetURLObject
aGroupObj( maRootURL
);
1702 aGroupObj
.insertName( rNewName
, false,
1703 INetURLObject::LAST_SEGMENT
, true,
1704 INetURLObject::ENCODE_ALL
);
1705 OUString aGroupURL
= aGroupObj
.GetMainURL( INetURLObject::NO_DECODE
);
1707 // Check, if there is a group with the new name, return false
1709 if ( Content::create( aGroupURL
, maCmdEnv
, aGroup
) )
1712 aGroupObj
.removeSegment();
1713 aGroupObj
.insertName( rOldName
, false,
1714 INetURLObject::LAST_SEGMENT
, true,
1715 INetURLObject::ENCODE_ALL
);
1716 aGroupURL
= aGroupObj
.GetMainURL( INetURLObject::NO_DECODE
);
1718 // When there is no group with the old name, we can't rename it
1719 if ( ! Content::create( aGroupURL
, maCmdEnv
, aGroup
) )
1722 OUString aGroupTargetURL
;
1723 // there is no need to check whether target dir url is in target path, since if the target path is changed
1724 // the target dir url should be already generated new
1725 OUString
aPropName( TARGET_DIR_URL
);
1727 if ( getProperty( aGroup
, aPropName
, aValue
) )
1728 aValue
>>= aGroupTargetURL
;
1730 if ( aGroupTargetURL
.isEmpty() )
1733 if ( !maTemplateDirs
.getLength() )
1735 ::rtl::OUString aGeneralTempPath
= maTemplateDirs
[ maTemplateDirs
.getLength() - 1 ];
1737 // check that the fs location is in writeble folder and this is not a "My templates" folder
1738 INetURLObject
aGroupParentFolder( aGroupTargetURL
);
1739 if ( !aGroupParentFolder
.removeSegment()
1740 || !::utl::UCBContentHelper::IsSubPath( aGeneralTempPath
,
1741 aGroupParentFolder
.GetMainURL( INetURLObject::NO_DECODE
) ) )
1744 // check that the group can be renamed ( all the contents must be in target location )
1745 sal_Bool bCanBeRenamed
= sal_False
;
1748 uno::Reference
< XResultSet
> xResultSet
;
1749 Sequence
< OUString
> aProps( 1 );
1751 aProps
[0] = OUString(TARGET_URL
);
1752 ResultSetInclude eInclude
= INCLUDE_DOCUMENTS_ONLY
;
1753 xResultSet
= aGroup
.createCursor( aProps
, eInclude
);
1755 if ( xResultSet
.is() )
1757 uno::Reference
< XContentAccess
> xContentAccess( xResultSet
, UNO_QUERY_THROW
);
1758 uno::Reference
< XRow
> xRow( xResultSet
, UNO_QUERY_THROW
);
1760 while ( xResultSet
->next() )
1762 OUString
aTemplTargetURL( xRow
->getString( 1 ) );
1764 if ( !::utl::UCBContentHelper::IsSubPath( aGroupTargetURL
, aTemplTargetURL
) )
1765 throw uno::Exception();
1768 bCanBeRenamed
= sal_True
;
1771 catch ( Exception
& ) {}
1773 if ( bCanBeRenamed
)
1775 INetURLObject
aGroupTargetObj( aGroupTargetURL
);
1776 ::rtl::OUString aFsysName
= aGroupTargetObj
.getName( INetURLObject::LAST_SEGMENT
, true, INetURLObject::DECODE_WITH_CHARSET
);
1778 if ( aGroupTargetObj
.removeSegment()
1779 && ReplaceUINamesForTemplateDir_Impl( aGroupTargetObj
.GetMainURL( INetURLObject::NO_DECODE
),
1784 // rename the group in the hierarchy
1785 OUString
aTitleProp( TITLE
);
1787 aTitleValue
<<= rNewName
;
1789 return setProperty( aGroup
, aTitleProp
, aTitleValue
);
1796 //-----------------------------------------------------------------------------
1797 sal_Bool
SfxDocTplService_Impl::storeTemplate( const OUString
& rGroupName
,
1798 const OUString
& rTemplateName
,
1799 const uno::Reference
< XSTORABLE
>& rStorable
)
1801 ::osl::MutexGuard
aGuard( maMutex
);
1803 // Check, whether or not there is a group with this name
1804 // Return false, if there is no group with the given name
1805 Content aGroup
, aTemplate
, aTargetGroup
, aTemplateToRemove
;
1806 OUString aGroupURL
, aTemplateURL
, aTemplateToRemoveTargetURL
;
1807 INetURLObject
aGroupObj( maRootURL
);
1808 sal_Bool bRemoveOldTemplateContent
= sal_False
;
1809 ::rtl::OUString sDocServiceName
;
1811 aGroupObj
.insertName( rGroupName
, false,
1812 INetURLObject::LAST_SEGMENT
, true,
1813 INetURLObject::ENCODE_ALL
);
1814 aGroupURL
= aGroupObj
.GetMainURL( INetURLObject::NO_DECODE
);
1816 if ( ! Content::create( aGroupURL
, maCmdEnv
, aGroup
) )
1819 ::rtl::OUString aGroupTargetURL
;
1820 ::rtl::OUString
aPropName( TARGET_DIR_URL
);
1822 if ( getProperty( aGroup
, aPropName
, aValue
) )
1823 aValue
>>= aGroupTargetURL
;
1826 // Check, if there's a template with the given name in this group
1827 // the target template should be overwritten if it is imported by user
1828 // in case the template is installed by office installation of by an add-in
1829 // it can not be replaced
1830 aGroupObj
.insertName( rTemplateName
, false,
1831 INetURLObject::LAST_SEGMENT
, true,
1832 INetURLObject::ENCODE_ALL
);
1833 aTemplateURL
= aGroupObj
.GetMainURL( INetURLObject::NO_DECODE
);
1835 if ( Content::create( aTemplateURL
, maCmdEnv
, aTemplateToRemove
) )
1837 OUString
aTargetTemplPropName( TARGET_URL
);
1839 bRemoveOldTemplateContent
= sal_True
;
1840 if ( getProperty( aTemplateToRemove
, aTargetTemplPropName
, aValue
) )
1841 aValue
>>= aTemplateToRemoveTargetURL
;
1843 if ( aGroupTargetURL
.isEmpty() || !maTemplateDirs
.getLength()
1844 || (!aTemplateToRemoveTargetURL
.isEmpty() && !::utl::UCBContentHelper::IsSubPath( maTemplateDirs
[ maTemplateDirs
.getLength() - 1 ], aTemplateToRemoveTargetURL
)) )
1845 return sal_False
; // it is not allowed to remove the template
1850 uno::Reference
< lang::XMultiServiceFactory
> xFactory
= ::comphelper::getProcessServiceFactory();
1851 if ( !xFactory
.is() )
1852 throw uno::RuntimeException();
1854 // get document service name
1855 uno::Reference
< frame::XModuleManager
> xModuleManager(
1856 xFactory
->createInstance(
1857 ::rtl::OUString("com.sun.star.frame.ModuleManager") ),
1858 uno::UNO_QUERY_THROW
);
1859 sDocServiceName
= xModuleManager
->identify( uno::Reference
< uno::XInterface
>( rStorable
, uno::UNO_QUERY
) );
1860 if ( sDocServiceName
.isEmpty() )
1861 throw uno::RuntimeException();
1863 // get the actual filter name
1864 ::rtl::OUString aFilterName
;
1866 uno::Reference
< lang::XMultiServiceFactory
> xConfigProvider(
1867 xFactory
->createInstance(
1868 ::rtl::OUString("com.sun.star.configuration.ConfigurationProvider") ),
1869 uno::UNO_QUERY_THROW
);
1871 uno::Sequence
< uno::Any
> aArgs( 1 );
1872 beans::PropertyValue aPathProp
;
1873 aPathProp
.Name
= ::rtl::OUString("nodepath");
1874 aPathProp
.Value
<<= ::rtl::OUString( "/org.openoffice.Setup/Office/Factories/" );
1875 aArgs
[0] <<= aPathProp
;
1877 uno::Reference
< container::XNameAccess
> xSOFConfig(
1878 xConfigProvider
->createInstanceWithArguments(
1879 ::rtl::OUString("com.sun.star.configuration.ConfigurationAccess"),
1881 uno::UNO_QUERY_THROW
);
1883 uno::Reference
< container::XNameAccess
> xApplConfig
;
1884 xSOFConfig
->getByName( sDocServiceName
) >>= xApplConfig
;
1885 if ( !xApplConfig
.is() )
1886 throw uno::RuntimeException();
1888 xApplConfig
->getByName( ::rtl::OUString( "ooSetupFactoryActualTemplateFilter" ) ) >>= aFilterName
;
1889 if ( aFilterName
.isEmpty() )
1890 throw uno::RuntimeException();
1892 // find the related type name
1893 ::rtl::OUString aTypeName
;
1894 uno::Reference
< container::XNameAccess
> xFilterFactory(
1895 xFactory
->createInstance( ::rtl::OUString("com.sun.star.document.FilterFactory") ),
1896 uno::UNO_QUERY_THROW
);
1898 uno::Sequence
< beans::PropertyValue
> aFilterData
;
1899 xFilterFactory
->getByName( aFilterName
) >>= aFilterData
;
1900 for ( sal_Int32 nInd
= 0; nInd
< aFilterData
.getLength(); nInd
++ )
1901 if ( aFilterData
[nInd
].Name
== "Type" )
1902 aFilterData
[nInd
].Value
>>= aTypeName
;
1904 if ( aTypeName
.isEmpty() )
1905 throw uno::RuntimeException();
1907 // find the mediatype and extension
1908 uno::Reference
< container::XNameAccess
> xTypeDetection
=
1910 uno::Reference
< container::XNameAccess
>( mxType
, uno::UNO_QUERY_THROW
) :
1911 uno::Reference
< container::XNameAccess
>(
1912 xFactory
->createInstance( ::rtl::OUString("com.sun.star.document.TypeDetection") ),
1913 uno::UNO_QUERY_THROW
);
1915 SequenceAsHashMap
aTypeProps( xTypeDetection
->getByName( aTypeName
) );
1916 uno::Sequence
< ::rtl::OUString
> aAllExt
=
1917 aTypeProps
.getUnpackedValueOrDefault( ::rtl::OUString("Extensions"), Sequence
< ::rtl::OUString
>() );
1918 if ( !aAllExt
.getLength() )
1919 throw uno::RuntimeException();
1921 ::rtl::OUString aMediaType
= aTypeProps
.getUnpackedValueOrDefault( ::rtl::OUString("MediaType"), ::rtl::OUString() );
1922 ::rtl::OUString aExt
= aAllExt
[0];
1924 if ( aMediaType
.isEmpty() || aExt
.isEmpty() )
1925 throw uno::RuntimeException();
1927 // construct destination url
1928 if ( aGroupTargetURL
.isEmpty() )
1930 aGroupTargetURL
= CreateNewGroupFsys( rGroupName
, aGroup
);
1932 if ( aGroupTargetURL
.isEmpty() )
1933 throw uno::RuntimeException();
1936 ::rtl::OUString aNewTemplateTargetURL
= CreateNewUniqueFileWithPrefix( aGroupTargetURL
, rTemplateName
, aExt
);
1937 if ( aNewTemplateTargetURL
.isEmpty() )
1939 aNewTemplateTargetURL
= CreateNewUniqueFileWithPrefix( aGroupTargetURL
, ::rtl::OUString( "UserTemplate" ), aExt
);
1941 if ( aNewTemplateTargetURL
.isEmpty() )
1942 throw uno::RuntimeException();
1946 uno::Sequence
< PropertyValue
> aStoreArgs( 2 );
1947 aStoreArgs
[0].Name
= ::rtl::OUString("FilterName");
1948 aStoreArgs
[0].Value
<<= aFilterName
;
1949 aStoreArgs
[1].Name
= ::rtl::OUString("DocumentTitle");
1950 aStoreArgs
[1].Value
<<= rTemplateName
;
1952 ::rtl::OUString aCurrentDocumentURL
= rStorable
->getLocation();
1953 if( !::utl::UCBContentHelper::EqualURLs( aNewTemplateTargetURL
, rStorable
->getLocation() ))
1954 rStorable
->storeToURL( aNewTemplateTargetURL
, aStoreArgs
);
1958 // the storing was successful, now the old template with the same name can be removed if it existed
1959 if ( !aTemplateToRemoveTargetURL
.isEmpty() )
1961 removeContent( aTemplateToRemoveTargetURL
);
1965 * if the old template was the standard template
1966 * it is necessary to change the standard template with the new file name
1968 String sStdTmplFile
= SfxObjectFactory::GetStandardTemplate( sDocServiceName
);
1969 if ( INetURLObject( sStdTmplFile
) == INetURLObject( aTemplateToRemoveTargetURL
) )
1971 SfxObjectFactory::SetStandardTemplate( sDocServiceName
, aNewTemplateTargetURL
);
1975 if ( bRemoveOldTemplateContent
)
1976 removeContent( aTemplateToRemove
);
1978 // add the template to hierarchy
1979 return addEntry( aGroup
, rTemplateName
, aNewTemplateTargetURL
, aMediaType
);
1983 // the template was not stored
1988 //-----------------------------------------------------------------------------
1989 sal_Bool
SfxDocTplService_Impl::addTemplate( const OUString
& rGroupName
,
1990 const OUString
& rTemplateName
,
1991 const OUString
& rSourceURL
)
1993 ::osl::MutexGuard
aGuard( maMutex
);
1995 // Check, whether or not there is a group with this name
1996 // Return false, if there is no group with the given name
1997 Content aGroup
, aTemplate
, aTargetGroup
;
1998 OUString aGroupURL
, aTemplateURL
;
1999 INetURLObject
aGroupObj( maRootURL
);
2001 aGroupObj
.insertName( rGroupName
, false,
2002 INetURLObject::LAST_SEGMENT
, true,
2003 INetURLObject::ENCODE_ALL
);
2004 aGroupURL
= aGroupObj
.GetMainURL( INetURLObject::NO_DECODE
);
2006 if ( ! Content::create( aGroupURL
, maCmdEnv
, aGroup
) )
2009 // Check, if there's a template with the given name in this group
2010 // Return false, if there already is a template
2011 aGroupObj
.insertName( rTemplateName
, false,
2012 INetURLObject::LAST_SEGMENT
, true,
2013 INetURLObject::ENCODE_ALL
);
2014 aTemplateURL
= aGroupObj
.GetMainURL( INetURLObject::NO_DECODE
);
2016 if ( Content::create( aTemplateURL
, maCmdEnv
, aTemplate
) )
2019 // get the target url of the group
2020 OUString aTargetURL
;
2021 OUString
aPropName( TARGET_DIR_URL
);
2024 if ( getProperty( aGroup
, aPropName
, aValue
) )
2025 aValue
>>= aTargetURL
;
2027 if ( aTargetURL
.isEmpty() )
2029 aTargetURL
= CreateNewGroupFsys( rGroupName
, aGroup
);
2031 if ( aTargetURL
.isEmpty() )
2035 // Get the content type
2036 OUString aTitle
, aType
, aTargetURL2
, aFullName
;
2038 // only StarOffice documents are acceptable
2039 sal_Bool bDocHasTitle
= sal_False
;
2040 if( !getTitleFromURL( rSourceURL
, aTitle
, aType
, bDocHasTitle
) )
2043 INetURLObject
aSourceObj( rSourceURL
);
2044 if ( rTemplateName
.equals( aTitle
) )
2046 // addTemplate will sometimes be called just to add an entry in the
2047 // hierarchy; the target URL and the source URL will be the same in
2049 // TODO/LATER: get rid of this old hack
2051 INetURLObject
aTargetObj( aTargetURL
);
2053 aTargetObj
.insertName( rTemplateName
, false,
2054 INetURLObject::LAST_SEGMENT
, true,
2055 INetURLObject::ENCODE_ALL
);
2056 aTargetObj
.setExtension( aSourceObj
.getExtension() );
2058 aTargetURL2
= aTargetObj
.GetMainURL( INetURLObject::NO_DECODE
);
2060 if ( aTargetURL2
== rSourceURL
)
2061 return addEntry( aGroup
, rTemplateName
, aTargetURL2
, aType
);
2064 // copy the template into the new group (targeturl)
2066 INetURLObject
aTmpURL( aSourceObj
);
2067 aTmpURL
.CutExtension();
2068 ::rtl::OUString aPattern
= aTmpURL
.getName( INetURLObject::LAST_SEGMENT
, true, INetURLObject::DECODE_WITH_CHARSET
);
2070 ::rtl::OUString aNewTemplateTargetURL
= CreateNewUniqueFileWithPrefix( aTargetURL
, aPattern
, aSourceObj
.getExtension() );
2071 INetURLObject
aNewTemplateTargetObj( aNewTemplateTargetURL
);
2072 ::rtl::OUString aNewTemplateTargetName
= aNewTemplateTargetObj
.getName( INetURLObject::LAST_SEGMENT
, true, INetURLObject::DECODE_WITH_CHARSET
);
2073 if ( aNewTemplateTargetURL
.isEmpty() || aNewTemplateTargetName
.isEmpty() )
2076 // get access to source file
2077 Content aSourceContent
;
2078 uno::Reference
< ucb::XCommandEnvironment
> xEnv
;
2079 INetURLObject
aSourceURL( rSourceURL
);
2080 if( ! Content::create( aSourceURL
.GetMainURL( INetURLObject::NO_DECODE
), xEnv
, aSourceContent
) )
2083 if( ! Content::create( aTargetURL
, xEnv
, aTargetGroup
) )
2086 // transfer source file
2089 if( ! aTargetGroup
.transferContent( aSourceContent
,
2090 InsertOperation_COPY
,
2091 aNewTemplateTargetName
,
2092 NameClash::OVERWRITE
) )
2095 // allow to edit the added template
2096 Content aResultContent
;
2097 if ( Content::create( aNewTemplateTargetURL
, xEnv
, aResultContent
) )
2099 ::rtl::OUString
aPropertyName( "IsReadOnly" );
2101 sal_Bool bReadOnly
= sal_False
;
2102 if ( getProperty( aResultContent
, aPropertyName
, aProperty
) && ( aProperty
>>= bReadOnly
) && bReadOnly
)
2103 setProperty( aResultContent
, aPropertyName
, uno::makeAny( (sal_Bool
)sal_False
) );
2106 catch ( ContentCreationException
& )
2107 { return sal_False
; }
2108 catch ( Exception
& )
2109 { return sal_False
; }
2112 // either the document has title and it is the same as requested, or we have to set it
2113 sal_Bool bCorrectTitle
= ( bDocHasTitle
&& aTitle
.equals( rTemplateName
) );
2114 if ( !bCorrectTitle
)
2116 if ( !bDocHasTitle
)
2118 INetURLObject
aNewTmpObj( aNewTemplateTargetObj
);
2119 aNewTmpObj
.CutExtension();
2120 bCorrectTitle
= ( aNewTmpObj
.getName( INetURLObject::LAST_SEGMENT
, true, INetURLObject::DECODE_WITH_CHARSET
).equals( rTemplateName
) );
2123 if ( !bCorrectTitle
)
2124 bCorrectTitle
= setTitleForURL( aNewTemplateTargetURL
, rTemplateName
);
2127 if ( bCorrectTitle
)
2129 // create a new entry in the hierarchy
2130 return addEntry( aGroup
, rTemplateName
, aNewTemplateTargetURL
, aType
);
2133 // TODO/LATER: The user could be notified here that the renaming has failed
2134 // create a new entry in the hierarchy
2135 addEntry( aGroup
, aTitle
, aNewTemplateTargetURL
, aType
);
2139 //-----------------------------------------------------------------------------
2140 sal_Bool
SfxDocTplService_Impl::removeTemplate( const OUString
& rGroupName
,
2141 const OUString
& rTemplateName
)
2143 ::osl::MutexGuard
aGuard( maMutex
);
2145 // Check, whether or not there is a group with this name
2146 // Return false, if there is no group with the given name
2147 Content aGroup
, aTemplate
;
2148 OUString aGroupURL
, aTemplateURL
;
2149 INetURLObject
aGroupObj( maRootURL
);
2151 aGroupObj
.insertName( rGroupName
, false,
2152 INetURLObject::LAST_SEGMENT
, true,
2153 INetURLObject::ENCODE_ALL
);
2154 aGroupURL
= aGroupObj
.GetMainURL( INetURLObject::NO_DECODE
);
2156 if ( ! Content::create( aGroupURL
, maCmdEnv
, aGroup
) )
2159 // Check, if there's a template with the given name in this group
2160 // Return false, if there is no template
2161 aGroupObj
.insertName( rTemplateName
, false,
2162 INetURLObject::LAST_SEGMENT
, true,
2163 INetURLObject::ENCODE_ALL
);
2164 aTemplateURL
= aGroupObj
.GetMainURL( INetURLObject::NO_DECODE
);
2166 if ( !Content::create( aTemplateURL
, maCmdEnv
, aTemplate
) )
2169 // get the target URL from the template
2170 OUString aTargetURL
;
2171 OUString
aPropName( TARGET_URL
);
2174 if ( getProperty( aTemplate
, aPropName
, aValue
) )
2175 aValue
>>= aTargetURL
;
2177 // delete the target template
2178 if ( !aTargetURL
.isEmpty() )
2180 if ( !maTemplateDirs
.getLength()
2181 || !::utl::UCBContentHelper::IsSubPath( maTemplateDirs
[ maTemplateDirs
.getLength() - 1 ], aTargetURL
) )
2184 removeContent( aTargetURL
);
2187 // delete the template entry
2188 return removeContent( aTemplate
);
2191 //-----------------------------------------------------------------------------
2192 sal_Bool
SfxDocTplService_Impl::renameTemplate( const OUString
& rGroupName
,
2193 const OUString
& rOldName
,
2194 const OUString
& rNewName
)
2196 ::osl::MutexGuard
aGuard( maMutex
);
2198 // Check, whether or not there is a group with this name
2199 // Return false, if there is no group with the given name
2200 Content aGroup
, aTemplate
;
2201 OUString aGroupURL
, aTemplateURL
;
2202 INetURLObject
aGroupObj( maRootURL
);
2204 aGroupObj
.insertName( rGroupName
, false,
2205 INetURLObject::LAST_SEGMENT
, true,
2206 INetURLObject::ENCODE_ALL
);
2207 aGroupURL
= aGroupObj
.GetMainURL( INetURLObject::NO_DECODE
);
2209 if ( ! Content::create( aGroupURL
, maCmdEnv
, aGroup
) )
2212 // Check, if there's a template with the new name in this group
2213 // Return false, if there is one
2214 aGroupObj
.insertName( rNewName
, false,
2215 INetURLObject::LAST_SEGMENT
, true,
2216 INetURLObject::ENCODE_ALL
);
2217 aTemplateURL
= aGroupObj
.GetMainURL( INetURLObject::NO_DECODE
);
2219 if ( Content::create( aTemplateURL
, maCmdEnv
, aTemplate
) )
2222 // Check, if there's a template with the old name in this group
2223 // Return false, if there is no template
2224 aGroupObj
.removeSegment();
2225 aGroupObj
.insertName( rOldName
, false,
2226 INetURLObject::LAST_SEGMENT
, true,
2227 INetURLObject::ENCODE_ALL
);
2228 aTemplateURL
= aGroupObj
.GetMainURL( INetURLObject::NO_DECODE
);
2230 if ( !Content::create( aTemplateURL
, maCmdEnv
, aTemplate
) )
2233 OUString aTemplateTargetURL
;
2234 OUString
aTargetProp( TARGET_URL
);
2237 if ( getProperty( aTemplate
, aTargetProp
, aTargetValue
) )
2238 aTargetValue
>>= aTemplateTargetURL
;
2240 if ( !setTitleForURL( aTemplateTargetURL
, rNewName
) )
2243 // rename the template entry in the cache
2244 OUString
aTitleProp( TITLE
);
2246 aTitleValue
<<= rNewName
;
2248 return setProperty( aTemplate
, aTitleProp
, aTitleValue
);
2251 //-----------------------------------------------------------------------------
2253 SFX_IMPL_XSERVICEINFO( SfxDocTplService
, TEMPLATE_SERVICE_NAME
, TEMPLATE_IMPLEMENTATION_NAME
)
2254 SFX_IMPL_SINGLEFACTORY( SfxDocTplService
)
2256 //-----------------------------------------------------------------------------
2257 SfxDocTplService::SfxDocTplService( const uno::Reference
< XMultiServiceFactory
>& xFactory
)
2259 pImp
= new SfxDocTplService_Impl( xFactory
);
2262 //-----------------------------------------------------------------------------
2264 SfxDocTplService::~SfxDocTplService()
2269 //-----------------------------------------------------------------------------
2270 //--- XLocalizable ---
2271 //-----------------------------------------------------------------------------
2273 Locale SAL_CALL
SfxDocTplService::getLocale()
2274 throw( RUNTIMEEXCEPTION
)
2276 return pImp
->getLocale();
2279 //-----------------------------------------------------------------------------
2281 void SAL_CALL
SfxDocTplService::setLocale( const Locale
& rLocale
)
2282 throw( RUNTIMEEXCEPTION
)
2284 pImp
->setLocale( rLocale
);
2287 //-----------------------------------------------------------------------------
2288 //--- XDocumentTemplates ---
2289 //-----------------------------------------------------------------------------
2290 uno::Reference
< XCONTENT
> SAL_CALL
SfxDocTplService::getContent()
2291 throw( RUNTIMEEXCEPTION
)
2294 return pImp
->getContent().get();
2299 //-----------------------------------------------------------------------------
2300 sal_Bool SAL_CALL
SfxDocTplService::storeTemplate( const OUString
& GroupName
,
2301 const OUString
& TemplateName
,
2302 const uno::Reference
< XSTORABLE
>& Storable
)
2303 throw( RUNTIMEEXCEPTION
)
2306 return pImp
->storeTemplate( GroupName
, TemplateName
, Storable
);
2311 //-----------------------------------------------------------------------------
2312 sal_Bool SAL_CALL
SfxDocTplService::addTemplate( const OUString
& rGroupName
,
2313 const OUString
& rTemplateName
,
2314 const OUString
& rSourceURL
)
2315 throw( RUNTIMEEXCEPTION
)
2318 return pImp
->addTemplate( rGroupName
, rTemplateName
, rSourceURL
);
2323 //-----------------------------------------------------------------------------
2324 sal_Bool SAL_CALL
SfxDocTplService::removeTemplate( const OUString
& rGroupName
,
2325 const OUString
& rTemplateName
)
2326 throw( RUNTIMEEXCEPTION
)
2329 return pImp
->removeTemplate( rGroupName
, rTemplateName
);
2334 //-----------------------------------------------------------------------------
2335 sal_Bool SAL_CALL
SfxDocTplService::renameTemplate( const OUString
& rGroupName
,
2336 const OUString
& rOldName
,
2337 const OUString
& rNewName
)
2338 throw( RUNTIMEEXCEPTION
)
2340 if ( rOldName
== rNewName
)
2344 return pImp
->renameTemplate( rGroupName
, rOldName
, rNewName
);
2349 //-----------------------------------------------------------------------------
2350 sal_Bool SAL_CALL
SfxDocTplService::addGroup( const OUString
& rGroupName
)
2351 throw( RUNTIMEEXCEPTION
)
2354 return pImp
->addGroup( rGroupName
);
2359 //-----------------------------------------------------------------------------
2360 sal_Bool SAL_CALL
SfxDocTplService::removeGroup( const OUString
& rGroupName
)
2361 throw( RUNTIMEEXCEPTION
)
2364 return pImp
->removeGroup( rGroupName
);
2369 //-----------------------------------------------------------------------------
2370 sal_Bool SAL_CALL
SfxDocTplService::renameGroup( const OUString
& rOldName
,
2371 const OUString
& rNewName
)
2372 throw( RUNTIMEEXCEPTION
)
2374 if ( rOldName
== rNewName
)
2378 return pImp
->renameGroup( rOldName
, rNewName
);
2383 //-----------------------------------------------------------------------------
2384 void SAL_CALL
SfxDocTplService::update()
2385 throw( RUNTIMEEXCEPTION
)
2388 pImp
->update( sal_True
);
2391 //------------------------------------------------------------------------
2393 Updater_Impl::Updater_Impl( SfxDocTplService_Impl
* pTemplates
)
2395 mpDocTemplates
= pTemplates
;
2398 //------------------------------------------------------------------------
2399 Updater_Impl::~Updater_Impl()
2403 //------------------------------------------------------------------------
2404 void SAL_CALL
Updater_Impl::run()
2406 mpDocTemplates
->doUpdate();
2409 //------------------------------------------------------------------------
2410 void SAL_CALL
Updater_Impl::onTerminated()
2412 mpDocTemplates
->finished();
2416 //-----------------------------------------------------------------------------
2417 WaitWindow_Impl::WaitWindow_Impl()
2418 : WorkWindow( NULL
, WB_BORDER
| WB_3DLOOK
)
2420 Rectangle aRect
= Rectangle( 0, 0, 300, 30000 );
2421 _nTextStyle
= TEXT_DRAW_CENTER
| TEXT_DRAW_VCENTER
| TEXT_DRAW_WORDBREAK
| TEXT_DRAW_MULTILINE
;
2422 _aText
= String( SfxResId( RID_CNT_STR_WAITING
) );
2423 _aRect
= GetTextRect( aRect
, _aText
, _nTextStyle
);
2425 aRect
.Right() += 2*X_OFFSET
;
2426 aRect
.Bottom() += 2*Y_OFFSET
;
2427 _aRect
.SetPos( Point( X_OFFSET
, Y_OFFSET
) );
2428 SetOutputSizePixel( aRect
.GetSize() );
2434 //-----------------------------------------------------------------------------
2435 WaitWindow_Impl::~WaitWindow_Impl()
2440 //-----------------------------------------------------------------------------
2441 void WaitWindow_Impl::Paint( const Rectangle
& /*rRect*/ )
2443 DrawText( _aRect
, _aText
, _nTextStyle
);
2446 //-----------------------------------------------------------------------------
2447 void SfxDocTplService_Impl::addHierGroup( GroupList_Impl
& rList
,
2448 const OUString
& rTitle
,
2449 const OUString
& rOwnURL
)
2451 // now get the content of the Group
2453 uno::Reference
< XResultSet
> xResultSet
;
2454 Sequence
< OUString
> aProps(3);
2456 aProps
[0] = OUString(TITLE
);
2457 aProps
[1] = OUString(TARGET_URL
);
2458 aProps
[2] = OUString(PROPERTY_TYPE
);
2462 aContent
= Content( rOwnURL
, maCmdEnv
);
2463 ResultSetInclude eInclude
= INCLUDE_DOCUMENTS_ONLY
;
2464 xResultSet
= aContent
.createCursor( aProps
, eInclude
);
2466 catch ( ContentCreationException
& )
2468 SAL_WARN( "sfx2.doc", "addHierGroup: ContentCreationException" );
2470 catch ( Exception
& ) {}
2472 if ( xResultSet
.is() )
2474 GroupData_Impl
*pGroup
= new GroupData_Impl( rTitle
);
2475 pGroup
->setHierarchy( sal_True
);
2476 pGroup
->setHierarchyURL( rOwnURL
);
2477 rList
.push_back( pGroup
);
2479 uno::Reference
< XContentAccess
> xContentAccess( xResultSet
, UNO_QUERY
);
2480 uno::Reference
< XRow
> xRow( xResultSet
, UNO_QUERY
);
2484 while ( xResultSet
->next() )
2486 sal_Bool bUpdateType
= sal_False
;
2487 DocTemplates_EntryData_Impl
*pData
;
2489 OUString
aTitle( xRow
->getString( 1 ) );
2490 OUString
aTargetDir( xRow
->getString( 2 ) );
2491 OUString
aType( xRow
->getString( 3 ) );
2492 OUString aHierURL
= xContentAccess
->queryContentIdentifierString();
2494 if ( aType
.isEmpty() )
2498 sal_Bool bDocHasTitle
= sal_False
;
2499 if( !getTitleFromURL( aTargetDir
, aTmpTitle
, aType
, bDocHasTitle
) )
2501 SAL_WARN( "sfx2.doc", "addHierGroup(): template of alien format" );
2505 if ( !aType
.isEmpty() )
2506 bUpdateType
= sal_True
;
2509 pData
= pGroup
->addEntry( aTitle
, aTargetDir
, aType
, aHierURL
);
2510 pData
->setUpdateType( bUpdateType
);
2513 catch ( Exception
& ) {}
2517 //-----------------------------------------------------------------------------
2518 void SfxDocTplService_Impl::addFsysGroup( GroupList_Impl
& rList
,
2519 const OUString
& rTitle
,
2520 const OUString
& rUITitle
,
2521 const OUString
& rOwnURL
,
2522 sal_Bool bWriteableGroup
)
2524 ::rtl::OUString aTitle
;
2526 if ( rUITitle
.isEmpty() )
2528 // reserved FS names that should not be used
2529 if ( rTitle
.compareToAscii( "wizard" ) == 0 )
2531 else if ( rTitle
.compareToAscii( "internal" ) == 0 )
2534 aTitle
= getLongName( rTitle
);
2539 if ( aTitle
.isEmpty() )
2542 GroupData_Impl
* pGroup
= NULL
;
2543 for ( size_t i
= 0, n
= rList
.size(); i
< n
; ++i
)
2545 if ( rList
[ i
]->getTitle() == aTitle
)
2547 pGroup
= rList
[ i
];
2554 pGroup
= new GroupData_Impl( aTitle
);
2555 rList
.push_back( pGroup
);
2558 if ( bWriteableGroup
)
2559 pGroup
->setTargetURL( rOwnURL
);
2563 // now get the content of the Group
2565 uno::Reference
< XResultSet
> xResultSet
;
2566 Sequence
< OUString
> aProps(1);
2567 aProps
[0] = OUString(TITLE
);
2571 // this method is only used during checking of the available template-folders
2572 // that should happen quietly
2573 uno::Reference
< XCommandEnvironment
> aQuietEnv
;
2574 aContent
= Content( rOwnURL
, aQuietEnv
);
2575 ResultSetInclude eInclude
= INCLUDE_DOCUMENTS_ONLY
;
2576 xResultSet
= aContent
.createCursor( aProps
, eInclude
);
2578 catch ( Exception
& ) {}
2580 if ( xResultSet
.is() )
2582 uno::Reference
< XContentAccess
> xContentAccess( xResultSet
, UNO_QUERY
);
2583 uno::Reference
< XRow
> xRow( xResultSet
, UNO_QUERY
);
2587 while ( xResultSet
->next() )
2589 OUString
aChildTitle( xRow
->getString( 1 ) );
2590 OUString aTargetURL
= xContentAccess
->queryContentIdentifierString();
2594 if ( aChildTitle
.compareToAscii( "sfx.tlx" ) == 0 || aChildTitle
== "groupuinames.xml" )
2597 // only StarOffice templates are accepted
2598 sal_Bool bDocHasTitle
= sal_False
;
2599 if( !getTitleFromURL( aTargetURL
, aChildTitle
, aType
, bDocHasTitle
) )
2602 pGroup
->addEntry( aChildTitle
, aTargetURL
, aType
, aHierURL
);
2605 catch ( Exception
& ) {}
2609 // -----------------------------------------------------------------------
2610 void SfxDocTplService_Impl::createFromContent( GroupList_Impl
& rList
,
2612 sal_Bool bHierarchy
,
2613 sal_Bool bWriteableContent
)
2615 OUString aTargetURL
= rContent
.get()->getIdentifier()->getContentIdentifier();
2617 // when scanning the file system, we have to add the 'standard' group, too
2620 OUString aUIStdTitle
= getLongName( OUString( STANDARD_FOLDER
) );
2621 addFsysGroup( rList
, ::rtl::OUString(), aUIStdTitle
, aTargetURL
, bWriteableContent
);
2624 // search for predefined UI names
2625 INetURLObject
aLayerObj( aTargetURL
);
2627 // TODO/LATER: Use hashmap in future
2628 uno::Sequence
< beans::StringPair
> aUINames
;
2630 aUINames
= ReadUINamesForTemplateDir_Impl( aLayerObj
.GetMainURL( INetURLObject::NO_DECODE
) );
2632 uno::Reference
< XResultSet
> xResultSet
;
2633 Sequence
< OUString
> aProps(1);
2634 aProps
[0] = OUString(TITLE
);
2638 ResultSetInclude eInclude
= INCLUDE_FOLDERS_ONLY
;
2639 xResultSet
= rContent
.createCursor( aProps
, eInclude
);
2641 catch ( Exception
& ) {}
2643 if ( xResultSet
.is() )
2645 uno::Reference
< XContentAccess
> xContentAccess( xResultSet
, UNO_QUERY
);
2646 uno::Reference
< XRow
> xRow( xResultSet
, UNO_QUERY
);
2650 while ( xResultSet
->next() )
2652 // TODO/LATER: clarify the encoding of the Title
2653 OUString
aTitle( xRow
->getString( 1 ) );
2654 OUString
aTargetSubfolderURL( xContentAccess
->queryContentIdentifierString() );
2657 addHierGroup( rList
, aTitle
, aTargetSubfolderURL
);
2660 ::rtl::OUString aUITitle
;
2661 for ( sal_Int32 nInd
= 0; nInd
< aUINames
.getLength(); nInd
++ )
2662 if ( aUINames
[nInd
].First
.equals( aTitle
) )
2664 aUITitle
= aUINames
[nInd
].Second
;
2668 addFsysGroup( rList
, aTitle
, aUITitle
, aTargetSubfolderURL
, bWriteableContent
);
2672 catch ( Exception
& ) {}
2676 //-----------------------------------------------------------------------------
2677 void SfxDocTplService_Impl::removeFromHierarchy( DocTemplates_EntryData_Impl
*pData
)
2681 if ( Content::create( pData
->getHierarchyURL(), maCmdEnv
, aTemplate
) )
2683 removeContent( aTemplate
);
2687 //-----------------------------------------------------------------------------
2688 void SfxDocTplService_Impl::addToHierarchy( GroupData_Impl
*pGroup
,
2689 DocTemplates_EntryData_Impl
*pData
)
2691 Content aGroup
, aTemplate
;
2693 if ( ! Content::create( pGroup
->getHierarchyURL(), maCmdEnv
, aGroup
) )
2696 // Check, if there's a template with the given name in this group
2697 // Return if there is already a template
2698 INetURLObject
aGroupObj( pGroup
->getHierarchyURL() );
2700 aGroupObj
.insertName( pData
->getTitle(), false,
2701 INetURLObject::LAST_SEGMENT
, true,
2702 INetURLObject::ENCODE_ALL
);
2704 OUString aTemplateURL
= aGroupObj
.GetMainURL( INetURLObject::NO_DECODE
);
2706 if ( Content::create( aTemplateURL
, maCmdEnv
, aTemplate
) )
2709 addEntry( aGroup
, pData
->getTitle(),
2710 pData
->getTargetURL(),
2714 //-----------------------------------------------------------------------------
2715 void SfxDocTplService_Impl::updateData( DocTemplates_EntryData_Impl
*pData
)
2719 if ( ! Content::create( pData
->getHierarchyURL(), maCmdEnv
, aTemplate
) )
2724 if ( pData
->getUpdateType() )
2726 aPropName
= OUString( PROPERTY_TYPE
);
2727 setProperty( aTemplate
, aPropName
, makeAny( pData
->getType() ) );
2730 if ( pData
->getUpdateLink() )
2732 aPropName
= OUString( TARGET_URL
);
2733 setProperty( aTemplate
, aPropName
, makeAny( pData
->getTargetURL() ) );
2737 //-----------------------------------------------------------------------------
2738 void SfxDocTplService_Impl::addGroupToHierarchy( GroupData_Impl
*pGroup
)
2740 OUString
aAdditionalProp( TARGET_DIR_URL
);
2743 INetURLObject
aNewGroupObj( maRootURL
);
2744 aNewGroupObj
.insertName( pGroup
->getTitle(), false,
2745 INetURLObject::LAST_SEGMENT
, true,
2746 INetURLObject::ENCODE_ALL
);
2748 OUString aNewGroupURL
= aNewGroupObj
.GetMainURL( INetURLObject::NO_DECODE
);
2750 if ( createFolder( aNewGroupURL
, sal_False
, sal_False
, aGroup
) )
2752 setProperty( aGroup
, aAdditionalProp
, makeAny( pGroup
->getTargetURL() ) );
2753 pGroup
->setHierarchyURL( aNewGroupURL
);
2755 sal_uIntPtr nCount
= pGroup
->count();
2756 for ( sal_uIntPtr i
=0; i
<nCount
; i
++ )
2758 DocTemplates_EntryData_Impl
*pData
= pGroup
->getEntry( i
);
2759 addToHierarchy( pGroup
, pData
); // add entry to hierarchy
2764 //-----------------------------------------------------------------------------
2765 void SfxDocTplService_Impl::removeFromHierarchy( GroupData_Impl
*pGroup
)
2769 if ( Content::create( pGroup
->getHierarchyURL(), maCmdEnv
, aGroup
) )
2771 removeContent( aGroup
);
2775 // -----------------------------------------------------------------------
2776 GroupData_Impl::GroupData_Impl( const OUString
& rTitle
)
2779 mbInUse
= sal_False
;
2780 mbInHierarchy
= sal_False
;
2783 // -----------------------------------------------------------------------
2784 GroupData_Impl::~GroupData_Impl()
2786 for ( size_t i
= 0, n
= maEntries
.size(); i
< n
; ++i
)
2787 delete maEntries
[ i
];
2791 // -----------------------------------------------------------------------
2792 DocTemplates_EntryData_Impl
* GroupData_Impl::addEntry( const OUString
& rTitle
,
2793 const OUString
& rTargetURL
,
2794 const OUString
& rType
,
2795 const OUString
& rHierURL
)
2797 DocTemplates_EntryData_Impl
* pData
= NULL
;
2798 bool EntryFound
= false;
2800 for ( size_t i
= 0, n
= maEntries
.size(); i
< n
; ++i
)
2802 pData
= maEntries
[ i
];
2803 if ( pData
->getTitle() == rTitle
)
2812 pData
= new DocTemplates_EntryData_Impl( rTitle
);
2813 pData
->setTargetURL( rTargetURL
);
2814 pData
->setType( rType
);
2815 if ( !rHierURL
.isEmpty() )
2817 pData
->setHierarchyURL( rHierURL
);
2818 pData
->setHierarchy( sal_True
);
2820 maEntries
.push_back( pData
);
2824 if ( !rHierURL
.isEmpty() )
2826 pData
->setHierarchyURL( rHierURL
);
2827 pData
->setHierarchy( sal_True
);
2830 if ( pData
->getInHierarchy() )
2833 if ( rTargetURL
!= pData
->getTargetURL() )
2835 pData
->setTargetURL( rTargetURL
);
2836 pData
->setUpdateLink( sal_True
);
2843 // -----------------------------------------------------------------------
2844 DocTemplates_EntryData_Impl::DocTemplates_EntryData_Impl( const OUString
& rTitle
)
2847 mbInUse
= sal_False
;
2848 mbInHierarchy
= sal_False
;
2849 mbUpdateType
= sal_False
;
2850 mbUpdateLink
= sal_False
;
2853 // -----------------------------------------------------------------------
2854 SfxURLRelocator_Impl::SfxURLRelocator_Impl( uno::Reference
< XMultiServiceFactory
> xFactory
)
2855 : mxFactory( xFactory
)
2859 // -----------------------------------------------------------------------
2860 SfxURLRelocator_Impl::~SfxURLRelocator_Impl()
2864 // -----------------------------------------------------------------------
2865 void SfxURLRelocator_Impl::initOfficeInstDirs()
2867 if ( !mxOfficeInstDirs
.is() )
2869 osl::MutexGuard
aGuard( maMutex
);
2870 if ( !mxOfficeInstDirs
.is() )
2872 OSL_ENSURE( mxFactory
.is(), "No service manager!" );
2874 uno::Reference
< XComponentContext
> xCtx
;
2875 uno::Reference
< XPropertySet
> xPropSet( mxFactory
, UNO_QUERY
);
2876 if ( xPropSet
.is() )
2878 xPropSet
->getPropertyValue(
2880 "DefaultContext" ) )
2884 OSL_ENSURE( xCtx
.is(),
2885 "Unable to obtain component context from "
2886 "service manager!" );
2890 xCtx
->getValueByName(
2893 "com.sun.star.util.theOfficeInstallationDirectories" ) )
2894 >>= mxOfficeInstDirs
;
2897 OSL_ENSURE( mxOfficeInstDirs
.is(),
2898 "Unable to obtain office installation directory "
2904 // -----------------------------------------------------------------------
2905 void SfxURLRelocator_Impl::implExpandURL( ::rtl::OUString
& io_url
)
2907 const INetURLObject
aParser( io_url
);
2908 if ( aParser
.GetProtocol() != INET_PROT_VND_SUN_STAR_EXPAND
)
2911 io_url
= aParser
.GetURLPath( INetURLObject::DECODE_WITH_CHARSET
);
2914 if ( !mxMacroExpander
.is() )
2916 ::comphelper::ComponentContext
aContext( mxFactory
);
2917 mxMacroExpander
.set( aContext
.getSingleton( "com.sun.star.util.theMacroExpander" ), UNO_QUERY_THROW
);
2919 io_url
= mxMacroExpander
->expandMacros( io_url
);
2921 catch( const Exception
& )
2923 DBG_UNHANDLED_EXCEPTION();
2927 // -----------------------------------------------------------------------
2928 void SfxURLRelocator_Impl::makeRelocatableURL( rtl::OUString
& rURL
)
2930 if ( !rURL
.isEmpty() )
2932 initOfficeInstDirs();
2933 implExpandURL( rURL
);
2934 rURL
= mxOfficeInstDirs
->makeRelocatableURL( rURL
);
2938 // -----------------------------------------------------------------------
2939 void SfxURLRelocator_Impl::makeAbsoluteURL( rtl::OUString
& rURL
)
2941 if ( !rURL
.isEmpty() )
2943 initOfficeInstDirs();
2944 implExpandURL( rURL
);
2945 rURL
= mxOfficeInstDirs
->makeAbsoluteURL( rURL
);
2950 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */