update dev300-m58
[ooovba.git] / sfx2 / source / doc / doctemplates.cxx
blob9d5ee078e2423948ac50a2fd49f80b7d8fc66032
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: doctemplates.cxx,v $
10 * $Revision: 1.42.84.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sfx2.hxx"
34 #include "doctemplates.hxx"
35 #include <vos/mutex.hxx>
36 #include <tools/debug.hxx>
37 #include <tools/urlobj.hxx>
38 #include <rtl/ustring.hxx>
39 #include <rtl/ustrbuf.hxx>
40 #include <osl/file.hxx>
41 #ifndef _SV_RESARY_HXX
42 #include <tools/resary.hxx>
43 #endif
44 #include <vcl/svapp.hxx>
45 #include <vcl/wrkwin.hxx>
46 #include <comphelper/sequenceashashmap.hxx>
47 #include <svtools/pathoptions.hxx>
48 #include <comphelper/processfactory.hxx>
49 #include <com/sun/star/beans/PropertyAttribute.hpp>
50 #include <com/sun/star/beans/XPropertySet.hpp>
51 #include <com/sun/star/beans/XPropertySetInfo.hpp>
52 #include <com/sun/star/beans/XPropertyContainer.hpp>
53 #include <com/sun/star/beans/StringPair.hpp>
54 #include <com/sun/star/util/XMacroExpander.hpp>
55 #include <com/sun/star/container/XContainerQuery.hpp>
56 #include <com/sun/star/document/XTypeDetection.hpp>
57 #include <com/sun/star/document/XStandaloneDocumentInfo.hpp>
58 #include <com/sun/star/sdbc/XResultSet.hpp>
59 #include <com/sun/star/sdbc/XRow.hpp>
60 #include <com/sun/star/ucb/NameClash.hpp>
61 #include <com/sun/star/ucb/NameClashException.hpp>
62 #include <com/sun/star/ucb/TransferInfo.hpp>
63 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
64 #include <com/sun/star/ucb/XContentAccess.hpp>
65 #include <com/sun/star/frame/XModuleManager.hpp>
66 #include <com/sun/star/uno/Exception.hpp>
67 #include <com/sun/star/util/XOfficeInstallationDirectories.hpp>
69 #include <svtools/templatefoldercache.hxx>
70 #include <unotools/configmgr.hxx>
71 #include <unotools/ucbhelper.hxx>
73 #include "sfxresid.hxx"
74 #include "sfxurlrelocator.hxx"
75 #include "doctemplateslocal.hxx"
76 #include <sfx2/docfac.hxx>
77 #include "doc.hrc"
79 //-----------------------------------------------------------------------------
81 //=============================================================================
83 #define TEMPLATE_SERVICE_NAME "com.sun.star.frame.DocumentTemplates"
84 #define TEMPLATE_IMPLEMENTATION_NAME "com.sun.star.comp.sfx2.DocumentTemplates"
86 #define SERVICENAME_TYPEDETECTION "com.sun.star.document.TypeDetection"
87 #define SERVICENAME_DOCINFO "com.sun.star.document.StandaloneDocumentInfo"
89 #define TEMPLATE_ROOT_URL "vnd.sun.star.hier:/templates"
90 #define TITLE "Title"
91 #define IS_FOLDER "IsFolder"
92 #define IS_DOCUMENT "IsDocument"
93 #define TARGET_URL "TargetURL"
94 #define TEMPLATE_VERSION "TemplateComponentVersion"
95 #define TEMPLATE_VERSION_VALUE "2"
96 #define TYPE_FOLDER "application/vnd.sun.star.hier-folder"
97 #define TYPE_LINK "application/vnd.sun.star.hier-link"
98 #define TYPE_FSYS_FOLDER "application/vnd.sun.staroffice.fsys-folder"
99 #define TYPE_FSYS_FILE "application/vnd.sun.staroffice.fsys-file"
101 #define PROPERTY_DIRLIST "DirectoryList"
102 #define PROPERTY_NEEDSUPDATE "NeedsUpdate"
103 #define PROPERTY_TYPE "TypeDescription"
105 #define TARGET_DIR_URL "TargetDirURL"
106 #define COMMAND_DELETE "delete"
107 #define COMMAND_TRANSFER "transfer"
109 #define STANDARD_FOLDER "standard"
111 #define C_DELIM ';'
113 //=============================================================================
115 using namespace ::com::sun::star;
116 using namespace ::com::sun::star::beans;
117 using namespace ::com::sun::star::document;
118 using namespace ::com::sun::star::io;
119 using namespace ::com::sun::star::lang;
120 using namespace ::com::sun::star::sdbc;
121 using namespace ::com::sun::star::ucb;
122 using namespace ::com::sun::star::uno;
123 using namespace ::com::sun::star::container;
124 using namespace ::com::sun::star::util;
126 using namespace ::rtl;
127 using namespace ::ucbhelper;
128 using namespace ::comphelper;
130 //=============================================================================
132 class WaitWindow_Impl : public WorkWindow
134 Rectangle _aRect;
135 USHORT _nTextStyle;
136 String _aText;
138 public:
139 WaitWindow_Impl();
140 ~WaitWindow_Impl();
141 virtual void Paint( const Rectangle& rRect );
144 #define X_OFFSET 15
145 #define Y_OFFSET 15
147 //=============================================================================
149 struct NamePair_Impl
151 OUString maShortName;
152 OUString maLongName;
155 DECLARE_LIST( NameList_Impl, NamePair_Impl* )
157 class Updater_Impl;
158 class GroupList_Impl;
159 class DocTemplates_EntryData_Impl;
160 class GroupData_Impl;
162 //=============================================================================
163 #include <com/sun/star/task/XInteractionHandler.hpp>
164 #include <com/sun/star/ucb/XProgressHandler.hpp>
165 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
167 class TplTaskEnvironment : public ::cppu::WeakImplHelper1< ucb::XCommandEnvironment >
169 uno::Reference< task::XInteractionHandler > m_xInteractionHandler;
170 uno::Reference< ucb::XProgressHandler > m_xProgressHandler;
172 public:
173 TplTaskEnvironment( const uno::Reference< task::XInteractionHandler>& rxInteractionHandler )
174 : m_xInteractionHandler( rxInteractionHandler )
177 virtual uno::Reference<task::XInteractionHandler> SAL_CALL getInteractionHandler() throw (uno::RuntimeException)
178 { return m_xInteractionHandler; }
180 virtual uno::Reference<ucb::XProgressHandler> SAL_CALL getProgressHandler() throw (uno::RuntimeException)
181 { return m_xProgressHandler; }
184 class SfxDocTplService_Impl
186 uno::Reference< XMultiServiceFactory > mxFactory;
187 uno::Reference< XCommandEnvironment > maCmdEnv;
188 uno::Reference< XStandaloneDocumentInfo > mxInfo;
189 uno::Reference< XTypeDetection > mxType;
191 ::osl::Mutex maMutex;
192 Sequence< OUString > maTemplateDirs;
193 OUString maRootURL;
194 NameList_Impl maNames;
195 Locale maLocale;
196 Content maRootContent;
197 Updater_Impl* mpUpdater;
198 sal_Bool mbIsInitialized : 1;
199 sal_Bool mbLocaleSet : 1;
201 SfxURLRelocator_Impl maRelocator;
203 void init_Impl();
204 void getDefaultLocale();
205 void getDirList();
206 void readFolderList();
207 sal_Bool needsUpdate();
208 OUString getLongName( const OUString& rShortName );
209 sal_Bool setTitleForURL( const OUString& rURL, const OUString& aTitle );
210 sal_Bool getTitleFromURL( const OUString& rURL, OUString& aTitle, OUString& aType, sal_Bool& bDocHasTitle );
212 sal_Bool addEntry( Content& rParentFolder,
213 const OUString& rTitle,
214 const OUString& rTargetURL,
215 const OUString& rType );
217 sal_Bool createFolder( const OUString& rNewFolderURL,
218 sal_Bool bCreateParent,
219 sal_Bool bFsysFolder,
220 Content &rNewFolder );
222 sal_Bool CreateNewUniqueFolderWithPrefix( const ::rtl::OUString& aPath,
223 const ::rtl::OUString& aPrefix,
224 ::rtl::OUString& aNewFolderName,
225 ::rtl::OUString& aNewFolderURL,
226 Content& aNewFolder );
227 ::rtl::OUString CreateNewUniqueFileWithPrefix( const ::rtl::OUString& aPath,
228 const ::rtl::OUString& aPrefix,
229 const ::rtl::OUString& aExt );
231 uno::Sequence< beans::StringPair > ReadUINamesForTemplateDir_Impl( const ::rtl::OUString& aUserPath );
232 sal_Bool UpdateUINamesForTemplateDir_Impl( const ::rtl::OUString& aUserPath,
233 const ::rtl::OUString& aGroupName,
234 const ::rtl::OUString& aNewFolderName );
235 sal_Bool ReplaceUINamesForTemplateDir_Impl( const ::rtl::OUString& aUserPath,
236 const ::rtl::OUString& aFsysGroupName,
237 const ::rtl::OUString& aOldGroupName,
238 const ::rtl::OUString& aNewGroupName );
239 sal_Bool RemoveUINamesForTemplateDir_Impl( const ::rtl::OUString& aUserPath,
240 const ::rtl::OUString& aGroupName );
241 sal_Bool WriteUINamesForTemplateDir_Impl( const ::rtl::OUString& aUserPath,
242 const uno::Sequence< beans::StringPair >& aUINames );
244 ::rtl::OUString CreateNewGroupFsys( const ::rtl::OUString& rGroupName, Content& aGroup );
246 sal_Bool removeContent( Content& rContent );
247 sal_Bool removeContent( const OUString& rContentURL );
249 sal_Bool setProperty( Content& rContent,
250 const OUString& rPropName,
251 const Any& rPropValue );
252 sal_Bool getProperty( Content& rContent,
253 const OUString& rPropName,
254 Any& rPropValue );
256 void createFromContent( GroupList_Impl& rList,
257 Content &rContent,
258 sal_Bool bHierarchy,
259 sal_Bool bWriteableContent = sal_False );
260 void addHierGroup( GroupList_Impl& rList,
261 const OUString& rTitle,
262 const OUString& rOwnURL );
263 void addFsysGroup( GroupList_Impl& rList,
264 const OUString& rTitle,
265 const OUString& rUITitle,
266 const OUString& rOwnURL,
267 sal_Bool bWriteableGroup = sal_False );
268 void removeFromHierarchy( DocTemplates_EntryData_Impl *pData );
269 void addToHierarchy( GroupData_Impl *pGroup,
270 DocTemplates_EntryData_Impl *pData );
272 void removeFromHierarchy( GroupData_Impl *pGroup );
273 void addGroupToHierarchy( GroupData_Impl *pGroup );
275 void updateData( DocTemplates_EntryData_Impl *pData );
277 public:
278 SfxDocTplService_Impl( uno::Reference< XMultiServiceFactory > xFactory );
279 ~SfxDocTplService_Impl();
281 sal_Bool init() { if ( !mbIsInitialized ) init_Impl(); return mbIsInitialized; }
282 Content getContent() { return maRootContent; }
284 void setLocale( const Locale & rLocale );
285 Locale getLocale();
287 sal_Bool storeTemplate( const OUString& rGroupName,
288 const OUString& rTemplateName,
289 const uno::Reference< XSTORABLE >& rStorable );
291 sal_Bool addTemplate( const OUString& rGroupName,
292 const OUString& rTemplateName,
293 const OUString& rSourceURL );
294 sal_Bool removeTemplate( const OUString& rGroupName,
295 const OUString& rTemplateName );
296 sal_Bool renameTemplate( const OUString& rGroupName,
297 const OUString& rOldName,
298 const OUString& rNewName );
300 sal_Bool addGroup( const OUString& rGroupName );
301 sal_Bool removeGroup( const OUString& rGroupName );
302 sal_Bool renameGroup( const OUString& rOldName,
303 const OUString& rNewName );
305 void update( sal_Bool bUpdateNow );
306 void doUpdate();
307 void finished() { mpUpdater = NULL; }
310 //=============================================================================
312 class Updater_Impl : public ::vos::OThread
314 private:
315 SfxDocTplService_Impl *mpDocTemplates;
317 public:
318 Updater_Impl( SfxDocTplService_Impl* pTemplates );
319 ~Updater_Impl();
321 virtual void SAL_CALL run();
322 virtual void SAL_CALL onTerminated();
325 //=============================================================================
327 class DocTemplates_EntryData_Impl
329 OUString maTitle;
330 OUString maType;
331 OUString maTargetURL;
332 OUString maHierarchyURL;
334 sal_Bool mbInHierarchy : 1;
335 sal_Bool mbInUse : 1;
336 sal_Bool mbUpdateType : 1;
337 sal_Bool mbUpdateLink : 1;
339 public:
340 DocTemplates_EntryData_Impl( const OUString& rTitle );
342 void setInUse() { mbInUse = sal_True; }
343 void setHierarchy( sal_Bool bInHierarchy ) { mbInHierarchy = bInHierarchy; }
344 void setUpdateLink( sal_Bool bUpdateLink ) { mbUpdateLink = bUpdateLink; }
345 void setUpdateType( sal_Bool bUpdateType ) { mbUpdateType = bUpdateType; }
347 sal_Bool getInUse() const { return mbInUse; }
348 sal_Bool getInHierarchy() const { return mbInHierarchy; }
349 sal_Bool getUpdateLink() const { return mbUpdateLink; }
350 sal_Bool getUpdateType() const { return mbUpdateType; }
352 const OUString& getHierarchyURL() const { return maHierarchyURL; }
353 const OUString& getTargetURL() const { return maTargetURL; }
354 const OUString& getTitle() const { return maTitle; }
355 const OUString& getType() const { return maType; }
357 void setHierarchyURL( const OUString& rURL ) { maHierarchyURL = rURL; }
358 void setTargetURL( const OUString& rURL ) { maTargetURL = rURL; }
359 void setType( const OUString& rType ) { maType = rType; }
362 //=============================================================================
364 class GroupData_Impl
366 DECLARE_LIST( EntryList_Impl, DocTemplates_EntryData_Impl* )
367 EntryList_Impl maEntries;
368 OUString maTitle;
369 OUString maHierarchyURL;
370 OUString maTargetURL;
371 sal_Bool mbInUse : 1;
372 sal_Bool mbInHierarchy : 1;
374 public:
375 GroupData_Impl( const OUString& rTitle );
376 ~GroupData_Impl();
378 void setInUse() { mbInUse = sal_True; }
379 void setHierarchy( sal_Bool bInHierarchy ) { mbInHierarchy = bInHierarchy; }
380 void setHierarchyURL( const OUString& rURL ) { maHierarchyURL = rURL; }
381 void setTargetURL( const OUString& rURL ) { maTargetURL = rURL; }
383 sal_Bool getInUse() { return mbInUse; }
384 sal_Bool getInHierarchy() { return mbInHierarchy; }
385 const OUString& getHierarchyURL() const { return maHierarchyURL; }
386 const OUString& getTargetURL() const { return maTargetURL; }
387 const OUString& getTitle() const { return maTitle; }
389 DocTemplates_EntryData_Impl* addEntry( const OUString& rTitle,
390 const OUString& rTargetURL,
391 const OUString& rType,
392 const OUString& rHierURL );
393 ULONG count() { return maEntries.Count(); }
394 DocTemplates_EntryData_Impl* getEntry( ULONG nPos ) { return maEntries.GetObject( nPos ); }
397 DECLARE_LIST( GroupList_Impl, GroupData_Impl* )
399 //=============================================================================
400 //=============================================================================
401 //=============================================================================
403 //-----------------------------------------------------------------------------
404 // private SfxDocTplService_Impl
405 //-----------------------------------------------------------------------------
406 void SfxDocTplService_Impl::init_Impl()
408 uno::Reference< lang::XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory();
409 if ( xFactory.is() )
411 uno::Reference < task::XInteractionHandler > xInteractionHandler( xFactory->createInstance( DEFINE_CONST_UNICODE("com.sun.star.task.InteractionHandler") ), uno::UNO_QUERY );
412 maCmdEnv = new TplTaskEnvironment( xInteractionHandler );
415 ::osl::ClearableMutexGuard aGuard( maMutex );
416 sal_Bool bIsInitialized = sal_False;
417 sal_Bool bNeedsUpdate = sal_False;
419 if ( !mbLocaleSet )
420 getDefaultLocale();
422 // convert locale to string
423 OUString aLang = maLocale.Language;
424 aLang += String( '-' );
425 aLang += maLocale.Country;
427 // set maRootContent to the root of the templates hierarchy. Create the
428 // entry if necessary
430 maRootURL = OUString( RTL_CONSTASCII_USTRINGPARAM( TEMPLATE_ROOT_URL ) );
431 maRootURL += String( '/' );
432 maRootURL += aLang;
434 ::rtl::OUString aTemplVersPropName( RTL_CONSTASCII_USTRINGPARAM( TEMPLATE_VERSION ) );
435 ::rtl::OUString aTemplVers( RTL_CONSTASCII_USTRINGPARAM( TEMPLATE_VERSION_VALUE ) );
436 if ( Content::create( maRootURL, maCmdEnv, maRootContent ) )
438 uno::Any aValue;
439 ::rtl::OUString aPropValue;
440 if ( getProperty( maRootContent, aTemplVersPropName, aValue )
441 && ( aValue >>= aPropValue )
442 && aPropValue.equals( aTemplVers ) )
444 bIsInitialized = sal_True;
446 else
447 removeContent( maRootContent );
450 if ( !bIsInitialized )
452 if ( createFolder( maRootURL, sal_True, sal_False, maRootContent )
453 && setProperty( maRootContent, aTemplVersPropName, uno::makeAny( aTemplVers ) ) )
454 bIsInitialized = sal_True;
456 bNeedsUpdate = sal_True;
459 if ( bIsInitialized )
461 OUString aService( RTL_CONSTASCII_USTRINGPARAM( SERVICENAME_DOCINFO ) );
462 try {
463 mxInfo = uno::Reference< XStandaloneDocumentInfo > (
464 mxFactory->createInstance( aService ), UNO_QUERY );
465 } catch (uno::RuntimeException &) {
466 OSL_ENSURE(false, "SfxDocTplService_Impl::init_Impl: "
467 "cannot create DocumentProperties service");
470 aService = OUString( RTL_CONSTASCII_USTRINGPARAM( SERVICENAME_TYPEDETECTION ) );
471 mxType = uno::Reference< XTypeDetection > ( mxFactory->createInstance( aService ), UNO_QUERY );
473 getDirList();
474 readFolderList();
476 if ( bNeedsUpdate )
478 aGuard.clear();
479 ::vos::OClearableGuard aSolarGuard( Application::GetSolarMutex() );
481 WaitWindow_Impl* pWin = new WaitWindow_Impl();
483 aSolarGuard.clear();
484 ::osl::ClearableMutexGuard anotherGuard( maMutex );
486 update( sal_True );
488 anotherGuard.clear();
489 ::vos::OGuard aSecondSolarGuard( Application::GetSolarMutex() );
491 delete pWin;
493 else if ( needsUpdate() )
494 // the UI should be shown only on the first update
495 update( sal_True );
497 else
499 DBG_ERRORFILE( "init_Impl(): Could not create root" );
502 mbIsInitialized = bIsInitialized;
505 //-----------------------------------------------------------------------------
506 void SfxDocTplService_Impl::getDefaultLocale()
508 if ( !mbLocaleSet )
510 ::osl::MutexGuard aGuard( maMutex );
511 if ( !mbLocaleSet )
513 rtl::OUString aLocale;
514 utl::ConfigManager::GetDirectConfigProperty( utl::ConfigManager::LOCALE )
515 >>= aLocale;
517 if ( aLocale.getLength() > 0 )
519 sal_Int32 nPos = aLocale.indexOf( sal_Unicode( '-' ) );
520 if ( nPos != -1 )
522 maLocale.Language = aLocale.copy( 0, nPos );
523 nPos = aLocale.indexOf( sal_Unicode( '_' ), nPos + 1 );
524 if ( nPos != -1 )
526 maLocale.Country
527 = aLocale.copy( maLocale.Language.getLength() + 1,
528 nPos - maLocale.Language.getLength() - 1 );
529 maLocale.Variant
530 = aLocale.copy( nPos + 1 );
532 else
534 maLocale.Country
535 = aLocale.copy( maLocale.Language.getLength() + 1 );
541 mbLocaleSet = sal_True;
546 // -----------------------------------------------------------------------
547 void SfxDocTplService_Impl::readFolderList()
549 ::vos::OGuard aGuard( Application::GetSolarMutex() );
551 ResStringArray aShortNames( SfxResId( TEMPLATE_SHORT_NAMES_ARY ) );
552 ResStringArray aLongNames( SfxResId( TEMPLATE_LONG_NAMES_ARY ) );
554 NamePair_Impl* pPair;
556 USHORT nCount = (USHORT)( Min( aShortNames.Count(), aLongNames.Count() ) );
558 for ( USHORT i=0; i<nCount; i++ )
560 pPair = new NamePair_Impl;
561 pPair->maShortName = aShortNames.GetString( i );
562 pPair->maLongName = aLongNames.GetString( i );
564 maNames.Insert( pPair, LIST_APPEND );
568 // -----------------------------------------------------------------------
569 OUString SfxDocTplService_Impl::getLongName( const OUString& rShortName )
571 OUString aRet;
572 NamePair_Impl *pPair = maNames.First();
574 while ( pPair )
576 if ( pPair->maShortName == rShortName )
578 aRet = pPair->maLongName;
579 break;
581 else
582 pPair = maNames.Next();
585 if ( !aRet.getLength() )
586 aRet = rShortName;
588 return aRet;
591 //-----------------------------------------------------------------------------
592 void SfxDocTplService_Impl::getDirList()
594 OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( PROPERTY_DIRLIST ) );
595 Any aValue;
597 // Get the template dir list
598 // TODO/LATER: let use service, register listener
599 INetURLObject aURL;
600 String aDirs = SvtPathOptions().GetTemplatePath();
601 USHORT nCount = aDirs.GetTokenCount( C_DELIM );
603 maTemplateDirs = Sequence< OUString >( nCount );
605 uno::Reference< XComponentContext > xCtx;
606 uno::Reference< util::XMacroExpander > xExpander;
607 uno::Reference< XPropertySet > xPropSet( mxFactory, UNO_QUERY );
608 const rtl::OUString aPrefix(
609 RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.expand:" ) );
611 if ( xPropSet.is() )
613 xPropSet->getPropertyValue(
614 rtl::OUString(
615 RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ) ) )
616 >>= xCtx;
619 if ( xCtx.is() )
621 xCtx->getValueByName(
622 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
623 "/singletons/com.sun.star.util.theMacroExpander" ) ) )
624 >>= xExpander;
626 OSL_ENSURE( xExpander.is(),
627 "Unable to obtain macro expander singleton!" );
630 for ( USHORT i=0; i<nCount; i++ )
632 aURL.SetSmartProtocol( INET_PROT_FILE );
633 aURL.SetURL( aDirs.GetToken( i, C_DELIM ) );
634 maTemplateDirs[i] = aURL.GetMainURL( INetURLObject::NO_DECODE );
636 sal_Int32 nIndex = maTemplateDirs[i].indexOf( aPrefix );
637 if ( nIndex != -1 && xExpander.is() )
639 maTemplateDirs[i] = maTemplateDirs[i].replaceAt(nIndex,
640 aPrefix.getLength(),
641 rtl::OUString());
642 maTemplateDirs[i] = xExpander->expandMacros( maTemplateDirs[i] );
646 aValue <<= maTemplateDirs;
648 // Store the template dir list
649 setProperty( maRootContent, aPropName, aValue );
652 //-----------------------------------------------------------------------------
653 sal_Bool SfxDocTplService_Impl::needsUpdate()
655 OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( PROPERTY_NEEDSUPDATE ) );
656 sal_Bool bHasProperty = sal_False;
657 sal_Bool bNeedsUpdate = sal_True;
658 Any aValue;
660 // Get the template dir list
661 bHasProperty = getProperty( maRootContent, aPropName, aValue );
663 if ( bHasProperty )
664 aValue >>= bNeedsUpdate;
666 // the old template component also checks this state, but it is initialized from this component
667 // so if this componend was already updated the old component does not need such an update
668 ::svt::TemplateFolderCache aTempCache;
669 if ( !bNeedsUpdate )
670 bNeedsUpdate = aTempCache.needsUpdate();
672 if ( bNeedsUpdate )
673 aTempCache.storeState();
675 return bNeedsUpdate;
678 // -----------------------------------------------------------------------
679 sal_Bool SfxDocTplService_Impl::setTitleForURL( const OUString& rURL, const OUString& aTitle )
681 sal_Bool bResult = sal_False;
682 if ( mxInfo.is() )
686 mxInfo->loadFromURL( rURL );
687 uno::Reference< XPropertySet > xPropSet( mxInfo, UNO_QUERY_THROW );
688 OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( TITLE ) );
689 xPropSet->setPropertyValue( aPropName, uno::makeAny( aTitle ) );
690 mxInfo->storeIntoURL( rURL );
691 bResult = sal_True;
693 catch ( Exception& )
698 return bResult;
701 // -----------------------------------------------------------------------
702 sal_Bool SfxDocTplService_Impl::getTitleFromURL( const OUString& rURL, OUString& aTitle, OUString& aType, sal_Bool& bDocHasTitle )
704 bDocHasTitle = sal_False;
706 if ( mxInfo.is() )
710 mxInfo->loadFromURL( rURL );
712 catch ( Exception& )
714 // the document is not a StarOffice document
715 return sal_False;
720 uno::Reference< XPropertySet > aPropSet( mxInfo, UNO_QUERY );
721 if ( aPropSet.is() )
723 OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( TITLE ) );
724 Any aValue = aPropSet->getPropertyValue( aPropName );
725 aValue >>= aTitle;
727 aPropName = OUString( RTL_CONSTASCII_USTRINGPARAM( "MIMEType" ) );
728 aValue = aPropSet->getPropertyValue( aPropName );
729 aValue >>= aType;
732 catch ( UnknownPropertyException& ) {}
733 catch ( Exception& ) {}
736 if ( ! aType.getLength() && mxType.is() )
738 ::rtl::OUString aDocType = mxType->queryTypeByURL( rURL );
739 if ( aDocType.getLength() )
742 uno::Reference< container::XNameAccess > xTypeDetection( mxType, uno::UNO_QUERY_THROW );
743 SequenceAsHashMap aTypeProps( xTypeDetection->getByName( aDocType ) );
744 aType = aTypeProps.getUnpackedValueOrDefault(
745 ::rtl::OUString::createFromAscii( "MediaType" ),
746 ::rtl::OUString() );
748 catch( uno::Exception& )
752 if ( ! aTitle.getLength() )
754 INetURLObject aURL( rURL );
755 aURL.CutExtension();
756 aTitle = aURL.getName( INetURLObject::LAST_SEGMENT, true,
757 INetURLObject::DECODE_WITH_CHARSET );
759 else
760 bDocHasTitle = sal_True;
762 return sal_True;
765 // -----------------------------------------------------------------------
766 sal_Bool SfxDocTplService_Impl::addEntry( Content& rParentFolder,
767 const OUString& rTitle,
768 const OUString& rTargetURL,
769 const OUString& rType )
771 sal_Bool bAddedEntry = sal_False;
773 INetURLObject aLinkObj( rParentFolder.getURL() );
774 aLinkObj.insertName( rTitle, false,
775 INetURLObject::LAST_SEGMENT, true,
776 INetURLObject::ENCODE_ALL );
777 OUString aLinkURL = aLinkObj.GetMainURL( INetURLObject::NO_DECODE );
779 Content aLink;
781 if ( ! Content::create( aLinkURL, maCmdEnv, aLink ) )
783 Sequence< OUString > aNames(3);
784 aNames[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( TITLE ) );
785 aNames[1] = OUString( RTL_CONSTASCII_USTRINGPARAM( IS_FOLDER ) );
786 aNames[2] = OUString( RTL_CONSTASCII_USTRINGPARAM( TARGET_URL ) );
788 Sequence< Any > aValues(3);
789 aValues[0] = makeAny( rTitle );
790 aValues[1] = makeAny( sal_Bool( sal_False ) );
791 aValues[2] = makeAny( rTargetURL );
793 OUString aType( RTL_CONSTASCII_USTRINGPARAM( TYPE_LINK ) );
794 OUString aAdditionalProp( RTL_CONSTASCII_USTRINGPARAM( PROPERTY_TYPE ) );
798 rParentFolder.insertNewContent( aType, aNames, aValues, aLink );
799 setProperty( aLink, aAdditionalProp, makeAny( rType ) );
800 bAddedEntry = sal_True;
802 catch( Exception& )
805 return bAddedEntry;
808 // -----------------------------------------------------------------------
809 sal_Bool SfxDocTplService_Impl::createFolder( const OUString& rNewFolderURL,
810 sal_Bool bCreateParent,
811 sal_Bool bFsysFolder,
812 Content &rNewFolder )
814 Content aParent;
815 sal_Bool bCreatedFolder = sal_False;
816 INetURLObject aParentURL( rNewFolderURL );
817 OUString aFolderName = aParentURL.getName( INetURLObject::LAST_SEGMENT, true,
818 INetURLObject::DECODE_WITH_CHARSET );
820 // compute the parent folder url from the new folder url
821 // and remove the final slash, because Content::create doesn't
822 // like it
823 aParentURL.removeSegment();
824 if ( aParentURL.getSegmentCount() >= 1 )
825 aParentURL.removeFinalSlash();
827 // if the parent exists, we can continue with the creation of the
828 // new folder, we have to create the parent otherwise ( as long as
829 // bCreateParent is set to true )
830 if ( Content::create( aParentURL.GetMainURL( INetURLObject::NO_DECODE ), maCmdEnv, aParent ) )
834 Sequence< OUString > aNames(2);
835 aNames[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( TITLE ) );
836 aNames[1] = OUString( RTL_CONSTASCII_USTRINGPARAM( IS_FOLDER ) );
838 Sequence< Any > aValues(2);
839 aValues[0] = makeAny( aFolderName );
840 aValues[1] = makeAny( sal_Bool( sal_True ) );
842 OUString aType;
844 if ( bFsysFolder )
845 aType = OUString( RTL_CONSTASCII_USTRINGPARAM( TYPE_FSYS_FOLDER ) );
846 else
847 aType = OUString( RTL_CONSTASCII_USTRINGPARAM( TYPE_FOLDER ) );
849 aParent.insertNewContent( aType, aNames, aValues, rNewFolder );
850 bCreatedFolder = sal_True;
852 catch( RuntimeException& )
854 DBG_ERRORFILE( "createFolder(): got runtime exception" );
856 catch( Exception& )
858 DBG_ERRORFILE( "createFolder(): Could not create new folder" );
861 else if ( bCreateParent )
863 // if the parent doesn't exists and bCreateParent is set to true,
864 // we try to create the parent and if this was successful, we
865 // try to create the new folder again ( but this time, we set
866 // bCreateParent to false to avoid endless recusions )
867 if ( ( aParentURL.getSegmentCount() >= 1 ) &&
868 createFolder( aParentURL.GetMainURL( INetURLObject::NO_DECODE ), bCreateParent, bFsysFolder, aParent ) )
870 bCreatedFolder = createFolder( rNewFolderURL, sal_False, bFsysFolder, rNewFolder );
874 return bCreatedFolder;
877 // -----------------------------------------------------------------------
878 sal_Bool SfxDocTplService_Impl::CreateNewUniqueFolderWithPrefix( const ::rtl::OUString& aPath,
879 const ::rtl::OUString& aPrefix,
880 ::rtl::OUString& aNewFolderName,
881 ::rtl::OUString& aNewFolderURL,
882 Content& aNewFolder )
884 sal_Bool bCreated = sal_False;
885 INetURLObject aDirPath( aPath );
887 Content aParent;
888 if ( Content::create( aDirPath.GetMainURL( INetURLObject::NO_DECODE ), maCmdEnv, aParent ) )
890 for ( sal_Int32 nInd = 0; nInd < 32000; nInd++ )
892 ::rtl::OUString aTryName = aPrefix;
893 if ( nInd )
894 aTryName += ::rtl::OUString::valueOf( nInd );
898 Sequence< OUString > aNames(2);
899 aNames[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( TITLE ) );
900 aNames[1] = OUString( RTL_CONSTASCII_USTRINGPARAM( IS_FOLDER ) );
902 Sequence< Any > aValues(2);
903 aValues[0] = makeAny( aTryName );
904 aValues[1] = makeAny( sal_Bool( sal_True ) );
906 OUString aType( RTL_CONSTASCII_USTRINGPARAM( TYPE_FSYS_FOLDER ) );
908 bCreated = aParent.insertNewContent( aType, aNames, aValues, aNewFolder );
910 catch( ucb::NameClashException& )
912 // if there is already an element, retry
914 catch( Exception& )
916 INetURLObject aObjPath( aDirPath );
917 aObjPath.insertName( aTryName, false,
918 INetURLObject::LAST_SEGMENT, true,
919 INetURLObject::ENCODE_ALL );
920 // if there is already an element, retry
921 // if there was another error, do not try any more
922 if ( !::utl::UCBContentHelper::Exists( aObjPath.GetMainURL( INetURLObject::NO_DECODE ) ) )
923 break;
926 if ( bCreated )
928 aNewFolderName = aTryName;
929 aNewFolderURL = aNewFolder.get()->getIdentifier()->getContentIdentifier();
930 break;
935 return bCreated;
938 // -----------------------------------------------------------------------
939 ::rtl::OUString SfxDocTplService_Impl::CreateNewUniqueFileWithPrefix( const ::rtl::OUString& aPath,
940 const ::rtl::OUString& aPrefix,
941 const ::rtl::OUString& aExt )
943 ::rtl::OUString aNewFileURL;
944 INetURLObject aDirPath( aPath );
946 Content aParent;
948 if ( Content::create( aDirPath.GetMainURL( INetURLObject::NO_DECODE ), maCmdEnv, aParent ) )
950 for ( sal_Int32 nInd = 0; nInd < 32000; nInd++ )
952 Content aNewFile;
953 sal_Bool bCreated = sal_False;
954 ::rtl::OUString aTryName = aPrefix;
955 if ( nInd )
956 aTryName += ::rtl::OUString::valueOf( nInd );
957 if ( aExt.toChar() != '.' )
958 aTryName += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "." ) );
959 aTryName += aExt;
963 Sequence< OUString > aNames(2);
964 aNames[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( TITLE ) );
965 aNames[1] = OUString( RTL_CONSTASCII_USTRINGPARAM( IS_DOCUMENT ) );
967 Sequence< Any > aValues(2);
968 aValues[0] = makeAny( aTryName );
969 aValues[1] = makeAny( sal_Bool( sal_True ) );
971 OUString aType( RTL_CONSTASCII_USTRINGPARAM( TYPE_FSYS_FILE ) );
973 bCreated = aParent.insertNewContent( aType, aNames, aValues, aNewFile );
975 catch( ucb::NameClashException& )
977 // if there is already an element, retry
979 catch( Exception& )
981 INetURLObject aObjPath( aPath );
982 aObjPath.insertName( aTryName, false,
983 INetURLObject::LAST_SEGMENT, true,
984 INetURLObject::ENCODE_ALL );
985 // if there is already an element, retry
986 // if there was another error, do not try any more
987 if ( !::utl::UCBContentHelper::Exists( aObjPath.GetMainURL( INetURLObject::NO_DECODE ) ) )
988 break;
991 if ( bCreated )
993 aNewFileURL = aNewFile.get()->getIdentifier()->getContentIdentifier();
994 break;
999 return aNewFileURL;
1002 // -----------------------------------------------------------------------
1003 sal_Bool SfxDocTplService_Impl::removeContent( Content& rContent )
1005 sal_Bool bRemoved = sal_False;
1008 OUString aCmd( RTL_CONSTASCII_USTRINGPARAM( COMMAND_DELETE ) );
1009 Any aArg = makeAny( sal_Bool( sal_True ) );
1011 rContent.executeCommand( aCmd, aArg );
1012 bRemoved = sal_True;
1014 catch ( RuntimeException& ) {}
1015 catch ( Exception& ) {}
1017 return bRemoved;
1020 // -----------------------------------------------------------------------
1021 sal_Bool SfxDocTplService_Impl::removeContent( const OUString& rContentURL )
1023 Content aContent;
1025 if ( Content::create( rContentURL, maCmdEnv, aContent ) )
1026 return removeContent( aContent );
1027 else
1028 return sal_False;
1031 // -----------------------------------------------------------------------
1032 sal_Bool SfxDocTplService_Impl::setProperty( Content& rContent,
1033 const OUString& rPropName,
1034 const Any& rPropValue )
1036 sal_Bool bPropertySet = sal_False;
1038 // Store the property
1041 Any aPropValue( rPropValue );
1042 uno::Reference< XPropertySetInfo > aPropInfo = rContent.getProperties();
1044 // check, wether or not the property exists, create it, when not
1045 if ( !aPropInfo.is() || !aPropInfo->hasPropertyByName( rPropName ) )
1047 uno::Reference< XPropertyContainer > xProperties( rContent.get(), UNO_QUERY );
1048 if ( xProperties.is() )
1052 xProperties->addProperty( rPropName, PropertyAttribute::MAYBEVOID, rPropValue );
1054 catch( PropertyExistException& ) {}
1055 catch( IllegalTypeException& ) { DBG_ERRORFILE( "IllegalTypeException" ); }
1056 catch( IllegalArgumentException& ) { DBG_ERRORFILE( "IllegalArgumentException" ); }
1060 // To ensure a reloctable office installation, the path to the
1061 // office installtion directory must never be stored directly.
1062 if ( SfxURLRelocator_Impl::propertyCanContainOfficeDir( rPropName ) )
1064 OUString aValue;
1065 if ( rPropValue >>= aValue )
1067 maRelocator.makeRelocatableURL( aValue );
1068 aPropValue = makeAny( aValue );
1070 else
1072 Sequence< OUString > aValues;
1073 if ( rPropValue >>= aValues )
1075 for ( sal_Int32 n = 0; n < aValues.getLength(); n++ )
1077 maRelocator.makeRelocatableURL( aValues[ n ] );
1079 aPropValue = makeAny( aValues );
1081 else
1083 OSL_ENSURE( false, "Unsupported property value type" );
1088 // now set the property
1090 rContent.setPropertyValue( rPropName, aPropValue );
1091 bPropertySet = sal_True;
1093 catch ( RuntimeException& ) {}
1094 catch ( Exception& ) {}
1096 return bPropertySet;
1099 // -----------------------------------------------------------------------
1100 sal_Bool SfxDocTplService_Impl::getProperty( Content& rContent,
1101 const OUString& rPropName,
1102 Any& rPropValue )
1104 sal_Bool bGotProperty = sal_False;
1106 // Get the property
1109 uno::Reference< XPropertySetInfo > aPropInfo = rContent.getProperties();
1111 // check, wether or not the property exists
1112 if ( !aPropInfo.is() || !aPropInfo->hasPropertyByName( rPropName ) )
1114 return sal_False;
1117 // now get the property
1119 rPropValue = rContent.getPropertyValue( rPropName );
1121 // To ensure a reloctable office installation, the path to the
1122 // office installtion directory must never be stored directly.
1123 if ( SfxURLRelocator_Impl::propertyCanContainOfficeDir( rPropName ) )
1125 OUString aValue;
1126 if ( rPropValue >>= aValue )
1128 maRelocator.makeAbsoluteURL( aValue );
1129 rPropValue = makeAny( aValue );
1131 else
1133 Sequence< OUString > aValues;
1134 if ( rPropValue >>= aValues )
1136 for ( sal_Int32 n = 0; n < aValues.getLength(); n++ )
1138 maRelocator.makeAbsoluteURL( aValues[ n ] );
1140 rPropValue = makeAny( aValues );
1142 else
1144 OSL_ENSURE( false, "Unsupported property value type" );
1149 bGotProperty = sal_True;
1151 catch ( RuntimeException& ) {}
1152 catch ( Exception& ) {}
1154 return bGotProperty;
1157 // -----------------------------------------------------------------------
1158 // static
1159 bool SfxURLRelocator_Impl::propertyCanContainOfficeDir(
1160 const rtl::OUString & rPropName )
1162 // Note: TargetURL is handled by UCB itself (because it is a property
1163 // with a predefined semantic). Additional Core properties introduced
1164 // be a client app must be handled by the client app itself, because
1165 // the UCB does not know the semantics of those properties.
1166 return ( rPropName.equalsAsciiL(
1167 RTL_CONSTASCII_STRINGPARAM( TARGET_DIR_URL ) ) ||
1168 rPropName.equalsAsciiL(
1169 RTL_CONSTASCII_STRINGPARAM( PROPERTY_DIRLIST ) ) );
1172 //-----------------------------------------------------------------------------
1173 // public SfxDocTplService_Impl
1174 //-----------------------------------------------------------------------------
1176 SfxDocTplService_Impl::SfxDocTplService_Impl( uno::Reference< XMultiServiceFactory > xFactory )
1177 : maRelocator( xFactory )
1179 mxFactory = xFactory;
1180 mpUpdater = NULL;
1181 mbIsInitialized = sal_False;
1182 mbLocaleSet = sal_False;
1185 //-----------------------------------------------------------------------------
1186 SfxDocTplService_Impl::~SfxDocTplService_Impl()
1188 ::osl::MutexGuard aGuard( maMutex );
1190 if ( mpUpdater )
1192 mpUpdater->kill();
1193 delete mpUpdater;
1197 //-----------------------------------------------------------------------------
1198 Locale SfxDocTplService_Impl::getLocale()
1200 ::osl::MutexGuard aGuard( maMutex );
1202 if ( !mbLocaleSet )
1203 getDefaultLocale();
1205 return maLocale;
1208 //-----------------------------------------------------------------------------
1209 void SfxDocTplService_Impl::setLocale( const Locale &rLocale )
1211 ::osl::MutexGuard aGuard( maMutex );
1213 if ( mbLocaleSet &&
1214 ( maLocale.Language != rLocale.Language ) &&
1215 ( maLocale.Country != rLocale.Country ) )
1216 mbIsInitialized = sal_False;
1218 maLocale = rLocale;
1219 mbLocaleSet = sal_True;
1222 //-----------------------------------------------------------------------------
1223 void SfxDocTplService_Impl::update( sal_Bool bUpdateNow )
1225 ::osl::MutexGuard aGuard( maMutex );
1227 if ( bUpdateNow )
1228 doUpdate();
1229 else
1231 mpUpdater = new Updater_Impl( this );
1232 mpUpdater->create();
1236 //-----------------------------------------------------------------------------
1237 void SfxDocTplService_Impl::doUpdate()
1239 ::osl::MutexGuard aGuard( maMutex );
1241 OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( PROPERTY_NEEDSUPDATE ) );
1242 Any aValue;
1244 aValue <<= sal_True;
1245 setProperty( maRootContent, aPropName, aValue );
1247 GroupList_Impl aGroupList;
1249 // get the entries from the hierarchy
1250 createFromContent( aGroupList, maRootContent, sal_True );
1252 // get the entries from the template directories
1253 sal_Int32 nCountDir = maTemplateDirs.getLength();
1254 OUString* pDirs = maTemplateDirs.getArray();
1255 Content aDirContent;
1257 // the last directory in the list must be writable
1258 sal_Bool bWriteableDirectory = sal_True;
1260 // the target folder might not exist, for this reason no interaction handler should be used
1261 uno::Reference< XCommandEnvironment > aQuietEnv;
1263 while ( nCountDir )
1265 nCountDir--;
1266 osl::Directory aDirectory (pDirs[ nCountDir ]);
1267 osl::FileBase::RC nError = aDirectory.open();
1268 if (nError == osl::FileBase::E_None || bWriteableDirectory)
1270 if ( Content::create( pDirs[ nCountDir ], aQuietEnv, aDirContent ) )
1272 createFromContent( aGroupList, aDirContent, sal_False, bWriteableDirectory );
1274 aDirectory.close();
1276 bWriteableDirectory = sal_False;
1279 // now check the list
1280 GroupData_Impl *pGroup = aGroupList.First();
1281 while ( pGroup )
1283 if ( pGroup->getInUse() )
1285 if ( pGroup->getInHierarchy() )
1287 Content aGroup;
1288 if ( Content::create( pGroup->getHierarchyURL(), maCmdEnv, aGroup ) )
1289 setProperty( aGroup,
1290 OUString( RTL_CONSTASCII_USTRINGPARAM( TARGET_DIR_URL ) ),
1291 makeAny( pGroup->getTargetURL() ) );
1293 ULONG nCount = pGroup->count();
1294 for ( ULONG i=0; i<nCount; i++ )
1296 DocTemplates_EntryData_Impl *pData = pGroup->getEntry( i );
1297 if ( ! pData->getInUse() )
1299 if ( pData->getInHierarchy() )
1300 removeFromHierarchy( pData ); // delete entry in hierarchy
1301 else
1302 addToHierarchy( pGroup, pData ); // add entry to hierarchy
1304 else if ( pData->getUpdateType() ||
1305 pData->getUpdateLink() )
1307 updateData( pData );
1311 else
1313 addGroupToHierarchy( pGroup ); // add group to hierarchy
1316 else
1317 removeFromHierarchy( pGroup ); // delete group from hierarchy
1319 delete pGroup;
1320 pGroup = aGroupList.Next();
1323 aValue <<= sal_False;
1324 setProperty( maRootContent, aPropName, aValue );
1327 //-----------------------------------------------------------------------------
1328 uno::Sequence< beans::StringPair > SfxDocTplService_Impl::ReadUINamesForTemplateDir_Impl( const ::rtl::OUString& aUserPath )
1330 INetURLObject aLocObj( aUserPath );
1331 aLocObj.insertName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "groupuinames.xml" ) ), false,
1332 INetURLObject::LAST_SEGMENT, true,
1333 INetURLObject::ENCODE_ALL );
1334 Content aLocContent;
1336 // TODO/LATER: Use hashmap in future
1337 uno::Sequence< beans::StringPair > aUINames;
1338 if ( Content::create( aLocObj.GetMainURL( INetURLObject::NO_DECODE ), uno::Reference < ucb::XCommandEnvironment >(), aLocContent ) )
1342 uno::Reference< io::XInputStream > xLocStream = aLocContent.openStream();
1343 if ( xLocStream.is() )
1344 aUINames = DocTemplLocaleHelper::ReadGroupLocalizationSequence( xLocStream, mxFactory );
1346 catch( uno::Exception& )
1350 return aUINames;
1353 //-----------------------------------------------------------------------------
1354 sal_Bool SfxDocTplService_Impl::UpdateUINamesForTemplateDir_Impl( const ::rtl::OUString& aUserPath,
1355 const ::rtl::OUString& aGroupName,
1356 const ::rtl::OUString& aNewFolderName )
1358 uno::Sequence< beans::StringPair > aUINames = ReadUINamesForTemplateDir_Impl( aUserPath );
1359 sal_Int32 nLen = aUINames.getLength();
1361 // it is possible that the name is used already, but it should be checked before
1362 for ( sal_Int32 nInd = 0; nInd < nLen; nInd++ )
1363 if ( aUINames[nInd].First.equals( aNewFolderName ) )
1364 return sal_False;
1366 aUINames.realloc( ++nLen );
1367 aUINames[nLen-1].First = aNewFolderName;
1368 aUINames[nLen-1].Second = aGroupName;
1370 return WriteUINamesForTemplateDir_Impl( aUserPath, aUINames );
1373 //-----------------------------------------------------------------------------
1374 sal_Bool SfxDocTplService_Impl::ReplaceUINamesForTemplateDir_Impl( const ::rtl::OUString& aUserPath,
1375 const ::rtl::OUString& aDefaultFsysGroupName,
1376 const ::rtl::OUString& aOldGroupName,
1377 const ::rtl::OUString& aNewGroupName )
1379 uno::Sequence< beans::StringPair > aUINames = ReadUINamesForTemplateDir_Impl( aUserPath );
1380 sal_Int32 nLen = aUINames.getLength();
1382 sal_Bool bChanged = sal_False;
1383 for ( sal_Int32 nInd = 0; nInd < nLen; nInd++ )
1384 if ( aUINames[nInd].Second.equals( aOldGroupName ) )
1386 aUINames[nInd].Second = aNewGroupName;
1387 bChanged = sal_True;
1390 if ( !bChanged )
1392 aUINames.realloc( ++nLen );
1393 aUINames[nLen-1].First = aDefaultFsysGroupName;
1394 aUINames[nLen-1].Second = aNewGroupName;
1396 return WriteUINamesForTemplateDir_Impl( aUserPath, aUINames );
1399 //-----------------------------------------------------------------------------
1400 sal_Bool SfxDocTplService_Impl::RemoveUINamesForTemplateDir_Impl( const ::rtl::OUString& aUserPath,
1401 const ::rtl::OUString& aGroupName )
1403 uno::Sequence< beans::StringPair > aUINames = ReadUINamesForTemplateDir_Impl( aUserPath );
1404 sal_Int32 nLen = aUINames.getLength();
1405 uno::Sequence< beans::StringPair > aNewUINames( nLen );
1406 sal_Int32 nNewLen = 0;
1408 sal_Bool bChanged = sal_False;
1409 for ( sal_Int32 nInd = 0; nInd < nLen; nInd++ )
1410 if ( aUINames[nInd].Second.equals( aGroupName ) )
1411 bChanged = sal_True;
1412 else
1414 nNewLen++;
1415 aNewUINames[nNewLen-1].First = aUINames[nInd].First;
1416 aNewUINames[nNewLen-1].Second = aUINames[nInd].Second;
1419 aNewUINames.realloc( nNewLen );
1421 return bChanged ? WriteUINamesForTemplateDir_Impl( aUserPath, aNewUINames ) : sal_True;
1425 //-----------------------------------------------------------------------------
1426 sal_Bool SfxDocTplService_Impl::WriteUINamesForTemplateDir_Impl( const ::rtl::OUString& aUserPath,
1427 const uno::Sequence< beans::StringPair >& aUINames )
1429 sal_Bool bResult = sal_False;
1430 try {
1431 uno::Reference< beans::XPropertySet > xTempFile(
1432 mxFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ),
1433 uno::UNO_QUERY_THROW );
1435 ::rtl::OUString aTempURL;
1436 uno::Any aUrl = xTempFile->getPropertyValue( ::rtl::OUString::createFromAscii( "Uri" ) );
1437 aUrl >>= aTempURL;
1439 uno::Reference< io::XStream > xStream( xTempFile, uno::UNO_QUERY_THROW );
1440 uno::Reference< io::XOutputStream > xOutStream = xStream->getOutputStream();
1441 if ( !xOutStream.is() )
1442 throw uno::RuntimeException();
1444 DocTemplLocaleHelper::WriteGroupLocalizationSequence( xOutStream, aUINames, mxFactory );
1445 try {
1446 // the SAX writer might close the stream
1447 xOutStream->closeOutput();
1448 } catch( uno::Exception& )
1451 Content aTargetContent( aUserPath, maCmdEnv );
1452 Content aSourceContent( aTempURL, maCmdEnv );
1453 aTargetContent.transferContent( aSourceContent,
1454 InsertOperation_COPY,
1455 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "groupuinames.xml" ) ),
1456 ucb::NameClash::OVERWRITE );
1457 bResult = sal_True;
1459 catch ( uno::Exception& )
1463 return bResult;
1466 //-----------------------------------------------------------------------------
1467 ::rtl::OUString SfxDocTplService_Impl::CreateNewGroupFsys( const ::rtl::OUString& rGroupName, Content& aGroup )
1469 ::rtl::OUString aResultURL;
1471 if ( maTemplateDirs.getLength() )
1473 ::rtl::OUString aTargetPath = maTemplateDirs[ maTemplateDirs.getLength() - 1 ];
1475 // create a new folder with the given name
1476 Content aNewFolder;
1477 ::rtl::OUString aNewFolderName;
1479 // the Fsys name instead of GroupName should be used, the groupuinames must be added also
1480 if ( !CreateNewUniqueFolderWithPrefix( aTargetPath,
1481 rGroupName,
1482 aNewFolderName,
1483 aResultURL,
1484 aNewFolder )
1485 && !CreateNewUniqueFolderWithPrefix( aTargetPath,
1486 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UserGroup" ) ),
1487 aNewFolderName,
1488 aResultURL,
1489 aNewFolder ) )
1491 return ::rtl::OUString();
1493 if ( !UpdateUINamesForTemplateDir_Impl( aTargetPath, rGroupName, aNewFolderName ) )
1495 // we could not create the groupuinames for the folder, so we delete the group in the
1496 // the folder and return
1497 removeContent( aNewFolder );
1498 return ::rtl::OUString();
1501 // Now set the target url for this group and we are done
1502 OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( TARGET_DIR_URL ) );
1503 Any aValue = makeAny( aResultURL );
1505 if ( ! setProperty( aGroup, aPropName, aValue ) )
1507 removeContent( aNewFolder );
1508 return ::rtl::OUString();
1512 return aResultURL;
1515 //-----------------------------------------------------------------------------
1516 sal_Bool SfxDocTplService_Impl::addGroup( const OUString& rGroupName )
1518 ::osl::MutexGuard aGuard( maMutex );
1520 // Check, wether or not there is a group with this name
1521 Content aNewGroup;
1522 OUString aNewGroupURL;
1523 INetURLObject aNewGroupObj( maRootURL );
1525 aNewGroupObj.insertName( rGroupName, false,
1526 INetURLObject::LAST_SEGMENT, true,
1527 INetURLObject::ENCODE_ALL );
1529 aNewGroupURL = aNewGroupObj.GetMainURL( INetURLObject::NO_DECODE );
1531 if ( Content::create( aNewGroupURL, maCmdEnv, aNewGroup ) ||
1532 ! createFolder( aNewGroupURL, sal_False, sal_False, aNewGroup ) )
1534 // if there already was a group with this name or the new group
1535 // could not be created, we return here
1536 return sal_False;
1539 // Get the user template path entry ( new group will always
1540 // be added in the user template path )
1541 sal_Int32 nIndex;
1542 OUString aUserPath;
1544 nIndex = maTemplateDirs.getLength();
1545 if ( nIndex )
1546 nIndex--;
1547 else
1548 return sal_False; // We don't know where to add the group
1550 aUserPath = maTemplateDirs[ nIndex ];
1552 // create a new folder with the given name
1553 Content aNewFolder;
1554 OUString aNewFolderName;
1555 OUString aNewFolderURL;
1557 // the Fsys name instead of GroupName should be used, the groupuinames must be added also
1558 if ( !CreateNewUniqueFolderWithPrefix( aUserPath,
1559 rGroupName,
1560 aNewFolderName,
1561 aNewFolderURL,
1562 aNewFolder )
1563 && !CreateNewUniqueFolderWithPrefix( aUserPath,
1564 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UserGroup" ) ),
1565 aNewFolderName,
1566 aNewFolderURL,
1567 aNewFolder ) )
1569 // we could not create the folder, so we delete the group in the
1570 // hierarchy and return
1571 removeContent( aNewGroup );
1572 return sal_False;
1575 if ( !UpdateUINamesForTemplateDir_Impl( aUserPath, rGroupName, aNewFolderName ) )
1577 // we could not create the groupuinames for the folder, so we delete the group in the
1578 // hierarchy, the folder and return
1579 removeContent( aNewGroup );
1580 removeContent( aNewFolder );
1581 return sal_False;
1584 // Now set the target url for this group and we are done
1585 OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( TARGET_DIR_URL ) );
1586 Any aValue = makeAny( aNewFolderURL );
1588 if ( ! setProperty( aNewGroup, aPropName, aValue ) )
1590 removeContent( aNewGroup );
1591 removeContent( aNewFolder );
1592 return sal_False;
1595 return sal_True;
1598 //-----------------------------------------------------------------------------
1599 sal_Bool SfxDocTplService_Impl::removeGroup( const OUString& rGroupName )
1601 // remove all the elements that have the prefix aTargetURL
1602 // if the group does not have other elements remove it
1604 ::osl::MutexGuard aGuard( maMutex );
1606 sal_Bool bResult = sal_False;
1608 // create the group url
1609 INetURLObject aGroupObj( maRootURL );
1610 aGroupObj.insertName( rGroupName, false,
1611 INetURLObject::LAST_SEGMENT, true,
1612 INetURLObject::ENCODE_ALL );
1614 // Get the target url
1615 Content aGroup;
1616 OUString aGroupURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE );
1618 if ( Content::create( aGroupURL, maCmdEnv, aGroup ) )
1620 OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( TARGET_DIR_URL ) );
1621 Any aValue;
1623 OUString aGroupTargetURL;
1624 if ( getProperty( aGroup, aPropName, aValue ) )
1625 aValue >>= aGroupTargetURL;
1627 if ( !aGroupTargetURL.getLength() )
1628 return sal_False; // nothing is allowed to be removed
1630 if ( !maTemplateDirs.getLength() )
1631 return sal_False;
1632 ::rtl::OUString aGeneralTempPath = maTemplateDirs[ maTemplateDirs.getLength() - 1 ];
1634 // check that the fs location is in writeble folder and this is not a "My templates" folder
1635 INetURLObject aGroupParentFolder( aGroupTargetURL );
1636 if ( !aGroupParentFolder.removeSegment()
1637 || !::utl::UCBContentHelper::IsSubPath( aGeneralTempPath,
1638 aGroupParentFolder.GetMainURL( INetURLObject::NO_DECODE ) ) )
1639 return sal_False;
1641 // now get the content of the Group
1642 uno::Reference< XResultSet > xResultSet;
1643 Sequence< OUString > aProps( 1 );
1645 aProps[0] = OUString::createFromAscii( TARGET_URL );
1649 sal_Bool bHasNonRemovable = sal_False;
1650 sal_Bool bHasShared = sal_False;
1652 ResultSetInclude eInclude = INCLUDE_DOCUMENTS_ONLY;
1653 xResultSet = aGroup.createCursor( aProps, eInclude );
1655 if ( xResultSet.is() )
1657 uno::Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY_THROW );
1658 uno::Reference< XRow > xRow( xResultSet, UNO_QUERY_THROW );
1660 while ( xResultSet->next() )
1662 OUString aTemplTargetURL( xRow->getString( 1 ) );
1663 OUString aHierURL = xContentAccess->queryContentIdentifierString();
1665 if ( ::utl::UCBContentHelper::IsSubPath( aGroupTargetURL, aTemplTargetURL ) )
1667 // this is a user template, and it can be removed
1668 if ( removeContent( aTemplTargetURL ) )
1669 removeContent( aHierURL );
1670 else
1671 bHasNonRemovable = sal_True;
1673 else
1674 bHasShared = sal_True;
1677 if ( !bHasNonRemovable && !bHasShared )
1679 if ( removeContent( aGroupTargetURL )
1680 || !::utl::UCBContentHelper::Exists( aGroupTargetURL ) )
1682 removeContent( aGroupURL );
1683 RemoveUINamesForTemplateDir_Impl( aGeneralTempPath, rGroupName );
1684 bResult = sal_True; // the operation is successful only if the whole group is removed
1687 else if ( !bHasNonRemovable )
1689 if ( removeContent( aGroupTargetURL )
1690 || !::utl::UCBContentHelper::Exists( aGroupTargetURL ) )
1692 RemoveUINamesForTemplateDir_Impl( aGeneralTempPath, rGroupName );
1693 setProperty( aGroup, aPropName, uno::makeAny( ::rtl::OUString() ) );
1698 catch ( Exception& ) {}
1701 return bResult;
1704 //-----------------------------------------------------------------------------
1705 sal_Bool SfxDocTplService_Impl::renameGroup( const OUString& rOldName,
1706 const OUString& rNewName )
1708 ::osl::MutexGuard aGuard( maMutex );
1710 // create the group url
1711 Content aGroup;
1712 INetURLObject aGroupObj( maRootURL );
1713 aGroupObj.insertName( rNewName, false,
1714 INetURLObject::LAST_SEGMENT, true,
1715 INetURLObject::ENCODE_ALL );
1716 OUString aGroupURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE );
1718 // Check, if there is a group with the new name, return false
1719 // if there is one.
1720 if ( Content::create( aGroupURL, maCmdEnv, aGroup ) )
1721 return sal_False;
1723 aGroupObj.removeSegment();
1724 aGroupObj.insertName( rOldName, false,
1725 INetURLObject::LAST_SEGMENT, true,
1726 INetURLObject::ENCODE_ALL );
1727 aGroupURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE );
1729 // When there is no group with the old name, we can't rename it
1730 if ( ! Content::create( aGroupURL, maCmdEnv, aGroup ) )
1731 return sal_False;
1733 OUString aGroupTargetURL;
1734 // there is no need to check whether target dir url is in target path, since if the target path is changed
1735 // the target dir url should be already generated new
1736 OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( TARGET_DIR_URL ) );
1737 Any aValue;
1738 if ( getProperty( aGroup, aPropName, aValue ) )
1739 aValue >>= aGroupTargetURL;
1741 if ( !aGroupTargetURL.getLength() )
1742 return sal_False;
1744 if ( !maTemplateDirs.getLength() )
1745 return sal_False;
1746 ::rtl::OUString aGeneralTempPath = maTemplateDirs[ maTemplateDirs.getLength() - 1 ];
1748 // check that the fs location is in writeble folder and this is not a "My templates" folder
1749 INetURLObject aGroupParentFolder( aGroupTargetURL );
1750 if ( !aGroupParentFolder.removeSegment()
1751 || !::utl::UCBContentHelper::IsSubPath( aGeneralTempPath,
1752 aGroupParentFolder.GetMainURL( INetURLObject::NO_DECODE ) ) )
1753 return sal_False;
1755 // check that the group can be renamed ( all the contents must be in target location )
1756 sal_Bool bCanBeRenamed = sal_False;
1759 uno::Reference< XResultSet > xResultSet;
1760 Sequence< OUString > aProps( 1 );
1762 aProps[0] = OUString::createFromAscii( TARGET_URL );
1763 ResultSetInclude eInclude = INCLUDE_DOCUMENTS_ONLY;
1764 xResultSet = aGroup.createCursor( aProps, eInclude );
1766 if ( xResultSet.is() )
1768 uno::Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY_THROW );
1769 uno::Reference< XRow > xRow( xResultSet, UNO_QUERY_THROW );
1771 while ( xResultSet->next() )
1773 OUString aTemplTargetURL( xRow->getString( 1 ) );
1775 if ( !::utl::UCBContentHelper::IsSubPath( aGroupTargetURL, aTemplTargetURL ) )
1776 throw uno::Exception();
1779 bCanBeRenamed = sal_True;
1782 catch ( Exception& ) {}
1784 if ( bCanBeRenamed )
1786 INetURLObject aGroupTargetObj( aGroupTargetURL );
1787 ::rtl::OUString aFsysName = aGroupTargetObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
1789 if ( aGroupTargetObj.removeSegment()
1790 && ReplaceUINamesForTemplateDir_Impl( aGroupTargetObj.GetMainURL( INetURLObject::NO_DECODE ),
1791 aFsysName,
1792 rOldName,
1793 rNewName ) )
1795 // rename the group in the hierarchy
1796 OUString aTitleProp( RTL_CONSTASCII_USTRINGPARAM( TITLE ) );
1797 Any aTitleValue;
1798 aTitleValue <<= rNewName;
1800 return setProperty( aGroup, aTitleProp, aTitleValue );
1804 return sal_False;
1807 //-----------------------------------------------------------------------------
1808 sal_Bool SfxDocTplService_Impl::storeTemplate( const OUString& rGroupName,
1809 const OUString& rTemplateName,
1810 const uno::Reference< XSTORABLE >& rStorable )
1812 ::osl::MutexGuard aGuard( maMutex );
1814 // Check, wether or not there is a group with this name
1815 // Return false, if there is no group with the given name
1816 Content aGroup, aTemplate, aTargetGroup, aTemplateToRemove;
1817 OUString aGroupURL, aTemplateURL, aTemplateToRemoveTargetURL;
1818 INetURLObject aGroupObj( maRootURL );
1819 sal_Bool bRemoveOldTemplateContent = sal_False;
1820 ::rtl::OUString sDocServiceName;
1822 aGroupObj.insertName( rGroupName, false,
1823 INetURLObject::LAST_SEGMENT, true,
1824 INetURLObject::ENCODE_ALL );
1825 aGroupURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE );
1827 if ( ! Content::create( aGroupURL, maCmdEnv, aGroup ) )
1828 return sal_False;
1830 ::rtl::OUString aGroupTargetURL;
1831 ::rtl::OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( TARGET_DIR_URL ) );
1832 Any aValue;
1833 if ( getProperty( aGroup, aPropName, aValue ) )
1834 aValue >>= aGroupTargetURL;
1837 // Check, if there's a template with the given name in this group
1838 // the target template should be overwritten if it is imported by user
1839 // in case the template is installed by office installation of by an add-in
1840 // it can not be replaced
1841 aGroupObj.insertName( rTemplateName, false,
1842 INetURLObject::LAST_SEGMENT, true,
1843 INetURLObject::ENCODE_ALL );
1844 aTemplateURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE );
1846 if ( Content::create( aTemplateURL, maCmdEnv, aTemplateToRemove ) )
1848 OUString aTargetTemplPropName( RTL_CONSTASCII_USTRINGPARAM( TARGET_URL ) );
1850 bRemoveOldTemplateContent = sal_True;
1851 if ( getProperty( aTemplateToRemove, aTargetTemplPropName, aValue ) )
1852 aValue >>= aTemplateToRemoveTargetURL;
1854 if ( !aGroupTargetURL.getLength() || !maTemplateDirs.getLength()
1855 || (aTemplateToRemoveTargetURL.getLength() && !::utl::UCBContentHelper::IsSubPath( maTemplateDirs[ maTemplateDirs.getLength() - 1 ], aTemplateToRemoveTargetURL )) )
1856 return sal_False; // it is not allowed to remove the template
1861 uno::Reference< lang::XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory();
1862 if ( !xFactory.is() )
1863 throw uno::RuntimeException();
1865 // get document service name
1866 uno::Reference< frame::XModuleManager > xModuleManager(
1867 xFactory->createInstance(
1868 ::rtl::OUString::createFromAscii( "com.sun.star.frame.ModuleManager" ) ),
1869 uno::UNO_QUERY_THROW );
1870 sDocServiceName = xModuleManager->identify( uno::Reference< uno::XInterface >( rStorable, uno::UNO_QUERY ) );
1871 if ( !sDocServiceName.getLength() )
1872 throw uno::RuntimeException();
1874 // get the actual filter name
1875 ::rtl::OUString aFilterName;
1877 uno::Reference< lang::XMultiServiceFactory > xConfigProvider(
1878 xFactory->createInstance(
1879 ::rtl::OUString::createFromAscii( "com.sun.star.configuration.ConfigurationProvider" ) ),
1880 uno::UNO_QUERY_THROW );
1882 uno::Sequence< uno::Any > aArgs( 1 );
1883 beans::PropertyValue aPathProp;
1884 aPathProp.Name = ::rtl::OUString::createFromAscii( "nodepath" );
1885 aPathProp.Value <<= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Setup/Office/Factories/" ) );
1886 aArgs[0] <<= aPathProp;
1888 uno::Reference< container::XNameAccess > xSOFConfig(
1889 xConfigProvider->createInstanceWithArguments(
1890 ::rtl::OUString::createFromAscii( "com.sun.star.configuration.ConfigurationAccess" ),
1891 aArgs ),
1892 uno::UNO_QUERY_THROW );
1894 uno::Reference< container::XNameAccess > xApplConfig;
1895 xSOFConfig->getByName( sDocServiceName ) >>= xApplConfig;
1896 if ( !xApplConfig.is() )
1897 throw uno::RuntimeException();
1899 xApplConfig->getByName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ooSetupFactoryActualTemplateFilter" ) ) ) >>= aFilterName;
1900 if ( !aFilterName.getLength() )
1901 throw uno::RuntimeException();
1903 // find the related type name
1904 ::rtl::OUString aTypeName;
1905 uno::Reference< container::XNameAccess > xFilterFactory(
1906 xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.document.FilterFactory" ) ),
1907 uno::UNO_QUERY_THROW );
1909 uno::Sequence< beans::PropertyValue > aFilterData;
1910 xFilterFactory->getByName( aFilterName ) >>= aFilterData;
1911 for ( sal_Int32 nInd = 0; nInd < aFilterData.getLength(); nInd++ )
1912 if ( aFilterData[nInd].Name.equalsAscii( "Type" ) )
1913 aFilterData[nInd].Value >>= aTypeName;
1915 if ( !aTypeName.getLength() )
1916 throw uno::RuntimeException();
1918 // find the mediatype and extension
1919 uno::Reference< container::XNameAccess > xTypeDetection =
1920 mxType.is() ?
1921 uno::Reference< container::XNameAccess >( mxType, uno::UNO_QUERY_THROW ) :
1922 uno::Reference< container::XNameAccess >(
1923 xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.document.TypeDetection" ) ),
1924 uno::UNO_QUERY_THROW );
1926 SequenceAsHashMap aTypeProps( xTypeDetection->getByName( aTypeName ) );
1927 uno::Sequence< ::rtl::OUString > aAllExt =
1928 aTypeProps.getUnpackedValueOrDefault( ::rtl::OUString::createFromAscii( "Extensions" ), Sequence< ::rtl::OUString >() );
1929 if ( !aAllExt.getLength() )
1930 throw uno::RuntimeException();
1932 ::rtl::OUString aMediaType = aTypeProps.getUnpackedValueOrDefault( ::rtl::OUString::createFromAscii( "MediaType" ), ::rtl::OUString() );
1933 ::rtl::OUString aExt = aAllExt[0];
1935 if ( !aMediaType.getLength() || !aExt.getLength() )
1936 throw uno::RuntimeException();
1938 // construct destination url
1939 if ( !aGroupTargetURL.getLength() )
1941 aGroupTargetURL = CreateNewGroupFsys( rGroupName, aGroup );
1943 if ( !aGroupTargetURL.getLength() )
1944 throw uno::RuntimeException();
1947 ::rtl::OUString aNewTemplateTargetURL = CreateNewUniqueFileWithPrefix( aGroupTargetURL, rTemplateName, aExt );
1948 if ( !aNewTemplateTargetURL.getLength() )
1950 aNewTemplateTargetURL = CreateNewUniqueFileWithPrefix( aGroupTargetURL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UserTemplate" ) ), aExt );
1952 if ( !aNewTemplateTargetURL.getLength() )
1953 throw uno::RuntimeException();
1956 // store template
1957 uno::Sequence< PropertyValue > aStoreArgs( 2 );
1958 aStoreArgs[0].Name = ::rtl::OUString::createFromAscii( "FilterName" );
1959 aStoreArgs[0].Value <<= aFilterName;
1960 aStoreArgs[1].Name = ::rtl::OUString::createFromAscii( "DocumentTitle" );
1961 aStoreArgs[1].Value <<= rTemplateName;
1963 rStorable->storeToURL( aNewTemplateTargetURL, aStoreArgs );
1965 // the storing was successful, now the old template with the same name can be removed if it existed
1966 if ( aTemplateToRemoveTargetURL.getLength() )
1968 removeContent( aTemplateToRemoveTargetURL );
1971 * pb: #i79496#
1972 * if the old template was the standard template
1973 * it is necessary to change the standard template with the new file name
1975 String sStdTmplFile = SfxObjectFactory::GetStandardTemplate( sDocServiceName );
1976 if ( INetURLObject( sStdTmplFile ) == INetURLObject( aTemplateToRemoveTargetURL ) )
1978 SfxObjectFactory::SetStandardTemplate( sDocServiceName, aNewTemplateTargetURL );
1982 if ( bRemoveOldTemplateContent )
1983 removeContent( aTemplateToRemove );
1985 // add the template to hierarchy
1986 return addEntry( aGroup, rTemplateName, aNewTemplateTargetURL, aMediaType );
1988 catch( Exception& )
1990 // the template was not stored
1991 return sal_False;
1995 //-----------------------------------------------------------------------------
1996 sal_Bool SfxDocTplService_Impl::addTemplate( const OUString& rGroupName,
1997 const OUString& rTemplateName,
1998 const OUString& rSourceURL )
2000 ::osl::MutexGuard aGuard( maMutex );
2002 // Check, wether or not there is a group with this name
2003 // Return false, if there is no group with the given name
2004 Content aGroup, aTemplate, aTargetGroup;
2005 OUString aGroupURL, aTemplateURL;
2006 INetURLObject aGroupObj( maRootURL );
2008 aGroupObj.insertName( rGroupName, false,
2009 INetURLObject::LAST_SEGMENT, true,
2010 INetURLObject::ENCODE_ALL );
2011 aGroupURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE );
2013 if ( ! Content::create( aGroupURL, maCmdEnv, aGroup ) )
2014 return sal_False;
2016 // Check, if there's a template with the given name in this group
2017 // Return false, if there already is a template
2018 aGroupObj.insertName( rTemplateName, false,
2019 INetURLObject::LAST_SEGMENT, true,
2020 INetURLObject::ENCODE_ALL );
2021 aTemplateURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE );
2023 if ( Content::create( aTemplateURL, maCmdEnv, aTemplate ) )
2024 return sal_False;
2026 // get the target url of the group
2027 OUString aTargetURL;
2028 OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( TARGET_DIR_URL ) );
2029 Any aValue;
2031 if ( getProperty( aGroup, aPropName, aValue ) )
2032 aValue >>= aTargetURL;
2034 if ( !aTargetURL.getLength() )
2036 aTargetURL = CreateNewGroupFsys( rGroupName, aGroup );
2038 if ( !aTargetURL.getLength() )
2039 return sal_False;
2042 // Get the content type
2043 OUString aTitle, aType, aTargetURL2, aFullName;
2045 // only StarOffice documents are acceptable
2046 sal_Bool bDocHasTitle = sal_False;
2047 if( !getTitleFromURL( rSourceURL, aTitle, aType, bDocHasTitle ) )
2048 return sal_False;
2050 INetURLObject aSourceObj( rSourceURL );
2051 if ( rTemplateName.equals( aTitle ) )
2053 /////////////////////////////////////////////////////
2054 // addTemplate will sometimes be called just to add an entry in the
2055 // hierarchy; the target URL and the source URL will be the same in
2056 // this scenario
2057 // TODO/LATER: get rid of this old hack
2059 INetURLObject aTargetObj( aTargetURL );
2061 aTargetObj.insertName( rTemplateName, false,
2062 INetURLObject::LAST_SEGMENT, true,
2063 INetURLObject::ENCODE_ALL );
2064 aTargetObj.setExtension( aSourceObj.getExtension() );
2066 aTargetURL2 = aTargetObj.GetMainURL( INetURLObject::NO_DECODE );
2068 if ( aTargetURL2 == rSourceURL )
2069 return addEntry( aGroup, rTemplateName, aTargetURL2, aType );
2072 /////////////////////////////////////////////////////
2073 // copy the template into the new group (targeturl)
2075 INetURLObject aTmpURL( aSourceObj );
2076 aTmpURL.CutExtension();
2077 ::rtl::OUString aPattern = aTmpURL.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
2079 ::rtl::OUString aNewTemplateTargetURL = CreateNewUniqueFileWithPrefix( aTargetURL, aPattern, aSourceObj.getExtension() );
2080 INetURLObject aNewTemplateTargetObj( aNewTemplateTargetURL );
2081 ::rtl::OUString aNewTemplateTargetName = aNewTemplateTargetObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
2082 if ( !aNewTemplateTargetURL.getLength() || !aNewTemplateTargetName.getLength() )
2083 return sal_False;
2085 // get access to source file
2086 Content aSourceContent;
2087 uno::Reference < ucb::XCommandEnvironment > xEnv;
2088 INetURLObject aSourceURL( rSourceURL );
2089 if( ! Content::create( aSourceURL.GetMainURL( INetURLObject::NO_DECODE ), xEnv, aSourceContent ) )
2090 return sal_False;
2092 if( ! Content::create( aTargetURL, xEnv, aTargetGroup ) )
2093 return sal_False;
2095 // transfer source file
2098 if( ! aTargetGroup.transferContent( aSourceContent,
2099 InsertOperation_COPY,
2100 aNewTemplateTargetName,
2101 NameClash::OVERWRITE ) )
2102 return sal_False;
2104 // allow to edit the added template
2105 Content aResultContent;
2106 if ( Content::create( aNewTemplateTargetURL, xEnv, aResultContent ) )
2108 ::rtl::OUString aPropertyName( RTL_CONSTASCII_USTRINGPARAM( "IsReadOnly" ) );
2109 uno::Any aProperty;
2110 sal_Bool bReadOnly = sal_False;
2111 if ( getProperty( aResultContent, aPropertyName, aProperty ) && ( aProperty >>= bReadOnly ) && bReadOnly )
2112 setProperty( aResultContent, aPropertyName, uno::makeAny( (sal_Bool)sal_False ) );
2115 catch ( ContentCreationException& )
2116 { return sal_False; }
2117 catch ( Exception& )
2118 { return sal_False; }
2121 // either the document has title and it is the same as requested, or we have to set it
2122 sal_Bool bCorrectTitle = ( bDocHasTitle && aTitle.equals( rTemplateName ) );
2123 if ( !bCorrectTitle )
2125 if ( !bDocHasTitle )
2127 INetURLObject aNewTmpObj( aNewTemplateTargetObj );
2128 aNewTmpObj.CutExtension();
2129 bCorrectTitle = ( aNewTmpObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET ).equals( rTemplateName ) );
2132 if ( !bCorrectTitle )
2133 bCorrectTitle = setTitleForURL( aNewTemplateTargetURL, rTemplateName );
2136 if ( bCorrectTitle )
2138 // create a new entry in the hierarchy
2139 return addEntry( aGroup, rTemplateName, aNewTemplateTargetURL, aType );
2142 // TODO/LATER: The user could be notified here that the renaming has failed
2143 // create a new entry in the hierarchy
2144 addEntry( aGroup, aTitle, aNewTemplateTargetURL, aType );
2145 return sal_False;
2148 //-----------------------------------------------------------------------------
2149 sal_Bool SfxDocTplService_Impl::removeTemplate( const OUString& rGroupName,
2150 const OUString& rTemplateName )
2152 ::osl::MutexGuard aGuard( maMutex );
2154 // Check, wether or not there is a group with this name
2155 // Return false, if there is no group with the given name
2156 Content aGroup, aTemplate;
2157 OUString aGroupURL, aTemplateURL;
2158 INetURLObject aGroupObj( maRootURL );
2160 aGroupObj.insertName( rGroupName, false,
2161 INetURLObject::LAST_SEGMENT, true,
2162 INetURLObject::ENCODE_ALL );
2163 aGroupURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE );
2165 if ( ! Content::create( aGroupURL, maCmdEnv, aGroup ) )
2166 return sal_False;
2168 // Check, if there's a template with the given name in this group
2169 // Return false, if there is no template
2170 aGroupObj.insertName( rTemplateName, false,
2171 INetURLObject::LAST_SEGMENT, true,
2172 INetURLObject::ENCODE_ALL );
2173 aTemplateURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE );
2175 if ( !Content::create( aTemplateURL, maCmdEnv, aTemplate ) )
2176 return sal_False;
2178 // get the target URL from the template
2179 OUString aTargetURL;
2180 OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( TARGET_URL ) );
2181 Any aValue;
2183 if ( getProperty( aTemplate, aPropName, aValue ) )
2184 aValue >>= aTargetURL;
2186 // delete the target template
2187 if ( aTargetURL.getLength() )
2189 if ( !maTemplateDirs.getLength()
2190 || !::utl::UCBContentHelper::IsSubPath( maTemplateDirs[ maTemplateDirs.getLength() - 1 ], aTargetURL ) )
2191 return sal_False;
2193 removeContent( aTargetURL );
2196 // delete the template entry
2197 return removeContent( aTemplate );
2200 //-----------------------------------------------------------------------------
2201 sal_Bool SfxDocTplService_Impl::renameTemplate( const OUString& rGroupName,
2202 const OUString& rOldName,
2203 const OUString& rNewName )
2205 ::osl::MutexGuard aGuard( maMutex );
2207 // Check, wether or not there is a group with this name
2208 // Return false, if there is no group with the given name
2209 Content aGroup, aTemplate;
2210 OUString aGroupURL, aTemplateURL;
2211 INetURLObject aGroupObj( maRootURL );
2213 aGroupObj.insertName( rGroupName, false,
2214 INetURLObject::LAST_SEGMENT, true,
2215 INetURLObject::ENCODE_ALL );
2216 aGroupURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE );
2218 if ( ! Content::create( aGroupURL, maCmdEnv, aGroup ) )
2219 return sal_False;
2221 // Check, if there's a template with the new name in this group
2222 // Return false, if there is one
2223 aGroupObj.insertName( rNewName, false,
2224 INetURLObject::LAST_SEGMENT, true,
2225 INetURLObject::ENCODE_ALL );
2226 aTemplateURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE );
2228 if ( Content::create( aTemplateURL, maCmdEnv, aTemplate ) )
2229 return sal_False;
2231 // Check, if there's a template with the old name in this group
2232 // Return false, if there is no template
2233 aGroupObj.removeSegment();
2234 aGroupObj.insertName( rOldName, false,
2235 INetURLObject::LAST_SEGMENT, true,
2236 INetURLObject::ENCODE_ALL );
2237 aTemplateURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE );
2239 if ( !Content::create( aTemplateURL, maCmdEnv, aTemplate ) )
2240 return sal_False;
2242 OUString aTemplateTargetURL;
2243 OUString aTargetProp( RTL_CONSTASCII_USTRINGPARAM( TARGET_URL ) );
2244 Any aTargetValue;
2246 if ( getProperty( aTemplate, aTargetProp, aTargetValue ) )
2247 aTargetValue >>= aTemplateTargetURL;
2249 if ( !setTitleForURL( aTemplateTargetURL, rNewName ) )
2250 return sal_False;
2252 // rename the template entry in the cache
2253 OUString aTitleProp( RTL_CONSTASCII_USTRINGPARAM( TITLE ) );
2254 Any aTitleValue;
2255 aTitleValue <<= rNewName;
2257 return setProperty( aTemplate, aTitleProp, aTitleValue );
2260 //-----------------------------------------------------------------------------
2261 //-----------------------------------------------------------------------------
2262 //-----------------------------------------------------------------------------
2264 SFX_IMPL_XSERVICEINFO( SfxDocTplService, TEMPLATE_SERVICE_NAME, TEMPLATE_IMPLEMENTATION_NAME )
2265 SFX_IMPL_SINGLEFACTORY( SfxDocTplService )
2267 //-----------------------------------------------------------------------------
2268 SfxDocTplService::SfxDocTplService( const uno::Reference< XMultiServiceFactory >& xFactory )
2270 pImp = new SfxDocTplService_Impl( xFactory );
2273 //-----------------------------------------------------------------------------
2275 SfxDocTplService::~SfxDocTplService()
2277 delete pImp;
2280 //-----------------------------------------------------------------------------
2281 //--- XLocalizable ---
2282 //-----------------------------------------------------------------------------
2284 Locale SAL_CALL SfxDocTplService::getLocale()
2285 throw( RUNTIMEEXCEPTION )
2287 return pImp->getLocale();
2290 //-----------------------------------------------------------------------------
2292 void SAL_CALL SfxDocTplService::setLocale( const Locale & rLocale )
2293 throw( RUNTIMEEXCEPTION )
2295 pImp->setLocale( rLocale );
2298 //-----------------------------------------------------------------------------
2299 //--- XDocumentTemplates ---
2300 //-----------------------------------------------------------------------------
2301 uno::Reference< XCONTENT > SAL_CALL SfxDocTplService::getContent()
2302 throw( RUNTIMEEXCEPTION )
2304 if ( pImp->init() )
2305 return pImp->getContent().get();
2306 else
2307 return NULL;
2310 //-----------------------------------------------------------------------------
2311 sal_Bool SAL_CALL SfxDocTplService::storeTemplate( const OUString& GroupName,
2312 const OUString& TemplateName,
2313 const uno::Reference< XSTORABLE >& Storable )
2314 throw( RUNTIMEEXCEPTION )
2316 if ( pImp->init() )
2317 return pImp->storeTemplate( GroupName, TemplateName, Storable );
2318 else
2319 return sal_False;
2322 //-----------------------------------------------------------------------------
2323 sal_Bool SAL_CALL SfxDocTplService::addTemplate( const OUString& rGroupName,
2324 const OUString& rTemplateName,
2325 const OUString& rSourceURL )
2326 throw( RUNTIMEEXCEPTION )
2328 if ( pImp->init() )
2329 return pImp->addTemplate( rGroupName, rTemplateName, rSourceURL );
2330 else
2331 return sal_False;
2334 //-----------------------------------------------------------------------------
2335 sal_Bool SAL_CALL SfxDocTplService::removeTemplate( const OUString& rGroupName,
2336 const OUString& rTemplateName )
2337 throw( RUNTIMEEXCEPTION )
2339 if ( pImp->init() )
2340 return pImp->removeTemplate( rGroupName, rTemplateName );
2341 else
2342 return sal_False;
2345 //-----------------------------------------------------------------------------
2346 sal_Bool SAL_CALL SfxDocTplService::renameTemplate( const OUString& rGroupName,
2347 const OUString& rOldName,
2348 const OUString& rNewName )
2349 throw( RUNTIMEEXCEPTION )
2351 if ( rOldName == rNewName )
2352 return sal_True;
2354 if ( pImp->init() )
2355 return pImp->renameTemplate( rGroupName, rOldName, rNewName );
2356 else
2357 return sal_False;
2360 //-----------------------------------------------------------------------------
2361 sal_Bool SAL_CALL SfxDocTplService::addGroup( const OUString& rGroupName )
2362 throw( RUNTIMEEXCEPTION )
2364 if ( pImp->init() )
2365 return pImp->addGroup( rGroupName );
2366 else
2367 return sal_False;
2370 //-----------------------------------------------------------------------------
2371 sal_Bool SAL_CALL SfxDocTplService::removeGroup( const OUString& rGroupName )
2372 throw( RUNTIMEEXCEPTION )
2374 if ( pImp->init() )
2375 return pImp->removeGroup( rGroupName );
2376 else
2377 return sal_False;
2380 //-----------------------------------------------------------------------------
2381 sal_Bool SAL_CALL SfxDocTplService::renameGroup( const OUString& rOldName,
2382 const OUString& rNewName )
2383 throw( RUNTIMEEXCEPTION )
2385 if ( rOldName == rNewName )
2386 return sal_True;
2388 if ( pImp->init() )
2389 return pImp->renameGroup( rOldName, rNewName );
2390 else
2391 return sal_False;
2394 //-----------------------------------------------------------------------------
2395 void SAL_CALL SfxDocTplService::update()
2396 throw( RUNTIMEEXCEPTION )
2398 if ( pImp->init() )
2399 pImp->update( sal_True );
2402 //-----------------------------------------------------------------------------
2403 //-----------------------------------------------------------------------------
2404 //------------------------------------------------------------------------
2406 Updater_Impl::Updater_Impl( SfxDocTplService_Impl* pTemplates )
2408 mpDocTemplates = pTemplates;
2411 //------------------------------------------------------------------------
2412 Updater_Impl::~Updater_Impl()
2416 //------------------------------------------------------------------------
2417 void SAL_CALL Updater_Impl::run()
2419 mpDocTemplates->doUpdate();
2422 //------------------------------------------------------------------------
2423 void SAL_CALL Updater_Impl::onTerminated()
2425 mpDocTemplates->finished();
2426 delete this;
2429 //-----------------------------------------------------------------------------
2430 //-----------------------------------------------------------------------------
2431 //-----------------------------------------------------------------------------
2432 WaitWindow_Impl::WaitWindow_Impl()
2433 : WorkWindow( NULL, WB_BORDER | WB_3DLOOK )
2435 Rectangle aRect = Rectangle( 0, 0, 300, 30000 );
2436 _nTextStyle = TEXT_DRAW_CENTER | TEXT_DRAW_VCENTER | TEXT_DRAW_WORDBREAK | TEXT_DRAW_MULTILINE;
2437 _aText = String( SfxResId( RID_CNT_STR_WAITING ) );
2438 _aRect = GetTextRect( aRect, _aText, _nTextStyle );
2439 aRect = _aRect;
2440 aRect.Right() += 2*X_OFFSET;
2441 aRect.Bottom() += 2*Y_OFFSET;
2442 _aRect.SetPos( Point( X_OFFSET, Y_OFFSET ) );
2443 SetOutputSizePixel( aRect.GetSize() );
2444 Show();
2445 Update();
2446 Flush();
2449 //-----------------------------------------------------------------------------
2450 WaitWindow_Impl::~WaitWindow_Impl()
2452 Hide();
2455 //-----------------------------------------------------------------------------
2456 void WaitWindow_Impl::Paint( const Rectangle& /*rRect*/ )
2458 DrawText( _aRect, _aText, _nTextStyle );
2461 //-----------------------------------------------------------------------------
2462 //-----------------------------------------------------------------------------
2463 //-----------------------------------------------------------------------------
2464 void SfxDocTplService_Impl::addHierGroup( GroupList_Impl& rList,
2465 const OUString& rTitle,
2466 const OUString& rOwnURL )
2468 // now get the content of the Group
2469 Content aContent;
2470 uno::Reference< XResultSet > xResultSet;
2471 Sequence< OUString > aProps(3);
2473 aProps[0] = OUString::createFromAscii( TITLE );
2474 aProps[1] = OUString::createFromAscii( TARGET_URL );
2475 aProps[2] = OUString::createFromAscii( PROPERTY_TYPE );
2479 aContent = Content( rOwnURL, maCmdEnv );
2480 ResultSetInclude eInclude = INCLUDE_DOCUMENTS_ONLY;
2481 xResultSet = aContent.createCursor( aProps, eInclude );
2483 catch ( ContentCreationException& )
2485 DBG_ERRORFILE( "addHierGroup: ContentCreationException" );
2487 catch ( Exception& ) {}
2489 if ( xResultSet.is() )
2491 GroupData_Impl *pGroup = new GroupData_Impl( rTitle );
2492 pGroup->setHierarchy( sal_True );
2493 pGroup->setHierarchyURL( rOwnURL );
2494 rList.Insert( pGroup );
2496 uno::Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY );
2497 uno::Reference< XRow > xRow( xResultSet, UNO_QUERY );
2501 while ( xResultSet->next() )
2503 BOOL bUpdateType = sal_False;
2504 DocTemplates_EntryData_Impl *pData;
2506 OUString aTitle( xRow->getString( 1 ) );
2507 OUString aTargetDir( xRow->getString( 2 ) );
2508 OUString aType( xRow->getString( 3 ) );
2509 OUString aHierURL = xContentAccess->queryContentIdentifierString();
2511 if ( !aType.getLength() )
2513 OUString aTmpTitle;
2515 sal_Bool bDocHasTitle = sal_False;
2516 if( !getTitleFromURL( aTargetDir, aTmpTitle, aType, bDocHasTitle ) )
2518 DBG_ERRORFILE( "addHierGroup(): template of alien format" );
2519 continue;
2522 if ( aType.getLength() )
2523 bUpdateType = sal_True;
2526 pData = pGroup->addEntry( aTitle, aTargetDir, aType, aHierURL );
2527 pData->setUpdateType( bUpdateType );
2530 catch ( Exception& ) {}
2534 //-----------------------------------------------------------------------------
2535 void SfxDocTplService_Impl::addFsysGroup( GroupList_Impl& rList,
2536 const OUString& rTitle,
2537 const OUString& rUITitle,
2538 const OUString& rOwnURL,
2539 sal_Bool bWriteableGroup )
2541 ::rtl::OUString aTitle;
2543 if ( !rUITitle.getLength() )
2545 // reserved FS names that should not be used
2546 if ( rTitle.compareToAscii( "wizard" ) == 0 )
2547 return;
2548 else if ( rTitle.compareToAscii( "internal" ) == 0 )
2549 return;
2551 aTitle = getLongName( rTitle );
2553 else
2554 aTitle = rUITitle;
2556 if ( !aTitle.getLength() )
2557 return;
2559 GroupData_Impl *pGroup = rList.First();
2561 while ( pGroup && pGroup->getTitle() != aTitle )
2562 pGroup = rList.Next();
2564 if ( !pGroup )
2566 pGroup = new GroupData_Impl( aTitle );
2567 rList.Insert( pGroup );
2570 if ( bWriteableGroup )
2571 pGroup->setTargetURL( rOwnURL );
2573 pGroup->setInUse();
2575 // now get the content of the Group
2576 Content aContent;
2577 uno::Reference< XResultSet > xResultSet;
2578 Sequence< OUString > aProps(1);
2579 aProps[0] = OUString::createFromAscii( TITLE );
2583 // this method is only used during checking of the available template-folders
2584 // that should happen quietly
2585 uno::Reference< XCommandEnvironment > aQuietEnv;
2586 aContent = Content( rOwnURL, aQuietEnv );
2587 ResultSetInclude eInclude = INCLUDE_DOCUMENTS_ONLY;
2588 xResultSet = aContent.createCursor( aProps, eInclude );
2590 catch ( Exception& ) {}
2592 if ( xResultSet.is() )
2594 uno::Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY );
2595 uno::Reference< XRow > xRow( xResultSet, UNO_QUERY );
2599 while ( xResultSet->next() )
2601 OUString aChildTitle( xRow->getString( 1 ) );
2602 OUString aTargetURL = xContentAccess->queryContentIdentifierString();
2603 OUString aType;
2604 OUString aHierURL;
2606 if ( aChildTitle.compareToAscii( "sfx.tlx" ) == 0
2607 || aChildTitle.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "groupuinames.xml" ) ) )
2608 continue;
2610 // only StarOffice templates are accepted
2611 sal_Bool bDocHasTitle = sal_False;
2612 if( !getTitleFromURL( aTargetURL, aChildTitle, aType, bDocHasTitle ) )
2613 continue;
2615 pGroup->addEntry( aChildTitle, aTargetURL, aType, aHierURL );
2618 catch ( Exception& ) {}
2622 // -----------------------------------------------------------------------
2623 void SfxDocTplService_Impl::createFromContent( GroupList_Impl& rList,
2624 Content &rContent,
2625 sal_Bool bHierarchy,
2626 sal_Bool bWriteableContent )
2628 OUString aTargetURL = rContent.get()->getIdentifier()->getContentIdentifier();
2630 // when scanning the file system, we have to add the 'standard' group, too
2631 if ( ! bHierarchy )
2633 OUString aUIStdTitle = getLongName( OUString( RTL_CONSTASCII_USTRINGPARAM( STANDARD_FOLDER ) ) );
2634 addFsysGroup( rList, ::rtl::OUString(), aUIStdTitle, aTargetURL, bWriteableContent );
2637 // search for predefined UI names
2638 INetURLObject aLayerObj( aTargetURL );
2640 // TODO/LATER: Use hashmap in future
2641 uno::Sequence< beans::StringPair > aUINames;
2642 if ( !bHierarchy )
2643 aUINames = ReadUINamesForTemplateDir_Impl( aLayerObj.GetMainURL( INetURLObject::NO_DECODE ) );
2645 uno::Reference< XResultSet > xResultSet;
2646 Sequence< OUString > aProps(1);
2647 aProps[0] = OUString::createFromAscii( TITLE );
2651 ResultSetInclude eInclude = INCLUDE_FOLDERS_ONLY;
2652 xResultSet = rContent.createCursor( aProps, eInclude );
2654 catch ( Exception& ) {}
2656 if ( xResultSet.is() )
2658 uno::Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY );
2659 uno::Reference< XRow > xRow( xResultSet, UNO_QUERY );
2663 while ( xResultSet->next() )
2665 // TODO/LATER: clarify the encoding of the Title
2666 OUString aTitle( xRow->getString( 1 ) );
2667 OUString aTargetSubfolderURL( xContentAccess->queryContentIdentifierString() );
2669 if ( bHierarchy )
2670 addHierGroup( rList, aTitle, aTargetSubfolderURL );
2671 else
2673 ::rtl::OUString aUITitle;
2674 for ( sal_Int32 nInd = 0; nInd < aUINames.getLength(); nInd++ )
2675 if ( aUINames[nInd].First.equals( aTitle ) )
2677 aUITitle = aUINames[nInd].Second;
2678 break;
2681 addFsysGroup( rList, aTitle, aUITitle, aTargetSubfolderURL, bWriteableContent );
2685 catch ( Exception& ) {}
2689 //-----------------------------------------------------------------------------
2690 void SfxDocTplService_Impl::removeFromHierarchy( DocTemplates_EntryData_Impl *pData )
2692 Content aTemplate;
2694 if ( Content::create( pData->getHierarchyURL(), maCmdEnv, aTemplate ) )
2696 removeContent( aTemplate );
2700 //-----------------------------------------------------------------------------
2701 void SfxDocTplService_Impl::addToHierarchy( GroupData_Impl *pGroup,
2702 DocTemplates_EntryData_Impl *pData )
2704 Content aGroup, aTemplate;
2706 if ( ! Content::create( pGroup->getHierarchyURL(), maCmdEnv, aGroup ) )
2707 return;
2709 // Check, if there's a template with the given name in this group
2710 // Return if there is already a template
2711 INetURLObject aGroupObj( pGroup->getHierarchyURL() );
2713 aGroupObj.insertName( pData->getTitle(), false,
2714 INetURLObject::LAST_SEGMENT, true,
2715 INetURLObject::ENCODE_ALL );
2717 OUString aTemplateURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE );
2719 if ( Content::create( aTemplateURL, maCmdEnv, aTemplate ) )
2720 return;
2722 addEntry( aGroup, pData->getTitle(),
2723 pData->getTargetURL(),
2724 pData->getType() );
2727 //-----------------------------------------------------------------------------
2728 void SfxDocTplService_Impl::updateData( DocTemplates_EntryData_Impl *pData )
2730 Content aTemplate;
2732 if ( ! Content::create( pData->getHierarchyURL(), maCmdEnv, aTemplate ) )
2733 return;
2735 OUString aPropName;
2737 if ( pData->getUpdateType() )
2739 aPropName = OUString( RTL_CONSTASCII_USTRINGPARAM( PROPERTY_TYPE ) );
2740 setProperty( aTemplate, aPropName, makeAny( pData->getType() ) );
2743 if ( pData->getUpdateLink() )
2745 aPropName = OUString( RTL_CONSTASCII_USTRINGPARAM( TARGET_URL ) );
2746 setProperty( aTemplate, aPropName, makeAny( pData->getTargetURL() ) );
2750 //-----------------------------------------------------------------------------
2751 void SfxDocTplService_Impl::addGroupToHierarchy( GroupData_Impl *pGroup )
2753 OUString aAdditionalProp( RTL_CONSTASCII_USTRINGPARAM( TARGET_DIR_URL ) );
2754 Content aGroup;
2756 INetURLObject aNewGroupObj( maRootURL );
2757 aNewGroupObj.insertName( pGroup->getTitle(), false,
2758 INetURLObject::LAST_SEGMENT, true,
2759 INetURLObject::ENCODE_ALL );
2761 OUString aNewGroupURL = aNewGroupObj.GetMainURL( INetURLObject::NO_DECODE );
2763 if ( createFolder( aNewGroupURL, sal_False, sal_False, aGroup ) )
2765 setProperty( aGroup, aAdditionalProp, makeAny( pGroup->getTargetURL() ) );
2766 pGroup->setHierarchyURL( aNewGroupURL );
2768 ULONG nCount = pGroup->count();
2769 for ( ULONG i=0; i<nCount; i++ )
2771 DocTemplates_EntryData_Impl *pData = pGroup->getEntry( i );
2772 addToHierarchy( pGroup, pData ); // add entry to hierarchy
2777 //-----------------------------------------------------------------------------
2778 void SfxDocTplService_Impl::removeFromHierarchy( GroupData_Impl *pGroup )
2780 Content aGroup;
2782 if ( Content::create( pGroup->getHierarchyURL(), maCmdEnv, aGroup ) )
2784 removeContent( aGroup );
2788 // -----------------------------------------------------------------------
2789 // -----------------------------------------------------------------------
2790 // -----------------------------------------------------------------------
2791 GroupData_Impl::GroupData_Impl( const OUString& rTitle )
2793 maTitle = rTitle;
2794 mbInUse = sal_False;
2795 mbInHierarchy = sal_False;
2798 // -----------------------------------------------------------------------
2799 GroupData_Impl::~GroupData_Impl()
2801 DocTemplates_EntryData_Impl *pData = maEntries.First();
2802 while ( pData )
2804 delete pData;
2805 pData = maEntries.Next();
2809 // -----------------------------------------------------------------------
2810 DocTemplates_EntryData_Impl* GroupData_Impl::addEntry( const OUString& rTitle,
2811 const OUString& rTargetURL,
2812 const OUString& rType,
2813 const OUString& rHierURL )
2815 DocTemplates_EntryData_Impl *pData = maEntries.First();
2817 while ( pData && pData->getTitle() != rTitle )
2818 pData = maEntries.Next();
2820 if ( !pData )
2822 pData = new DocTemplates_EntryData_Impl( rTitle );
2823 pData->setTargetURL( rTargetURL );
2824 pData->setType( rType );
2825 if ( rHierURL.getLength() )
2827 pData->setHierarchyURL( rHierURL );
2828 pData->setHierarchy( sal_True );
2830 maEntries.Insert( pData );
2832 else
2834 if ( rHierURL.getLength() )
2836 pData->setHierarchyURL( rHierURL );
2837 pData->setHierarchy( sal_True );
2840 if ( pData->getInHierarchy() )
2841 pData->setInUse();
2843 if ( rTargetURL != pData->getTargetURL() )
2845 pData->setTargetURL( rTargetURL );
2846 pData->setUpdateLink( sal_True );
2850 return pData;
2853 // -----------------------------------------------------------------------
2854 // -----------------------------------------------------------------------
2855 // -----------------------------------------------------------------------
2856 DocTemplates_EntryData_Impl::DocTemplates_EntryData_Impl( const OUString& rTitle )
2858 maTitle = rTitle;
2859 mbInUse = sal_False;
2860 mbInHierarchy = sal_False;
2861 mbUpdateType = sal_False;
2862 mbUpdateLink = sal_False;
2865 // -----------------------------------------------------------------------
2866 SfxURLRelocator_Impl::SfxURLRelocator_Impl( uno::Reference< XMultiServiceFactory > xFactory )
2867 : mxFactory( xFactory )
2871 // -----------------------------------------------------------------------
2872 SfxURLRelocator_Impl::~SfxURLRelocator_Impl()
2876 // -----------------------------------------------------------------------
2877 void SfxURLRelocator_Impl::initOfficeInstDirs()
2879 if ( !mxOfficeInstDirs.is() )
2881 osl::MutexGuard aGuard( maMutex );
2882 if ( !mxOfficeInstDirs.is() )
2884 OSL_ENSURE( mxFactory.is(), "No service manager!" );
2886 uno::Reference< XComponentContext > xCtx;
2887 uno::Reference< XPropertySet > xPropSet( mxFactory, UNO_QUERY );
2888 if ( xPropSet.is() )
2890 xPropSet->getPropertyValue(
2891 rtl::OUString(
2892 RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ) ) )
2893 >>= xCtx;
2896 OSL_ENSURE( xCtx.is(),
2897 "Unable to obtain component context from "
2898 "service manager!" );
2900 if ( xCtx.is() )
2902 xCtx->getValueByName(
2903 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
2904 "/singletons/"
2905 "com.sun.star.util.theOfficeInstallationDirectories" ) ) )
2906 >>= mxOfficeInstDirs;
2909 OSL_ENSURE( mxOfficeInstDirs.is(),
2910 "Unable to obtain office installation directory "
2911 "singleton!" );
2916 // -----------------------------------------------------------------------
2917 void SfxURLRelocator_Impl::makeRelocatableURL( rtl::OUString & rURL )
2919 if ( rURL.getLength() > 0 )
2921 initOfficeInstDirs();
2922 rURL = mxOfficeInstDirs->makeRelocatableURL( rURL );
2926 // -----------------------------------------------------------------------
2927 void SfxURLRelocator_Impl::makeAbsoluteURL( rtl::OUString & rURL )
2929 if ( rURL.getLength() > 0 )
2931 initOfficeInstDirs();
2932 rURL = mxOfficeInstDirs->makeAbsoluteURL( rURL );