Update ooo320-m1
[ooovba.git] / sfx2 / source / doc / doctemplates.cxx
blobf3d1bc55fa890608474940b2504e10ff5462b498
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 <sfx2/docfile.hxx>
78 #include "doc.hrc"
80 //-----------------------------------------------------------------------------
82 //=============================================================================
84 #define TEMPLATE_SERVICE_NAME "com.sun.star.frame.DocumentTemplates"
85 #define TEMPLATE_IMPLEMENTATION_NAME "com.sun.star.comp.sfx2.DocumentTemplates"
87 #define SERVICENAME_TYPEDETECTION "com.sun.star.document.TypeDetection"
88 #define SERVICENAME_DOCINFO "com.sun.star.document.StandaloneDocumentInfo"
90 #define TEMPLATE_ROOT_URL "vnd.sun.star.hier:/templates"
91 #define TITLE "Title"
92 #define IS_FOLDER "IsFolder"
93 #define IS_DOCUMENT "IsDocument"
94 #define TARGET_URL "TargetURL"
95 #define TEMPLATE_VERSION "TemplateComponentVersion"
96 #define TEMPLATE_VERSION_VALUE "2"
97 #define TYPE_FOLDER "application/vnd.sun.star.hier-folder"
98 #define TYPE_LINK "application/vnd.sun.star.hier-link"
99 #define TYPE_FSYS_FOLDER "application/vnd.sun.staroffice.fsys-folder"
100 #define TYPE_FSYS_FILE "application/vnd.sun.staroffice.fsys-file"
102 #define PROPERTY_DIRLIST "DirectoryList"
103 #define PROPERTY_NEEDSUPDATE "NeedsUpdate"
104 #define PROPERTY_TYPE "TypeDescription"
106 #define TARGET_DIR_URL "TargetDirURL"
107 #define COMMAND_DELETE "delete"
108 #define COMMAND_TRANSFER "transfer"
110 #define STANDARD_FOLDER "standard"
112 #define C_DELIM ';'
114 //=============================================================================
116 using namespace ::com::sun::star;
117 using namespace ::com::sun::star::beans;
118 using namespace ::com::sun::star::document;
119 using namespace ::com::sun::star::io;
120 using namespace ::com::sun::star::lang;
121 using namespace ::com::sun::star::sdbc;
122 using namespace ::com::sun::star::ucb;
123 using namespace ::com::sun::star::uno;
124 using namespace ::com::sun::star::container;
125 using namespace ::com::sun::star::util;
127 using namespace ::rtl;
128 using namespace ::ucbhelper;
129 using namespace ::comphelper;
131 //=============================================================================
133 class WaitWindow_Impl : public WorkWindow
135 Rectangle _aRect;
136 USHORT _nTextStyle;
137 String _aText;
139 public:
140 WaitWindow_Impl();
141 ~WaitWindow_Impl();
142 virtual void Paint( const Rectangle& rRect );
145 #define X_OFFSET 15
146 #define Y_OFFSET 15
148 //=============================================================================
150 struct NamePair_Impl
152 OUString maShortName;
153 OUString maLongName;
156 DECLARE_LIST( NameList_Impl, NamePair_Impl* )
158 class Updater_Impl;
159 class GroupList_Impl;
160 class DocTemplates_EntryData_Impl;
161 class GroupData_Impl;
163 //=============================================================================
164 #include <com/sun/star/task/XInteractionHandler.hpp>
165 #include <com/sun/star/ucb/XProgressHandler.hpp>
166 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
168 class TplTaskEnvironment : public ::cppu::WeakImplHelper1< ucb::XCommandEnvironment >
170 uno::Reference< task::XInteractionHandler > m_xInteractionHandler;
171 uno::Reference< ucb::XProgressHandler > m_xProgressHandler;
173 public:
174 TplTaskEnvironment( const uno::Reference< task::XInteractionHandler>& rxInteractionHandler )
175 : m_xInteractionHandler( rxInteractionHandler )
178 virtual uno::Reference<task::XInteractionHandler> SAL_CALL getInteractionHandler() throw (uno::RuntimeException)
179 { return m_xInteractionHandler; }
181 virtual uno::Reference<ucb::XProgressHandler> SAL_CALL getProgressHandler() throw (uno::RuntimeException)
182 { return m_xProgressHandler; }
185 class SfxDocTplService_Impl
187 uno::Reference< XMultiServiceFactory > mxFactory;
188 uno::Reference< XCommandEnvironment > maCmdEnv;
189 uno::Reference< XStandaloneDocumentInfo > mxInfo;
190 uno::Reference< XTypeDetection > mxType;
192 ::osl::Mutex maMutex;
193 Sequence< OUString > maTemplateDirs;
194 OUString maRootURL;
195 NameList_Impl maNames;
196 Locale maLocale;
197 Content maRootContent;
198 Updater_Impl* mpUpdater;
199 sal_Bool mbIsInitialized : 1;
200 sal_Bool mbLocaleSet : 1;
202 SfxURLRelocator_Impl maRelocator;
204 void init_Impl();
205 void getDefaultLocale();
206 void getDirList();
207 void readFolderList();
208 sal_Bool needsUpdate();
209 OUString getLongName( const OUString& rShortName );
210 sal_Bool setTitleForURL( const OUString& rURL, const OUString& aTitle );
211 sal_Bool getTitleFromURL( const OUString& rURL, OUString& aTitle, OUString& aType, sal_Bool& bDocHasTitle );
213 sal_Bool addEntry( Content& rParentFolder,
214 const OUString& rTitle,
215 const OUString& rTargetURL,
216 const OUString& rType );
218 sal_Bool createFolder( const OUString& rNewFolderURL,
219 sal_Bool bCreateParent,
220 sal_Bool bFsysFolder,
221 Content &rNewFolder );
223 sal_Bool CreateNewUniqueFolderWithPrefix( const ::rtl::OUString& aPath,
224 const ::rtl::OUString& aPrefix,
225 ::rtl::OUString& aNewFolderName,
226 ::rtl::OUString& aNewFolderURL,
227 Content& aNewFolder );
228 ::rtl::OUString CreateNewUniqueFileWithPrefix( const ::rtl::OUString& aPath,
229 const ::rtl::OUString& aPrefix,
230 const ::rtl::OUString& aExt );
232 uno::Sequence< beans::StringPair > ReadUINamesForTemplateDir_Impl( const ::rtl::OUString& aUserPath );
233 sal_Bool UpdateUINamesForTemplateDir_Impl( const ::rtl::OUString& aUserPath,
234 const ::rtl::OUString& aGroupName,
235 const ::rtl::OUString& aNewFolderName );
236 sal_Bool ReplaceUINamesForTemplateDir_Impl( const ::rtl::OUString& aUserPath,
237 const ::rtl::OUString& aFsysGroupName,
238 const ::rtl::OUString& aOldGroupName,
239 const ::rtl::OUString& aNewGroupName );
240 sal_Bool RemoveUINamesForTemplateDir_Impl( const ::rtl::OUString& aUserPath,
241 const ::rtl::OUString& aGroupName );
242 sal_Bool WriteUINamesForTemplateDir_Impl( const ::rtl::OUString& aUserPath,
243 const uno::Sequence< beans::StringPair >& aUINames );
245 ::rtl::OUString CreateNewGroupFsys( const ::rtl::OUString& rGroupName, Content& aGroup );
247 sal_Bool removeContent( Content& rContent );
248 sal_Bool removeContent( const OUString& rContentURL );
250 sal_Bool setProperty( Content& rContent,
251 const OUString& rPropName,
252 const Any& rPropValue );
253 sal_Bool getProperty( Content& rContent,
254 const OUString& rPropName,
255 Any& rPropValue );
257 void createFromContent( GroupList_Impl& rList,
258 Content &rContent,
259 sal_Bool bHierarchy,
260 sal_Bool bWriteableContent = sal_False );
261 void addHierGroup( GroupList_Impl& rList,
262 const OUString& rTitle,
263 const OUString& rOwnURL );
264 void addFsysGroup( GroupList_Impl& rList,
265 const OUString& rTitle,
266 const OUString& rUITitle,
267 const OUString& rOwnURL,
268 sal_Bool bWriteableGroup = sal_False );
269 void removeFromHierarchy( DocTemplates_EntryData_Impl *pData );
270 void addToHierarchy( GroupData_Impl *pGroup,
271 DocTemplates_EntryData_Impl *pData );
273 void removeFromHierarchy( GroupData_Impl *pGroup );
274 void addGroupToHierarchy( GroupData_Impl *pGroup );
276 void updateData( DocTemplates_EntryData_Impl *pData );
278 public:
279 SfxDocTplService_Impl( uno::Reference< XMultiServiceFactory > xFactory );
280 ~SfxDocTplService_Impl();
282 sal_Bool init() { if ( !mbIsInitialized ) init_Impl(); return mbIsInitialized; }
283 Content getContent() { return maRootContent; }
285 void setLocale( const Locale & rLocale );
286 Locale getLocale();
288 sal_Bool storeTemplate( const OUString& rGroupName,
289 const OUString& rTemplateName,
290 const uno::Reference< XSTORABLE >& rStorable );
292 sal_Bool addTemplate( const OUString& rGroupName,
293 const OUString& rTemplateName,
294 const OUString& rSourceURL );
295 sal_Bool removeTemplate( const OUString& rGroupName,
296 const OUString& rTemplateName );
297 sal_Bool renameTemplate( const OUString& rGroupName,
298 const OUString& rOldName,
299 const OUString& rNewName );
301 sal_Bool addGroup( const OUString& rGroupName );
302 sal_Bool removeGroup( const OUString& rGroupName );
303 sal_Bool renameGroup( const OUString& rOldName,
304 const OUString& rNewName );
306 void update( sal_Bool bUpdateNow );
307 void doUpdate();
308 void finished() { mpUpdater = NULL; }
311 //=============================================================================
313 class Updater_Impl : public ::vos::OThread
315 private:
316 SfxDocTplService_Impl *mpDocTemplates;
318 public:
319 Updater_Impl( SfxDocTplService_Impl* pTemplates );
320 ~Updater_Impl();
322 virtual void SAL_CALL run();
323 virtual void SAL_CALL onTerminated();
326 //=============================================================================
328 class DocTemplates_EntryData_Impl
330 OUString maTitle;
331 OUString maType;
332 OUString maTargetURL;
333 OUString maHierarchyURL;
335 sal_Bool mbInHierarchy : 1;
336 sal_Bool mbInUse : 1;
337 sal_Bool mbUpdateType : 1;
338 sal_Bool mbUpdateLink : 1;
340 public:
341 DocTemplates_EntryData_Impl( const OUString& rTitle );
343 void setInUse() { mbInUse = sal_True; }
344 void setHierarchy( sal_Bool bInHierarchy ) { mbInHierarchy = bInHierarchy; }
345 void setUpdateLink( sal_Bool bUpdateLink ) { mbUpdateLink = bUpdateLink; }
346 void setUpdateType( sal_Bool bUpdateType ) { mbUpdateType = bUpdateType; }
348 sal_Bool getInUse() const { return mbInUse; }
349 sal_Bool getInHierarchy() const { return mbInHierarchy; }
350 sal_Bool getUpdateLink() const { return mbUpdateLink; }
351 sal_Bool getUpdateType() const { return mbUpdateType; }
353 const OUString& getHierarchyURL() const { return maHierarchyURL; }
354 const OUString& getTargetURL() const { return maTargetURL; }
355 const OUString& getTitle() const { return maTitle; }
356 const OUString& getType() const { return maType; }
358 void setHierarchyURL( const OUString& rURL ) { maHierarchyURL = rURL; }
359 void setTargetURL( const OUString& rURL ) { maTargetURL = rURL; }
360 void setType( const OUString& rType ) { maType = rType; }
363 //=============================================================================
365 class GroupData_Impl
367 DECLARE_LIST( EntryList_Impl, DocTemplates_EntryData_Impl* )
368 EntryList_Impl maEntries;
369 OUString maTitle;
370 OUString maHierarchyURL;
371 OUString maTargetURL;
372 sal_Bool mbInUse : 1;
373 sal_Bool mbInHierarchy : 1;
375 public:
376 GroupData_Impl( const OUString& rTitle );
377 ~GroupData_Impl();
379 void setInUse() { mbInUse = sal_True; }
380 void setHierarchy( sal_Bool bInHierarchy ) { mbInHierarchy = bInHierarchy; }
381 void setHierarchyURL( const OUString& rURL ) { maHierarchyURL = rURL; }
382 void setTargetURL( const OUString& rURL ) { maTargetURL = rURL; }
384 sal_Bool getInUse() { return mbInUse; }
385 sal_Bool getInHierarchy() { return mbInHierarchy; }
386 const OUString& getHierarchyURL() const { return maHierarchyURL; }
387 const OUString& getTargetURL() const { return maTargetURL; }
388 const OUString& getTitle() const { return maTitle; }
390 DocTemplates_EntryData_Impl* addEntry( const OUString& rTitle,
391 const OUString& rTargetURL,
392 const OUString& rType,
393 const OUString& rHierURL );
394 ULONG count() { return maEntries.Count(); }
395 DocTemplates_EntryData_Impl* getEntry( ULONG nPos ) { return maEntries.GetObject( nPos ); }
398 DECLARE_LIST( GroupList_Impl, GroupData_Impl* )
400 //=============================================================================
401 //=============================================================================
402 //=============================================================================
404 //-----------------------------------------------------------------------------
405 // private SfxDocTplService_Impl
406 //-----------------------------------------------------------------------------
407 void SfxDocTplService_Impl::init_Impl()
409 uno::Reference< lang::XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory();
410 if ( xFactory.is() )
412 uno::Reference < task::XInteractionHandler > xInteractionHandler( xFactory->createInstance( DEFINE_CONST_UNICODE("com.sun.star.task.InteractionHandler") ), uno::UNO_QUERY );
413 maCmdEnv = new TplTaskEnvironment( xInteractionHandler );
416 ::osl::ClearableMutexGuard aGuard( maMutex );
417 sal_Bool bIsInitialized = sal_False;
418 sal_Bool bNeedsUpdate = sal_False;
420 if ( !mbLocaleSet )
421 getDefaultLocale();
423 // convert locale to string
424 OUString aLang = maLocale.Language;
425 aLang += String( '-' );
426 aLang += maLocale.Country;
428 // set maRootContent to the root of the templates hierarchy. Create the
429 // entry if necessary
431 maRootURL = OUString( RTL_CONSTASCII_USTRINGPARAM( TEMPLATE_ROOT_URL ) );
432 maRootURL += String( '/' );
433 maRootURL += aLang;
435 ::rtl::OUString aTemplVersPropName( RTL_CONSTASCII_USTRINGPARAM( TEMPLATE_VERSION ) );
436 ::rtl::OUString aTemplVers( RTL_CONSTASCII_USTRINGPARAM( TEMPLATE_VERSION_VALUE ) );
437 if ( Content::create( maRootURL, maCmdEnv, maRootContent ) )
439 uno::Any aValue;
440 ::rtl::OUString aPropValue;
441 if ( getProperty( maRootContent, aTemplVersPropName, aValue )
442 && ( aValue >>= aPropValue )
443 && aPropValue.equals( aTemplVers ) )
445 bIsInitialized = sal_True;
447 else
448 removeContent( maRootContent );
451 if ( !bIsInitialized )
453 if ( createFolder( maRootURL, sal_True, sal_False, maRootContent )
454 && setProperty( maRootContent, aTemplVersPropName, uno::makeAny( aTemplVers ) ) )
455 bIsInitialized = sal_True;
457 bNeedsUpdate = sal_True;
460 if ( bIsInitialized )
462 OUString aService( RTL_CONSTASCII_USTRINGPARAM( SERVICENAME_DOCINFO ) );
463 try {
464 mxInfo = uno::Reference< XStandaloneDocumentInfo > (
465 mxFactory->createInstance( aService ), UNO_QUERY );
466 } catch (uno::RuntimeException &) {
467 OSL_ENSURE(false, "SfxDocTplService_Impl::init_Impl: "
468 "cannot create DocumentProperties service");
471 aService = OUString( RTL_CONSTASCII_USTRINGPARAM( SERVICENAME_TYPEDETECTION ) );
472 mxType = uno::Reference< XTypeDetection > ( mxFactory->createInstance( aService ), UNO_QUERY );
474 getDirList();
475 readFolderList();
477 if ( bNeedsUpdate )
479 aGuard.clear();
480 ::vos::OClearableGuard aSolarGuard( Application::GetSolarMutex() );
482 WaitWindow_Impl* pWin = new WaitWindow_Impl();
484 aSolarGuard.clear();
485 ::osl::ClearableMutexGuard anotherGuard( maMutex );
487 update( sal_True );
489 anotherGuard.clear();
490 ::vos::OGuard aSecondSolarGuard( Application::GetSolarMutex() );
492 delete pWin;
494 else if ( needsUpdate() )
495 // the UI should be shown only on the first update
496 update( sal_True );
498 else
500 DBG_ERRORFILE( "init_Impl(): Could not create root" );
503 mbIsInitialized = bIsInitialized;
506 //-----------------------------------------------------------------------------
507 void SfxDocTplService_Impl::getDefaultLocale()
509 if ( !mbLocaleSet )
511 ::osl::MutexGuard aGuard( maMutex );
512 if ( !mbLocaleSet )
514 rtl::OUString aLocale;
515 utl::ConfigManager::GetDirectConfigProperty( utl::ConfigManager::LOCALE )
516 >>= aLocale;
518 if ( aLocale.getLength() > 0 )
520 sal_Int32 nPos = aLocale.indexOf( sal_Unicode( '-' ) );
521 if ( nPos != -1 )
523 maLocale.Language = aLocale.copy( 0, nPos );
524 nPos = aLocale.indexOf( sal_Unicode( '_' ), nPos + 1 );
525 if ( nPos != -1 )
527 maLocale.Country
528 = aLocale.copy( maLocale.Language.getLength() + 1,
529 nPos - maLocale.Language.getLength() - 1 );
530 maLocale.Variant
531 = aLocale.copy( nPos + 1 );
533 else
535 maLocale.Country
536 = aLocale.copy( maLocale.Language.getLength() + 1 );
542 mbLocaleSet = sal_True;
547 // -----------------------------------------------------------------------
548 void SfxDocTplService_Impl::readFolderList()
550 ::vos::OGuard aGuard( Application::GetSolarMutex() );
552 ResStringArray aShortNames( SfxResId( TEMPLATE_SHORT_NAMES_ARY ) );
553 ResStringArray aLongNames( SfxResId( TEMPLATE_LONG_NAMES_ARY ) );
555 NamePair_Impl* pPair;
557 USHORT nCount = (USHORT)( Min( aShortNames.Count(), aLongNames.Count() ) );
559 for ( USHORT i=0; i<nCount; i++ )
561 pPair = new NamePair_Impl;
562 pPair->maShortName = aShortNames.GetString( i );
563 pPair->maLongName = aLongNames.GetString( i );
565 maNames.Insert( pPair, LIST_APPEND );
569 // -----------------------------------------------------------------------
570 OUString SfxDocTplService_Impl::getLongName( const OUString& rShortName )
572 OUString aRet;
573 NamePair_Impl *pPair = maNames.First();
575 while ( pPair )
577 if ( pPair->maShortName == rShortName )
579 aRet = pPair->maLongName;
580 break;
582 else
583 pPair = maNames.Next();
586 if ( !aRet.getLength() )
587 aRet = rShortName;
589 return aRet;
592 //-----------------------------------------------------------------------------
593 void SfxDocTplService_Impl::getDirList()
595 OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( PROPERTY_DIRLIST ) );
596 Any aValue;
598 // Get the template dir list
599 // TODO/LATER: let use service, register listener
600 INetURLObject aURL;
601 String aDirs = SvtPathOptions().GetTemplatePath();
602 USHORT nCount = aDirs.GetTokenCount( C_DELIM );
604 maTemplateDirs = Sequence< OUString >( nCount );
606 uno::Reference< XComponentContext > xCtx;
607 uno::Reference< util::XMacroExpander > xExpander;
608 uno::Reference< XPropertySet > xPropSet( mxFactory, UNO_QUERY );
609 const rtl::OUString aPrefix(
610 RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.expand:" ) );
612 if ( xPropSet.is() )
614 xPropSet->getPropertyValue(
615 rtl::OUString(
616 RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ) ) )
617 >>= xCtx;
620 if ( xCtx.is() )
622 xCtx->getValueByName(
623 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
624 "/singletons/com.sun.star.util.theMacroExpander" ) ) )
625 >>= xExpander;
627 OSL_ENSURE( xExpander.is(),
628 "Unable to obtain macro expander singleton!" );
631 for ( USHORT i=0; i<nCount; i++ )
633 aURL.SetSmartProtocol( INET_PROT_FILE );
634 aURL.SetURL( aDirs.GetToken( i, C_DELIM ) );
635 maTemplateDirs[i] = aURL.GetMainURL( INetURLObject::NO_DECODE );
637 sal_Int32 nIndex = maTemplateDirs[i].indexOf( aPrefix );
638 if ( nIndex != -1 && xExpander.is() )
640 maTemplateDirs[i] = maTemplateDirs[i].replaceAt(nIndex,
641 aPrefix.getLength(),
642 rtl::OUString());
643 maTemplateDirs[i] = xExpander->expandMacros( maTemplateDirs[i] );
647 aValue <<= maTemplateDirs;
649 // Store the template dir list
650 setProperty( maRootContent, aPropName, aValue );
653 //-----------------------------------------------------------------------------
654 sal_Bool SfxDocTplService_Impl::needsUpdate()
656 OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( PROPERTY_NEEDSUPDATE ) );
657 sal_Bool bHasProperty = sal_False;
658 sal_Bool bNeedsUpdate = sal_True;
659 Any aValue;
661 // Get the template dir list
662 bHasProperty = getProperty( maRootContent, aPropName, aValue );
664 if ( bHasProperty )
665 aValue >>= bNeedsUpdate;
667 // the old template component also checks this state, but it is initialized from this component
668 // so if this componend was already updated the old component does not need such an update
669 ::svt::TemplateFolderCache aTempCache;
670 if ( !bNeedsUpdate )
671 bNeedsUpdate = aTempCache.needsUpdate();
673 if ( bNeedsUpdate )
674 aTempCache.storeState();
676 return bNeedsUpdate;
679 // -----------------------------------------------------------------------
680 sal_Bool SfxDocTplService_Impl::setTitleForURL( const OUString& rURL, const OUString& aTitle )
682 sal_Bool bResult = sal_False;
683 if ( mxInfo.is() )
687 mxInfo->loadFromURL( rURL );
688 uno::Reference< XPropertySet > xPropSet( mxInfo, UNO_QUERY_THROW );
689 OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( TITLE ) );
690 xPropSet->setPropertyValue( aPropName, uno::makeAny( aTitle ) );
691 mxInfo->storeIntoURL( rURL );
692 bResult = sal_True;
694 catch ( Exception& )
699 return bResult;
702 // -----------------------------------------------------------------------
703 sal_Bool SfxDocTplService_Impl::getTitleFromURL( const OUString& rURL, OUString& aTitle, OUString& aType, sal_Bool& bDocHasTitle )
705 bDocHasTitle = sal_False;
707 if ( mxInfo.is() )
711 mxInfo->loadFromURL( rURL );
713 catch ( Exception& )
715 // the document is not a StarOffice document
716 return sal_False;
721 uno::Reference< XPropertySet > aPropSet( mxInfo, UNO_QUERY );
722 if ( aPropSet.is() )
724 OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( TITLE ) );
725 Any aValue = aPropSet->getPropertyValue( aPropName );
726 aValue >>= aTitle;
728 aPropName = OUString( RTL_CONSTASCII_USTRINGPARAM( "MIMEType" ) );
729 aValue = aPropSet->getPropertyValue( aPropName );
730 aValue >>= aType;
733 catch ( UnknownPropertyException& ) {}
734 catch ( Exception& ) {}
737 if ( ! aType.getLength() && mxType.is() )
739 ::rtl::OUString aDocType = mxType->queryTypeByURL( rURL );
740 if ( aDocType.getLength() )
743 uno::Reference< container::XNameAccess > xTypeDetection( mxType, uno::UNO_QUERY_THROW );
744 SequenceAsHashMap aTypeProps( xTypeDetection->getByName( aDocType ) );
745 aType = aTypeProps.getUnpackedValueOrDefault(
746 ::rtl::OUString::createFromAscii( "MediaType" ),
747 ::rtl::OUString() );
749 catch( uno::Exception& )
753 if ( ! aTitle.getLength() )
755 INetURLObject aURL( rURL );
756 aURL.CutExtension();
757 aTitle = aURL.getName( INetURLObject::LAST_SEGMENT, true,
758 INetURLObject::DECODE_WITH_CHARSET );
760 else
761 bDocHasTitle = sal_True;
763 return sal_True;
766 // -----------------------------------------------------------------------
767 sal_Bool SfxDocTplService_Impl::addEntry( Content& rParentFolder,
768 const OUString& rTitle,
769 const OUString& rTargetURL,
770 const OUString& rType )
772 sal_Bool bAddedEntry = sal_False;
774 INetURLObject aLinkObj( rParentFolder.getURL() );
775 aLinkObj.insertName( rTitle, false,
776 INetURLObject::LAST_SEGMENT, true,
777 INetURLObject::ENCODE_ALL );
778 OUString aLinkURL = aLinkObj.GetMainURL( INetURLObject::NO_DECODE );
780 Content aLink;
782 if ( ! Content::create( aLinkURL, maCmdEnv, aLink ) )
784 Sequence< OUString > aNames(3);
785 aNames[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( TITLE ) );
786 aNames[1] = OUString( RTL_CONSTASCII_USTRINGPARAM( IS_FOLDER ) );
787 aNames[2] = OUString( RTL_CONSTASCII_USTRINGPARAM( TARGET_URL ) );
789 Sequence< Any > aValues(3);
790 aValues[0] = makeAny( rTitle );
791 aValues[1] = makeAny( sal_Bool( sal_False ) );
792 aValues[2] = makeAny( rTargetURL );
794 OUString aType( RTL_CONSTASCII_USTRINGPARAM( TYPE_LINK ) );
795 OUString aAdditionalProp( RTL_CONSTASCII_USTRINGPARAM( PROPERTY_TYPE ) );
799 rParentFolder.insertNewContent( aType, aNames, aValues, aLink );
800 setProperty( aLink, aAdditionalProp, makeAny( rType ) );
801 bAddedEntry = sal_True;
803 catch( Exception& )
806 return bAddedEntry;
809 // -----------------------------------------------------------------------
810 sal_Bool SfxDocTplService_Impl::createFolder( const OUString& rNewFolderURL,
811 sal_Bool bCreateParent,
812 sal_Bool bFsysFolder,
813 Content &rNewFolder )
815 Content aParent;
816 sal_Bool bCreatedFolder = sal_False;
817 INetURLObject aParentURL( rNewFolderURL );
818 OUString aFolderName = aParentURL.getName( INetURLObject::LAST_SEGMENT, true,
819 INetURLObject::DECODE_WITH_CHARSET );
821 // compute the parent folder url from the new folder url
822 // and remove the final slash, because Content::create doesn't
823 // like it
824 aParentURL.removeSegment();
825 if ( aParentURL.getSegmentCount() >= 1 )
826 aParentURL.removeFinalSlash();
828 // if the parent exists, we can continue with the creation of the
829 // new folder, we have to create the parent otherwise ( as long as
830 // bCreateParent is set to true )
831 if ( Content::create( aParentURL.GetMainURL( INetURLObject::NO_DECODE ), maCmdEnv, aParent ) )
835 Sequence< OUString > aNames(2);
836 aNames[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( TITLE ) );
837 aNames[1] = OUString( RTL_CONSTASCII_USTRINGPARAM( IS_FOLDER ) );
839 Sequence< Any > aValues(2);
840 aValues[0] = makeAny( aFolderName );
841 aValues[1] = makeAny( sal_Bool( sal_True ) );
843 OUString aType;
845 if ( bFsysFolder )
846 aType = OUString( RTL_CONSTASCII_USTRINGPARAM( TYPE_FSYS_FOLDER ) );
847 else
848 aType = OUString( RTL_CONSTASCII_USTRINGPARAM( TYPE_FOLDER ) );
850 aParent.insertNewContent( aType, aNames, aValues, rNewFolder );
851 bCreatedFolder = sal_True;
853 catch( RuntimeException& )
855 DBG_ERRORFILE( "createFolder(): got runtime exception" );
857 catch( Exception& )
859 DBG_ERRORFILE( "createFolder(): Could not create new folder" );
862 else if ( bCreateParent )
864 // if the parent doesn't exists and bCreateParent is set to true,
865 // we try to create the parent and if this was successful, we
866 // try to create the new folder again ( but this time, we set
867 // bCreateParent to false to avoid endless recusions )
868 if ( ( aParentURL.getSegmentCount() >= 1 ) &&
869 createFolder( aParentURL.GetMainURL( INetURLObject::NO_DECODE ), bCreateParent, bFsysFolder, aParent ) )
871 bCreatedFolder = createFolder( rNewFolderURL, sal_False, bFsysFolder, rNewFolder );
875 return bCreatedFolder;
878 // -----------------------------------------------------------------------
879 sal_Bool SfxDocTplService_Impl::CreateNewUniqueFolderWithPrefix( const ::rtl::OUString& aPath,
880 const ::rtl::OUString& aPrefix,
881 ::rtl::OUString& aNewFolderName,
882 ::rtl::OUString& aNewFolderURL,
883 Content& aNewFolder )
885 sal_Bool bCreated = sal_False;
886 INetURLObject aDirPath( aPath );
888 Content aParent;
889 if ( Content::create( aDirPath.GetMainURL( INetURLObject::NO_DECODE ), maCmdEnv, aParent ) )
891 for ( sal_Int32 nInd = 0; nInd < 32000; nInd++ )
893 ::rtl::OUString aTryName = aPrefix;
894 if ( nInd )
895 aTryName += ::rtl::OUString::valueOf( nInd );
899 Sequence< OUString > aNames(2);
900 aNames[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( TITLE ) );
901 aNames[1] = OUString( RTL_CONSTASCII_USTRINGPARAM( IS_FOLDER ) );
903 Sequence< Any > aValues(2);
904 aValues[0] = makeAny( aTryName );
905 aValues[1] = makeAny( sal_Bool( sal_True ) );
907 OUString aType( RTL_CONSTASCII_USTRINGPARAM( TYPE_FSYS_FOLDER ) );
909 bCreated = aParent.insertNewContent( aType, aNames, aValues, aNewFolder );
911 catch( ucb::NameClashException& )
913 // if there is already an element, retry
915 catch( Exception& )
917 INetURLObject aObjPath( aDirPath );
918 aObjPath.insertName( aTryName, false,
919 INetURLObject::LAST_SEGMENT, true,
920 INetURLObject::ENCODE_ALL );
921 // if there is already an element, retry
922 // if there was another error, do not try any more
923 if ( !::utl::UCBContentHelper::Exists( aObjPath.GetMainURL( INetURLObject::NO_DECODE ) ) )
924 break;
927 if ( bCreated )
929 aNewFolderName = aTryName;
930 aNewFolderURL = aNewFolder.get()->getIdentifier()->getContentIdentifier();
931 break;
936 return bCreated;
939 // -----------------------------------------------------------------------
940 ::rtl::OUString SfxDocTplService_Impl::CreateNewUniqueFileWithPrefix( const ::rtl::OUString& aPath,
941 const ::rtl::OUString& aPrefix,
942 const ::rtl::OUString& aExt )
944 ::rtl::OUString aNewFileURL;
945 INetURLObject aDirPath( aPath );
947 Content aParent;
949 uno::Reference< XCommandEnvironment > aQuietEnv;
950 if ( Content::create( aDirPath.GetMainURL( INetURLObject::NO_DECODE ), aQuietEnv, aParent ) )
952 for ( sal_Int32 nInd = 0; nInd < 32000; nInd++ )
954 Content aNewFile;
955 sal_Bool bCreated = sal_False;
956 ::rtl::OUString aTryName = aPrefix;
957 if ( nInd )
958 aTryName += ::rtl::OUString::valueOf( nInd );
959 if ( aExt.toChar() != '.' )
960 aTryName += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "." ) );
961 aTryName += aExt;
965 Sequence< OUString > aNames(2);
966 aNames[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( TITLE ) );
967 aNames[1] = OUString( RTL_CONSTASCII_USTRINGPARAM( IS_DOCUMENT ) );
969 Sequence< Any > aValues(2);
970 aValues[0] = makeAny( aTryName );
971 aValues[1] = makeAny( sal_Bool( sal_True ) );
973 OUString aType( RTL_CONSTASCII_USTRINGPARAM( TYPE_FSYS_FILE ) );
975 bCreated = aParent.insertNewContent( aType, aNames, aValues, aNewFile );
977 catch( ucb::NameClashException& )
979 // if there is already an element, retry
981 catch( Exception& )
983 INetURLObject aObjPath( aPath );
984 aObjPath.insertName( aTryName, false,
985 INetURLObject::LAST_SEGMENT, true,
986 INetURLObject::ENCODE_ALL );
987 // if there is already an element, retry
988 // if there was another error, do not try any more
989 if ( !::utl::UCBContentHelper::Exists( aObjPath.GetMainURL( INetURLObject::NO_DECODE ) ) )
990 break;
993 if ( bCreated )
995 aNewFileURL = aNewFile.get()->getIdentifier()->getContentIdentifier();
996 break;
1001 return aNewFileURL;
1004 // -----------------------------------------------------------------------
1005 sal_Bool SfxDocTplService_Impl::removeContent( Content& rContent )
1007 sal_Bool bRemoved = sal_False;
1010 OUString aCmd( RTL_CONSTASCII_USTRINGPARAM( COMMAND_DELETE ) );
1011 Any aArg = makeAny( sal_Bool( sal_True ) );
1013 rContent.executeCommand( aCmd, aArg );
1014 bRemoved = sal_True;
1016 catch ( RuntimeException& ) {}
1017 catch ( Exception& ) {}
1019 return bRemoved;
1022 // -----------------------------------------------------------------------
1023 sal_Bool SfxDocTplService_Impl::removeContent( const OUString& rContentURL )
1025 Content aContent;
1027 if ( Content::create( rContentURL, maCmdEnv, aContent ) )
1028 return removeContent( aContent );
1029 else
1030 return sal_False;
1033 // -----------------------------------------------------------------------
1034 sal_Bool SfxDocTplService_Impl::setProperty( Content& rContent,
1035 const OUString& rPropName,
1036 const Any& rPropValue )
1038 sal_Bool bPropertySet = sal_False;
1040 // Store the property
1043 Any aPropValue( rPropValue );
1044 uno::Reference< XPropertySetInfo > aPropInfo = rContent.getProperties();
1046 // check, wether or not the property exists, create it, when not
1047 if ( !aPropInfo.is() || !aPropInfo->hasPropertyByName( rPropName ) )
1049 uno::Reference< XPropertyContainer > xProperties( rContent.get(), UNO_QUERY );
1050 if ( xProperties.is() )
1054 xProperties->addProperty( rPropName, PropertyAttribute::MAYBEVOID, rPropValue );
1056 catch( PropertyExistException& ) {}
1057 catch( IllegalTypeException& ) { DBG_ERRORFILE( "IllegalTypeException" ); }
1058 catch( IllegalArgumentException& ) { DBG_ERRORFILE( "IllegalArgumentException" ); }
1062 // To ensure a reloctable office installation, the path to the
1063 // office installtion directory must never be stored directly.
1064 if ( SfxURLRelocator_Impl::propertyCanContainOfficeDir( rPropName ) )
1066 OUString aValue;
1067 if ( rPropValue >>= aValue )
1069 maRelocator.makeRelocatableURL( aValue );
1070 aPropValue = makeAny( aValue );
1072 else
1074 Sequence< OUString > aValues;
1075 if ( rPropValue >>= aValues )
1077 for ( sal_Int32 n = 0; n < aValues.getLength(); n++ )
1079 maRelocator.makeRelocatableURL( aValues[ n ] );
1081 aPropValue = makeAny( aValues );
1083 else
1085 OSL_ENSURE( false, "Unsupported property value type" );
1090 // now set the property
1092 rContent.setPropertyValue( rPropName, aPropValue );
1093 bPropertySet = sal_True;
1095 catch ( RuntimeException& ) {}
1096 catch ( Exception& ) {}
1098 return bPropertySet;
1101 // -----------------------------------------------------------------------
1102 sal_Bool SfxDocTplService_Impl::getProperty( Content& rContent,
1103 const OUString& rPropName,
1104 Any& rPropValue )
1106 sal_Bool bGotProperty = sal_False;
1108 // Get the property
1111 uno::Reference< XPropertySetInfo > aPropInfo = rContent.getProperties();
1113 // check, wether or not the property exists
1114 if ( !aPropInfo.is() || !aPropInfo->hasPropertyByName( rPropName ) )
1116 return sal_False;
1119 // now get the property
1121 rPropValue = rContent.getPropertyValue( rPropName );
1123 // To ensure a reloctable office installation, the path to the
1124 // office installtion directory must never be stored directly.
1125 if ( SfxURLRelocator_Impl::propertyCanContainOfficeDir( rPropName ) )
1127 OUString aValue;
1128 if ( rPropValue >>= aValue )
1130 maRelocator.makeAbsoluteURL( aValue );
1131 rPropValue = makeAny( aValue );
1133 else
1135 Sequence< OUString > aValues;
1136 if ( rPropValue >>= aValues )
1138 for ( sal_Int32 n = 0; n < aValues.getLength(); n++ )
1140 maRelocator.makeAbsoluteURL( aValues[ n ] );
1142 rPropValue = makeAny( aValues );
1144 else
1146 OSL_ENSURE( false, "Unsupported property value type" );
1151 bGotProperty = sal_True;
1153 catch ( RuntimeException& ) {}
1154 catch ( Exception& ) {}
1156 return bGotProperty;
1159 // -----------------------------------------------------------------------
1160 // static
1161 bool SfxURLRelocator_Impl::propertyCanContainOfficeDir(
1162 const rtl::OUString & rPropName )
1164 // Note: TargetURL is handled by UCB itself (because it is a property
1165 // with a predefined semantic). Additional Core properties introduced
1166 // be a client app must be handled by the client app itself, because
1167 // the UCB does not know the semantics of those properties.
1168 return ( rPropName.equalsAsciiL(
1169 RTL_CONSTASCII_STRINGPARAM( TARGET_DIR_URL ) ) ||
1170 rPropName.equalsAsciiL(
1171 RTL_CONSTASCII_STRINGPARAM( PROPERTY_DIRLIST ) ) );
1174 //-----------------------------------------------------------------------------
1175 // public SfxDocTplService_Impl
1176 //-----------------------------------------------------------------------------
1178 SfxDocTplService_Impl::SfxDocTplService_Impl( uno::Reference< XMultiServiceFactory > xFactory )
1179 : maRelocator( xFactory )
1181 mxFactory = xFactory;
1182 mpUpdater = NULL;
1183 mbIsInitialized = sal_False;
1184 mbLocaleSet = sal_False;
1187 //-----------------------------------------------------------------------------
1188 SfxDocTplService_Impl::~SfxDocTplService_Impl()
1190 ::osl::MutexGuard aGuard( maMutex );
1192 if ( mpUpdater )
1194 mpUpdater->kill();
1195 delete mpUpdater;
1199 //-----------------------------------------------------------------------------
1200 Locale SfxDocTplService_Impl::getLocale()
1202 ::osl::MutexGuard aGuard( maMutex );
1204 if ( !mbLocaleSet )
1205 getDefaultLocale();
1207 return maLocale;
1210 //-----------------------------------------------------------------------------
1211 void SfxDocTplService_Impl::setLocale( const Locale &rLocale )
1213 ::osl::MutexGuard aGuard( maMutex );
1215 if ( mbLocaleSet &&
1216 ( maLocale.Language != rLocale.Language ) &&
1217 ( maLocale.Country != rLocale.Country ) )
1218 mbIsInitialized = sal_False;
1220 maLocale = rLocale;
1221 mbLocaleSet = sal_True;
1224 //-----------------------------------------------------------------------------
1225 void SfxDocTplService_Impl::update( sal_Bool bUpdateNow )
1227 ::osl::MutexGuard aGuard( maMutex );
1229 if ( bUpdateNow )
1230 doUpdate();
1231 else
1233 mpUpdater = new Updater_Impl( this );
1234 mpUpdater->create();
1238 //-----------------------------------------------------------------------------
1239 void SfxDocTplService_Impl::doUpdate()
1241 ::osl::MutexGuard aGuard( maMutex );
1243 OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( PROPERTY_NEEDSUPDATE ) );
1244 Any aValue;
1246 aValue <<= sal_True;
1247 setProperty( maRootContent, aPropName, aValue );
1249 GroupList_Impl aGroupList;
1251 // get the entries from the hierarchy
1252 createFromContent( aGroupList, maRootContent, sal_True );
1254 // get the entries from the template directories
1255 sal_Int32 nCountDir = maTemplateDirs.getLength();
1256 OUString* pDirs = maTemplateDirs.getArray();
1257 Content aDirContent;
1259 // the last directory in the list must be writable
1260 sal_Bool bWriteableDirectory = sal_True;
1262 // the target folder might not exist, for this reason no interaction handler should be used
1263 uno::Reference< XCommandEnvironment > aQuietEnv;
1265 while ( nCountDir )
1267 nCountDir--;
1268 osl::Directory aDirectory (pDirs[ nCountDir ]);
1269 osl::FileBase::RC nError = aDirectory.open();
1270 if (nError == osl::FileBase::E_None || bWriteableDirectory)
1272 if ( Content::create( pDirs[ nCountDir ], aQuietEnv, aDirContent ) )
1274 createFromContent( aGroupList, aDirContent, sal_False, bWriteableDirectory );
1276 aDirectory.close();
1278 bWriteableDirectory = sal_False;
1281 // now check the list
1282 GroupData_Impl *pGroup = aGroupList.First();
1283 while ( pGroup )
1285 if ( pGroup->getInUse() )
1287 if ( pGroup->getInHierarchy() )
1289 Content aGroup;
1290 if ( Content::create( pGroup->getHierarchyURL(), maCmdEnv, aGroup ) )
1291 setProperty( aGroup,
1292 OUString( RTL_CONSTASCII_USTRINGPARAM( TARGET_DIR_URL ) ),
1293 makeAny( pGroup->getTargetURL() ) );
1295 ULONG nCount = pGroup->count();
1296 for ( ULONG i=0; i<nCount; i++ )
1298 DocTemplates_EntryData_Impl *pData = pGroup->getEntry( i );
1299 if ( ! pData->getInUse() )
1301 if ( pData->getInHierarchy() )
1302 removeFromHierarchy( pData ); // delete entry in hierarchy
1303 else
1304 addToHierarchy( pGroup, pData ); // add entry to hierarchy
1306 else if ( pData->getUpdateType() ||
1307 pData->getUpdateLink() )
1309 updateData( pData );
1313 else
1315 addGroupToHierarchy( pGroup ); // add group to hierarchy
1318 else
1319 removeFromHierarchy( pGroup ); // delete group from hierarchy
1321 delete pGroup;
1322 pGroup = aGroupList.Next();
1325 aValue <<= sal_False;
1326 setProperty( maRootContent, aPropName, aValue );
1329 //-----------------------------------------------------------------------------
1330 uno::Sequence< beans::StringPair > SfxDocTplService_Impl::ReadUINamesForTemplateDir_Impl( const ::rtl::OUString& aUserPath )
1332 INetURLObject aLocObj( aUserPath );
1333 aLocObj.insertName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "groupuinames.xml" ) ), false,
1334 INetURLObject::LAST_SEGMENT, true,
1335 INetURLObject::ENCODE_ALL );
1336 Content aLocContent;
1338 // TODO/LATER: Use hashmap in future
1339 uno::Sequence< beans::StringPair > aUINames;
1340 if ( Content::create( aLocObj.GetMainURL( INetURLObject::NO_DECODE ), uno::Reference < ucb::XCommandEnvironment >(), aLocContent ) )
1344 uno::Reference< io::XInputStream > xLocStream = aLocContent.openStream();
1345 if ( xLocStream.is() )
1346 aUINames = DocTemplLocaleHelper::ReadGroupLocalizationSequence( xLocStream, mxFactory );
1348 catch( uno::Exception& )
1352 return aUINames;
1355 //-----------------------------------------------------------------------------
1356 sal_Bool SfxDocTplService_Impl::UpdateUINamesForTemplateDir_Impl( const ::rtl::OUString& aUserPath,
1357 const ::rtl::OUString& aGroupName,
1358 const ::rtl::OUString& aNewFolderName )
1360 uno::Sequence< beans::StringPair > aUINames = ReadUINamesForTemplateDir_Impl( aUserPath );
1361 sal_Int32 nLen = aUINames.getLength();
1363 // it is possible that the name is used already, but it should be checked before
1364 for ( sal_Int32 nInd = 0; nInd < nLen; nInd++ )
1365 if ( aUINames[nInd].First.equals( aNewFolderName ) )
1366 return sal_False;
1368 aUINames.realloc( ++nLen );
1369 aUINames[nLen-1].First = aNewFolderName;
1370 aUINames[nLen-1].Second = aGroupName;
1372 return WriteUINamesForTemplateDir_Impl( aUserPath, aUINames );
1375 //-----------------------------------------------------------------------------
1376 sal_Bool SfxDocTplService_Impl::ReplaceUINamesForTemplateDir_Impl( const ::rtl::OUString& aUserPath,
1377 const ::rtl::OUString& aDefaultFsysGroupName,
1378 const ::rtl::OUString& aOldGroupName,
1379 const ::rtl::OUString& aNewGroupName )
1381 uno::Sequence< beans::StringPair > aUINames = ReadUINamesForTemplateDir_Impl( aUserPath );
1382 sal_Int32 nLen = aUINames.getLength();
1384 sal_Bool bChanged = sal_False;
1385 for ( sal_Int32 nInd = 0; nInd < nLen; nInd++ )
1386 if ( aUINames[nInd].Second.equals( aOldGroupName ) )
1388 aUINames[nInd].Second = aNewGroupName;
1389 bChanged = sal_True;
1392 if ( !bChanged )
1394 aUINames.realloc( ++nLen );
1395 aUINames[nLen-1].First = aDefaultFsysGroupName;
1396 aUINames[nLen-1].Second = aNewGroupName;
1398 return WriteUINamesForTemplateDir_Impl( aUserPath, aUINames );
1401 //-----------------------------------------------------------------------------
1402 sal_Bool SfxDocTplService_Impl::RemoveUINamesForTemplateDir_Impl( const ::rtl::OUString& aUserPath,
1403 const ::rtl::OUString& aGroupName )
1405 uno::Sequence< beans::StringPair > aUINames = ReadUINamesForTemplateDir_Impl( aUserPath );
1406 sal_Int32 nLen = aUINames.getLength();
1407 uno::Sequence< beans::StringPair > aNewUINames( nLen );
1408 sal_Int32 nNewLen = 0;
1410 sal_Bool bChanged = sal_False;
1411 for ( sal_Int32 nInd = 0; nInd < nLen; nInd++ )
1412 if ( aUINames[nInd].Second.equals( aGroupName ) )
1413 bChanged = sal_True;
1414 else
1416 nNewLen++;
1417 aNewUINames[nNewLen-1].First = aUINames[nInd].First;
1418 aNewUINames[nNewLen-1].Second = aUINames[nInd].Second;
1421 aNewUINames.realloc( nNewLen );
1423 return bChanged ? WriteUINamesForTemplateDir_Impl( aUserPath, aNewUINames ) : sal_True;
1427 //-----------------------------------------------------------------------------
1428 sal_Bool SfxDocTplService_Impl::WriteUINamesForTemplateDir_Impl( const ::rtl::OUString& aUserPath,
1429 const uno::Sequence< beans::StringPair >& aUINames )
1431 sal_Bool bResult = sal_False;
1432 try {
1433 uno::Reference< beans::XPropertySet > xTempFile(
1434 mxFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ),
1435 uno::UNO_QUERY_THROW );
1437 ::rtl::OUString aTempURL;
1438 uno::Any aUrl = xTempFile->getPropertyValue( ::rtl::OUString::createFromAscii( "Uri" ) );
1439 aUrl >>= aTempURL;
1441 uno::Reference< io::XStream > xStream( xTempFile, uno::UNO_QUERY_THROW );
1442 uno::Reference< io::XOutputStream > xOutStream = xStream->getOutputStream();
1443 if ( !xOutStream.is() )
1444 throw uno::RuntimeException();
1446 DocTemplLocaleHelper::WriteGroupLocalizationSequence( xOutStream, aUINames, mxFactory );
1447 try {
1448 // the SAX writer might close the stream
1449 xOutStream->closeOutput();
1450 } catch( uno::Exception& )
1453 Content aTargetContent( aUserPath, maCmdEnv );
1454 Content aSourceContent( aTempURL, maCmdEnv );
1455 aTargetContent.transferContent( aSourceContent,
1456 InsertOperation_COPY,
1457 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "groupuinames.xml" ) ),
1458 ucb::NameClash::OVERWRITE );
1459 bResult = sal_True;
1461 catch ( uno::Exception& )
1465 return bResult;
1468 //-----------------------------------------------------------------------------
1469 ::rtl::OUString SfxDocTplService_Impl::CreateNewGroupFsys( const ::rtl::OUString& rGroupName, Content& aGroup )
1471 ::rtl::OUString aResultURL;
1473 if ( maTemplateDirs.getLength() )
1475 ::rtl::OUString aTargetPath = maTemplateDirs[ maTemplateDirs.getLength() - 1 ];
1477 // create a new folder with the given name
1478 Content aNewFolder;
1479 ::rtl::OUString aNewFolderName;
1481 // the Fsys name instead of GroupName should be used, the groupuinames must be added also
1482 if ( !CreateNewUniqueFolderWithPrefix( aTargetPath,
1483 rGroupName,
1484 aNewFolderName,
1485 aResultURL,
1486 aNewFolder )
1487 && !CreateNewUniqueFolderWithPrefix( aTargetPath,
1488 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UserGroup" ) ),
1489 aNewFolderName,
1490 aResultURL,
1491 aNewFolder ) )
1493 return ::rtl::OUString();
1495 if ( !UpdateUINamesForTemplateDir_Impl( aTargetPath, rGroupName, aNewFolderName ) )
1497 // we could not create the groupuinames for the folder, so we delete the group in the
1498 // the folder and return
1499 removeContent( aNewFolder );
1500 return ::rtl::OUString();
1503 // Now set the target url for this group and we are done
1504 OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( TARGET_DIR_URL ) );
1505 Any aValue = makeAny( aResultURL );
1507 if ( ! setProperty( aGroup, aPropName, aValue ) )
1509 removeContent( aNewFolder );
1510 return ::rtl::OUString();
1514 return aResultURL;
1517 //-----------------------------------------------------------------------------
1518 sal_Bool SfxDocTplService_Impl::addGroup( const OUString& rGroupName )
1520 ::osl::MutexGuard aGuard( maMutex );
1522 // Check, wether or not there is a group with this name
1523 Content aNewGroup;
1524 OUString aNewGroupURL;
1525 INetURLObject aNewGroupObj( maRootURL );
1527 aNewGroupObj.insertName( rGroupName, false,
1528 INetURLObject::LAST_SEGMENT, true,
1529 INetURLObject::ENCODE_ALL );
1531 aNewGroupURL = aNewGroupObj.GetMainURL( INetURLObject::NO_DECODE );
1533 if ( Content::create( aNewGroupURL, maCmdEnv, aNewGroup ) ||
1534 ! createFolder( aNewGroupURL, sal_False, sal_False, aNewGroup ) )
1536 // if there already was a group with this name or the new group
1537 // could not be created, we return here
1538 return sal_False;
1541 // Get the user template path entry ( new group will always
1542 // be added in the user template path )
1543 sal_Int32 nIndex;
1544 OUString aUserPath;
1546 nIndex = maTemplateDirs.getLength();
1547 if ( nIndex )
1548 nIndex--;
1549 else
1550 return sal_False; // We don't know where to add the group
1552 aUserPath = maTemplateDirs[ nIndex ];
1554 // create a new folder with the given name
1555 Content aNewFolder;
1556 OUString aNewFolderName;
1557 OUString aNewFolderURL;
1559 // the Fsys name instead of GroupName should be used, the groupuinames must be added also
1560 if ( !CreateNewUniqueFolderWithPrefix( aUserPath,
1561 rGroupName,
1562 aNewFolderName,
1563 aNewFolderURL,
1564 aNewFolder )
1565 && !CreateNewUniqueFolderWithPrefix( aUserPath,
1566 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UserGroup" ) ),
1567 aNewFolderName,
1568 aNewFolderURL,
1569 aNewFolder ) )
1571 // we could not create the folder, so we delete the group in the
1572 // hierarchy and return
1573 removeContent( aNewGroup );
1574 return sal_False;
1577 if ( !UpdateUINamesForTemplateDir_Impl( aUserPath, rGroupName, aNewFolderName ) )
1579 // we could not create the groupuinames for the folder, so we delete the group in the
1580 // hierarchy, the folder and return
1581 removeContent( aNewGroup );
1582 removeContent( aNewFolder );
1583 return sal_False;
1586 // Now set the target url for this group and we are done
1587 OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( TARGET_DIR_URL ) );
1588 Any aValue = makeAny( aNewFolderURL );
1590 if ( ! setProperty( aNewGroup, aPropName, aValue ) )
1592 removeContent( aNewGroup );
1593 removeContent( aNewFolder );
1594 return sal_False;
1597 return sal_True;
1600 //-----------------------------------------------------------------------------
1601 sal_Bool SfxDocTplService_Impl::removeGroup( const OUString& rGroupName )
1603 // remove all the elements that have the prefix aTargetURL
1604 // if the group does not have other elements remove it
1606 ::osl::MutexGuard aGuard( maMutex );
1608 sal_Bool bResult = sal_False;
1610 // create the group url
1611 INetURLObject aGroupObj( maRootURL );
1612 aGroupObj.insertName( rGroupName, false,
1613 INetURLObject::LAST_SEGMENT, true,
1614 INetURLObject::ENCODE_ALL );
1616 // Get the target url
1617 Content aGroup;
1618 OUString aGroupURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE );
1620 if ( Content::create( aGroupURL, maCmdEnv, aGroup ) )
1622 OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( TARGET_DIR_URL ) );
1623 Any aValue;
1625 OUString aGroupTargetURL;
1626 if ( getProperty( aGroup, aPropName, aValue ) )
1627 aValue >>= aGroupTargetURL;
1629 if ( !aGroupTargetURL.getLength() )
1630 return sal_False; // nothing is allowed to be removed
1632 if ( !maTemplateDirs.getLength() )
1633 return sal_False;
1634 ::rtl::OUString aGeneralTempPath = maTemplateDirs[ maTemplateDirs.getLength() - 1 ];
1636 // check that the fs location is in writeble folder and this is not a "My templates" folder
1637 INetURLObject aGroupParentFolder( aGroupTargetURL );
1638 if ( !aGroupParentFolder.removeSegment()
1639 || !::utl::UCBContentHelper::IsSubPath( aGeneralTempPath,
1640 aGroupParentFolder.GetMainURL( INetURLObject::NO_DECODE ) ) )
1641 return sal_False;
1643 // now get the content of the Group
1644 uno::Reference< XResultSet > xResultSet;
1645 Sequence< OUString > aProps( 1 );
1647 aProps[0] = OUString::createFromAscii( TARGET_URL );
1651 sal_Bool bHasNonRemovable = sal_False;
1652 sal_Bool bHasShared = sal_False;
1654 ResultSetInclude eInclude = INCLUDE_DOCUMENTS_ONLY;
1655 xResultSet = aGroup.createCursor( aProps, eInclude );
1657 if ( xResultSet.is() )
1659 uno::Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY_THROW );
1660 uno::Reference< XRow > xRow( xResultSet, UNO_QUERY_THROW );
1662 while ( xResultSet->next() )
1664 OUString aTemplTargetURL( xRow->getString( 1 ) );
1665 OUString aHierURL = xContentAccess->queryContentIdentifierString();
1667 if ( ::utl::UCBContentHelper::IsSubPath( aGroupTargetURL, aTemplTargetURL ) )
1669 // this is a user template, and it can be removed
1670 if ( removeContent( aTemplTargetURL ) )
1671 removeContent( aHierURL );
1672 else
1673 bHasNonRemovable = sal_True;
1675 else
1676 bHasShared = sal_True;
1679 if ( !bHasNonRemovable && !bHasShared )
1681 if ( removeContent( aGroupTargetURL )
1682 || !::utl::UCBContentHelper::Exists( aGroupTargetURL ) )
1684 removeContent( aGroupURL );
1685 RemoveUINamesForTemplateDir_Impl( aGeneralTempPath, rGroupName );
1686 bResult = sal_True; // the operation is successful only if the whole group is removed
1689 else if ( !bHasNonRemovable )
1691 if ( removeContent( aGroupTargetURL )
1692 || !::utl::UCBContentHelper::Exists( aGroupTargetURL ) )
1694 RemoveUINamesForTemplateDir_Impl( aGeneralTempPath, rGroupName );
1695 setProperty( aGroup, aPropName, uno::makeAny( ::rtl::OUString() ) );
1700 catch ( Exception& ) {}
1703 return bResult;
1706 //-----------------------------------------------------------------------------
1707 sal_Bool SfxDocTplService_Impl::renameGroup( const OUString& rOldName,
1708 const OUString& rNewName )
1710 ::osl::MutexGuard aGuard( maMutex );
1712 // create the group url
1713 Content aGroup;
1714 INetURLObject aGroupObj( maRootURL );
1715 aGroupObj.insertName( rNewName, false,
1716 INetURLObject::LAST_SEGMENT, true,
1717 INetURLObject::ENCODE_ALL );
1718 OUString aGroupURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE );
1720 // Check, if there is a group with the new name, return false
1721 // if there is one.
1722 if ( Content::create( aGroupURL, maCmdEnv, aGroup ) )
1723 return sal_False;
1725 aGroupObj.removeSegment();
1726 aGroupObj.insertName( rOldName, false,
1727 INetURLObject::LAST_SEGMENT, true,
1728 INetURLObject::ENCODE_ALL );
1729 aGroupURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE );
1731 // When there is no group with the old name, we can't rename it
1732 if ( ! Content::create( aGroupURL, maCmdEnv, aGroup ) )
1733 return sal_False;
1735 OUString aGroupTargetURL;
1736 // there is no need to check whether target dir url is in target path, since if the target path is changed
1737 // the target dir url should be already generated new
1738 OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( TARGET_DIR_URL ) );
1739 Any aValue;
1740 if ( getProperty( aGroup, aPropName, aValue ) )
1741 aValue >>= aGroupTargetURL;
1743 if ( !aGroupTargetURL.getLength() )
1744 return sal_False;
1746 if ( !maTemplateDirs.getLength() )
1747 return sal_False;
1748 ::rtl::OUString aGeneralTempPath = maTemplateDirs[ maTemplateDirs.getLength() - 1 ];
1750 // check that the fs location is in writeble folder and this is not a "My templates" folder
1751 INetURLObject aGroupParentFolder( aGroupTargetURL );
1752 if ( !aGroupParentFolder.removeSegment()
1753 || !::utl::UCBContentHelper::IsSubPath( aGeneralTempPath,
1754 aGroupParentFolder.GetMainURL( INetURLObject::NO_DECODE ) ) )
1755 return sal_False;
1757 // check that the group can be renamed ( all the contents must be in target location )
1758 sal_Bool bCanBeRenamed = sal_False;
1761 uno::Reference< XResultSet > xResultSet;
1762 Sequence< OUString > aProps( 1 );
1764 aProps[0] = OUString::createFromAscii( TARGET_URL );
1765 ResultSetInclude eInclude = INCLUDE_DOCUMENTS_ONLY;
1766 xResultSet = aGroup.createCursor( aProps, eInclude );
1768 if ( xResultSet.is() )
1770 uno::Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY_THROW );
1771 uno::Reference< XRow > xRow( xResultSet, UNO_QUERY_THROW );
1773 while ( xResultSet->next() )
1775 OUString aTemplTargetURL( xRow->getString( 1 ) );
1777 if ( !::utl::UCBContentHelper::IsSubPath( aGroupTargetURL, aTemplTargetURL ) )
1778 throw uno::Exception();
1781 bCanBeRenamed = sal_True;
1784 catch ( Exception& ) {}
1786 if ( bCanBeRenamed )
1788 INetURLObject aGroupTargetObj( aGroupTargetURL );
1789 ::rtl::OUString aFsysName = aGroupTargetObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
1791 if ( aGroupTargetObj.removeSegment()
1792 && ReplaceUINamesForTemplateDir_Impl( aGroupTargetObj.GetMainURL( INetURLObject::NO_DECODE ),
1793 aFsysName,
1794 rOldName,
1795 rNewName ) )
1797 // rename the group in the hierarchy
1798 OUString aTitleProp( RTL_CONSTASCII_USTRINGPARAM( TITLE ) );
1799 Any aTitleValue;
1800 aTitleValue <<= rNewName;
1802 return setProperty( aGroup, aTitleProp, aTitleValue );
1806 return sal_False;
1809 //-----------------------------------------------------------------------------
1810 sal_Bool SfxDocTplService_Impl::storeTemplate( const OUString& rGroupName,
1811 const OUString& rTemplateName,
1812 const uno::Reference< XSTORABLE >& rStorable )
1814 ::osl::MutexGuard aGuard( maMutex );
1816 // Check, wether or not there is a group with this name
1817 // Return false, if there is no group with the given name
1818 Content aGroup, aTemplate, aTargetGroup, aTemplateToRemove;
1819 OUString aGroupURL, aTemplateURL, aTemplateToRemoveTargetURL;
1820 INetURLObject aGroupObj( maRootURL );
1821 sal_Bool bRemoveOldTemplateContent = sal_False;
1822 ::rtl::OUString sDocServiceName;
1824 aGroupObj.insertName( rGroupName, false,
1825 INetURLObject::LAST_SEGMENT, true,
1826 INetURLObject::ENCODE_ALL );
1827 aGroupURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE );
1829 if ( ! Content::create( aGroupURL, maCmdEnv, aGroup ) )
1830 return sal_False;
1832 ::rtl::OUString aGroupTargetURL;
1833 ::rtl::OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( TARGET_DIR_URL ) );
1834 Any aValue;
1835 if ( getProperty( aGroup, aPropName, aValue ) )
1836 aValue >>= aGroupTargetURL;
1839 // Check, if there's a template with the given name in this group
1840 // the target template should be overwritten if it is imported by user
1841 // in case the template is installed by office installation of by an add-in
1842 // it can not be replaced
1843 aGroupObj.insertName( rTemplateName, false,
1844 INetURLObject::LAST_SEGMENT, true,
1845 INetURLObject::ENCODE_ALL );
1846 aTemplateURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE );
1848 if ( Content::create( aTemplateURL, maCmdEnv, aTemplateToRemove ) )
1850 OUString aTargetTemplPropName( RTL_CONSTASCII_USTRINGPARAM( TARGET_URL ) );
1852 bRemoveOldTemplateContent = sal_True;
1853 if ( getProperty( aTemplateToRemove, aTargetTemplPropName, aValue ) )
1854 aValue >>= aTemplateToRemoveTargetURL;
1856 if ( !aGroupTargetURL.getLength() || !maTemplateDirs.getLength()
1857 || (aTemplateToRemoveTargetURL.getLength() && !::utl::UCBContentHelper::IsSubPath( maTemplateDirs[ maTemplateDirs.getLength() - 1 ], aTemplateToRemoveTargetURL )) )
1858 return sal_False; // it is not allowed to remove the template
1863 uno::Reference< lang::XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory();
1864 if ( !xFactory.is() )
1865 throw uno::RuntimeException();
1867 // get document service name
1868 uno::Reference< frame::XModuleManager > xModuleManager(
1869 xFactory->createInstance(
1870 ::rtl::OUString::createFromAscii( "com.sun.star.frame.ModuleManager" ) ),
1871 uno::UNO_QUERY_THROW );
1872 sDocServiceName = xModuleManager->identify( uno::Reference< uno::XInterface >( rStorable, uno::UNO_QUERY ) );
1873 if ( !sDocServiceName.getLength() )
1874 throw uno::RuntimeException();
1876 // get the actual filter name
1877 ::rtl::OUString aFilterName;
1879 uno::Reference< lang::XMultiServiceFactory > xConfigProvider(
1880 xFactory->createInstance(
1881 ::rtl::OUString::createFromAscii( "com.sun.star.configuration.ConfigurationProvider" ) ),
1882 uno::UNO_QUERY_THROW );
1884 uno::Sequence< uno::Any > aArgs( 1 );
1885 beans::PropertyValue aPathProp;
1886 aPathProp.Name = ::rtl::OUString::createFromAscii( "nodepath" );
1887 aPathProp.Value <<= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Setup/Office/Factories/" ) );
1888 aArgs[0] <<= aPathProp;
1890 uno::Reference< container::XNameAccess > xSOFConfig(
1891 xConfigProvider->createInstanceWithArguments(
1892 ::rtl::OUString::createFromAscii( "com.sun.star.configuration.ConfigurationAccess" ),
1893 aArgs ),
1894 uno::UNO_QUERY_THROW );
1896 uno::Reference< container::XNameAccess > xApplConfig;
1897 xSOFConfig->getByName( sDocServiceName ) >>= xApplConfig;
1898 if ( !xApplConfig.is() )
1899 throw uno::RuntimeException();
1901 xApplConfig->getByName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ooSetupFactoryActualTemplateFilter" ) ) ) >>= aFilterName;
1902 if ( !aFilterName.getLength() )
1903 throw uno::RuntimeException();
1905 // find the related type name
1906 ::rtl::OUString aTypeName;
1907 uno::Reference< container::XNameAccess > xFilterFactory(
1908 xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.document.FilterFactory" ) ),
1909 uno::UNO_QUERY_THROW );
1911 uno::Sequence< beans::PropertyValue > aFilterData;
1912 xFilterFactory->getByName( aFilterName ) >>= aFilterData;
1913 for ( sal_Int32 nInd = 0; nInd < aFilterData.getLength(); nInd++ )
1914 if ( aFilterData[nInd].Name.equalsAscii( "Type" ) )
1915 aFilterData[nInd].Value >>= aTypeName;
1917 if ( !aTypeName.getLength() )
1918 throw uno::RuntimeException();
1920 // find the mediatype and extension
1921 uno::Reference< container::XNameAccess > xTypeDetection =
1922 mxType.is() ?
1923 uno::Reference< container::XNameAccess >( mxType, uno::UNO_QUERY_THROW ) :
1924 uno::Reference< container::XNameAccess >(
1925 xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.document.TypeDetection" ) ),
1926 uno::UNO_QUERY_THROW );
1928 SequenceAsHashMap aTypeProps( xTypeDetection->getByName( aTypeName ) );
1929 uno::Sequence< ::rtl::OUString > aAllExt =
1930 aTypeProps.getUnpackedValueOrDefault( ::rtl::OUString::createFromAscii( "Extensions" ), Sequence< ::rtl::OUString >() );
1931 if ( !aAllExt.getLength() )
1932 throw uno::RuntimeException();
1934 ::rtl::OUString aMediaType = aTypeProps.getUnpackedValueOrDefault( ::rtl::OUString::createFromAscii( "MediaType" ), ::rtl::OUString() );
1935 ::rtl::OUString aExt = aAllExt[0];
1937 if ( !aMediaType.getLength() || !aExt.getLength() )
1938 throw uno::RuntimeException();
1940 // construct destination url
1941 if ( !aGroupTargetURL.getLength() )
1943 aGroupTargetURL = CreateNewGroupFsys( rGroupName, aGroup );
1945 if ( !aGroupTargetURL.getLength() )
1946 throw uno::RuntimeException();
1949 ::rtl::OUString aNewTemplateTargetURL = CreateNewUniqueFileWithPrefix( aGroupTargetURL, rTemplateName, aExt );
1950 if ( !aNewTemplateTargetURL.getLength() )
1952 aNewTemplateTargetURL = CreateNewUniqueFileWithPrefix( aGroupTargetURL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UserTemplate" ) ), aExt );
1954 if ( !aNewTemplateTargetURL.getLength() )
1955 throw uno::RuntimeException();
1958 // store template
1959 uno::Sequence< PropertyValue > aStoreArgs( 2 );
1960 aStoreArgs[0].Name = ::rtl::OUString::createFromAscii( "FilterName" );
1961 aStoreArgs[0].Value <<= aFilterName;
1962 aStoreArgs[1].Name = ::rtl::OUString::createFromAscii( "DocumentTitle" );
1963 aStoreArgs[1].Value <<= rTemplateName;
1965 ::rtl::OUString aCurrentDocumentURL = rStorable->getLocation();
1966 if( !SfxMedium::EqualURLs( aNewTemplateTargetURL, rStorable->getLocation() ))
1967 rStorable->storeToURL( aNewTemplateTargetURL, aStoreArgs );
1968 else
1969 rStorable->store();
1971 // the storing was successful, now the old template with the same name can be removed if it existed
1972 if ( aTemplateToRemoveTargetURL.getLength() )
1974 removeContent( aTemplateToRemoveTargetURL );
1977 * pb: #i79496#
1978 * if the old template was the standard template
1979 * it is necessary to change the standard template with the new file name
1981 String sStdTmplFile = SfxObjectFactory::GetStandardTemplate( sDocServiceName );
1982 if ( INetURLObject( sStdTmplFile ) == INetURLObject( aTemplateToRemoveTargetURL ) )
1984 SfxObjectFactory::SetStandardTemplate( sDocServiceName, aNewTemplateTargetURL );
1988 if ( bRemoveOldTemplateContent )
1989 removeContent( aTemplateToRemove );
1991 // add the template to hierarchy
1992 return addEntry( aGroup, rTemplateName, aNewTemplateTargetURL, aMediaType );
1994 catch( Exception& )
1996 // the template was not stored
1997 return sal_False;
2001 //-----------------------------------------------------------------------------
2002 sal_Bool SfxDocTplService_Impl::addTemplate( const OUString& rGroupName,
2003 const OUString& rTemplateName,
2004 const OUString& rSourceURL )
2006 ::osl::MutexGuard aGuard( maMutex );
2008 // Check, wether or not there is a group with this name
2009 // Return false, if there is no group with the given name
2010 Content aGroup, aTemplate, aTargetGroup;
2011 OUString aGroupURL, aTemplateURL;
2012 INetURLObject aGroupObj( maRootURL );
2014 aGroupObj.insertName( rGroupName, false,
2015 INetURLObject::LAST_SEGMENT, true,
2016 INetURLObject::ENCODE_ALL );
2017 aGroupURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE );
2019 if ( ! Content::create( aGroupURL, maCmdEnv, aGroup ) )
2020 return sal_False;
2022 // Check, if there's a template with the given name in this group
2023 // Return false, if there already is a template
2024 aGroupObj.insertName( rTemplateName, false,
2025 INetURLObject::LAST_SEGMENT, true,
2026 INetURLObject::ENCODE_ALL );
2027 aTemplateURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE );
2029 if ( Content::create( aTemplateURL, maCmdEnv, aTemplate ) )
2030 return sal_False;
2032 // get the target url of the group
2033 OUString aTargetURL;
2034 OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( TARGET_DIR_URL ) );
2035 Any aValue;
2037 if ( getProperty( aGroup, aPropName, aValue ) )
2038 aValue >>= aTargetURL;
2040 if ( !aTargetURL.getLength() )
2042 aTargetURL = CreateNewGroupFsys( rGroupName, aGroup );
2044 if ( !aTargetURL.getLength() )
2045 return sal_False;
2048 // Get the content type
2049 OUString aTitle, aType, aTargetURL2, aFullName;
2051 // only StarOffice documents are acceptable
2052 sal_Bool bDocHasTitle = sal_False;
2053 if( !getTitleFromURL( rSourceURL, aTitle, aType, bDocHasTitle ) )
2054 return sal_False;
2056 INetURLObject aSourceObj( rSourceURL );
2057 if ( rTemplateName.equals( aTitle ) )
2059 /////////////////////////////////////////////////////
2060 // addTemplate will sometimes be called just to add an entry in the
2061 // hierarchy; the target URL and the source URL will be the same in
2062 // this scenario
2063 // TODO/LATER: get rid of this old hack
2065 INetURLObject aTargetObj( aTargetURL );
2067 aTargetObj.insertName( rTemplateName, false,
2068 INetURLObject::LAST_SEGMENT, true,
2069 INetURLObject::ENCODE_ALL );
2070 aTargetObj.setExtension( aSourceObj.getExtension() );
2072 aTargetURL2 = aTargetObj.GetMainURL( INetURLObject::NO_DECODE );
2074 if ( aTargetURL2 == rSourceURL )
2075 return addEntry( aGroup, rTemplateName, aTargetURL2, aType );
2078 /////////////////////////////////////////////////////
2079 // copy the template into the new group (targeturl)
2081 INetURLObject aTmpURL( aSourceObj );
2082 aTmpURL.CutExtension();
2083 ::rtl::OUString aPattern = aTmpURL.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
2085 ::rtl::OUString aNewTemplateTargetURL = CreateNewUniqueFileWithPrefix( aTargetURL, aPattern, aSourceObj.getExtension() );
2086 INetURLObject aNewTemplateTargetObj( aNewTemplateTargetURL );
2087 ::rtl::OUString aNewTemplateTargetName = aNewTemplateTargetObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
2088 if ( !aNewTemplateTargetURL.getLength() || !aNewTemplateTargetName.getLength() )
2089 return sal_False;
2091 // get access to source file
2092 Content aSourceContent;
2093 uno::Reference < ucb::XCommandEnvironment > xEnv;
2094 INetURLObject aSourceURL( rSourceURL );
2095 if( ! Content::create( aSourceURL.GetMainURL( INetURLObject::NO_DECODE ), xEnv, aSourceContent ) )
2096 return sal_False;
2098 if( ! Content::create( aTargetURL, xEnv, aTargetGroup ) )
2099 return sal_False;
2101 // transfer source file
2104 if( ! aTargetGroup.transferContent( aSourceContent,
2105 InsertOperation_COPY,
2106 aNewTemplateTargetName,
2107 NameClash::OVERWRITE ) )
2108 return sal_False;
2110 // allow to edit the added template
2111 Content aResultContent;
2112 if ( Content::create( aNewTemplateTargetURL, xEnv, aResultContent ) )
2114 ::rtl::OUString aPropertyName( RTL_CONSTASCII_USTRINGPARAM( "IsReadOnly" ) );
2115 uno::Any aProperty;
2116 sal_Bool bReadOnly = sal_False;
2117 if ( getProperty( aResultContent, aPropertyName, aProperty ) && ( aProperty >>= bReadOnly ) && bReadOnly )
2118 setProperty( aResultContent, aPropertyName, uno::makeAny( (sal_Bool)sal_False ) );
2121 catch ( ContentCreationException& )
2122 { return sal_False; }
2123 catch ( Exception& )
2124 { return sal_False; }
2127 // either the document has title and it is the same as requested, or we have to set it
2128 sal_Bool bCorrectTitle = ( bDocHasTitle && aTitle.equals( rTemplateName ) );
2129 if ( !bCorrectTitle )
2131 if ( !bDocHasTitle )
2133 INetURLObject aNewTmpObj( aNewTemplateTargetObj );
2134 aNewTmpObj.CutExtension();
2135 bCorrectTitle = ( aNewTmpObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET ).equals( rTemplateName ) );
2138 if ( !bCorrectTitle )
2139 bCorrectTitle = setTitleForURL( aNewTemplateTargetURL, rTemplateName );
2142 if ( bCorrectTitle )
2144 // create a new entry in the hierarchy
2145 return addEntry( aGroup, rTemplateName, aNewTemplateTargetURL, aType );
2148 // TODO/LATER: The user could be notified here that the renaming has failed
2149 // create a new entry in the hierarchy
2150 addEntry( aGroup, aTitle, aNewTemplateTargetURL, aType );
2151 return sal_False;
2154 //-----------------------------------------------------------------------------
2155 sal_Bool SfxDocTplService_Impl::removeTemplate( const OUString& rGroupName,
2156 const OUString& rTemplateName )
2158 ::osl::MutexGuard aGuard( maMutex );
2160 // Check, wether or not there is a group with this name
2161 // Return false, if there is no group with the given name
2162 Content aGroup, aTemplate;
2163 OUString aGroupURL, aTemplateURL;
2164 INetURLObject aGroupObj( maRootURL );
2166 aGroupObj.insertName( rGroupName, false,
2167 INetURLObject::LAST_SEGMENT, true,
2168 INetURLObject::ENCODE_ALL );
2169 aGroupURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE );
2171 if ( ! Content::create( aGroupURL, maCmdEnv, aGroup ) )
2172 return sal_False;
2174 // Check, if there's a template with the given name in this group
2175 // Return false, if there is no template
2176 aGroupObj.insertName( rTemplateName, false,
2177 INetURLObject::LAST_SEGMENT, true,
2178 INetURLObject::ENCODE_ALL );
2179 aTemplateURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE );
2181 if ( !Content::create( aTemplateURL, maCmdEnv, aTemplate ) )
2182 return sal_False;
2184 // get the target URL from the template
2185 OUString aTargetURL;
2186 OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( TARGET_URL ) );
2187 Any aValue;
2189 if ( getProperty( aTemplate, aPropName, aValue ) )
2190 aValue >>= aTargetURL;
2192 // delete the target template
2193 if ( aTargetURL.getLength() )
2195 if ( !maTemplateDirs.getLength()
2196 || !::utl::UCBContentHelper::IsSubPath( maTemplateDirs[ maTemplateDirs.getLength() - 1 ], aTargetURL ) )
2197 return sal_False;
2199 removeContent( aTargetURL );
2202 // delete the template entry
2203 return removeContent( aTemplate );
2206 //-----------------------------------------------------------------------------
2207 sal_Bool SfxDocTplService_Impl::renameTemplate( const OUString& rGroupName,
2208 const OUString& rOldName,
2209 const OUString& rNewName )
2211 ::osl::MutexGuard aGuard( maMutex );
2213 // Check, wether or not there is a group with this name
2214 // Return false, if there is no group with the given name
2215 Content aGroup, aTemplate;
2216 OUString aGroupURL, aTemplateURL;
2217 INetURLObject aGroupObj( maRootURL );
2219 aGroupObj.insertName( rGroupName, false,
2220 INetURLObject::LAST_SEGMENT, true,
2221 INetURLObject::ENCODE_ALL );
2222 aGroupURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE );
2224 if ( ! Content::create( aGroupURL, maCmdEnv, aGroup ) )
2225 return sal_False;
2227 // Check, if there's a template with the new name in this group
2228 // Return false, if there is one
2229 aGroupObj.insertName( rNewName, false,
2230 INetURLObject::LAST_SEGMENT, true,
2231 INetURLObject::ENCODE_ALL );
2232 aTemplateURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE );
2234 if ( Content::create( aTemplateURL, maCmdEnv, aTemplate ) )
2235 return sal_False;
2237 // Check, if there's a template with the old name in this group
2238 // Return false, if there is no template
2239 aGroupObj.removeSegment();
2240 aGroupObj.insertName( rOldName, false,
2241 INetURLObject::LAST_SEGMENT, true,
2242 INetURLObject::ENCODE_ALL );
2243 aTemplateURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE );
2245 if ( !Content::create( aTemplateURL, maCmdEnv, aTemplate ) )
2246 return sal_False;
2248 OUString aTemplateTargetURL;
2249 OUString aTargetProp( RTL_CONSTASCII_USTRINGPARAM( TARGET_URL ) );
2250 Any aTargetValue;
2252 if ( getProperty( aTemplate, aTargetProp, aTargetValue ) )
2253 aTargetValue >>= aTemplateTargetURL;
2255 if ( !setTitleForURL( aTemplateTargetURL, rNewName ) )
2256 return sal_False;
2258 // rename the template entry in the cache
2259 OUString aTitleProp( RTL_CONSTASCII_USTRINGPARAM( TITLE ) );
2260 Any aTitleValue;
2261 aTitleValue <<= rNewName;
2263 return setProperty( aTemplate, aTitleProp, aTitleValue );
2266 //-----------------------------------------------------------------------------
2267 //-----------------------------------------------------------------------------
2268 //-----------------------------------------------------------------------------
2270 SFX_IMPL_XSERVICEINFO( SfxDocTplService, TEMPLATE_SERVICE_NAME, TEMPLATE_IMPLEMENTATION_NAME )
2271 SFX_IMPL_SINGLEFACTORY( SfxDocTplService )
2273 //-----------------------------------------------------------------------------
2274 SfxDocTplService::SfxDocTplService( const uno::Reference< XMultiServiceFactory >& xFactory )
2276 pImp = new SfxDocTplService_Impl( xFactory );
2279 //-----------------------------------------------------------------------------
2281 SfxDocTplService::~SfxDocTplService()
2283 delete pImp;
2286 //-----------------------------------------------------------------------------
2287 //--- XLocalizable ---
2288 //-----------------------------------------------------------------------------
2290 Locale SAL_CALL SfxDocTplService::getLocale()
2291 throw( RUNTIMEEXCEPTION )
2293 return pImp->getLocale();
2296 //-----------------------------------------------------------------------------
2298 void SAL_CALL SfxDocTplService::setLocale( const Locale & rLocale )
2299 throw( RUNTIMEEXCEPTION )
2301 pImp->setLocale( rLocale );
2304 //-----------------------------------------------------------------------------
2305 //--- XDocumentTemplates ---
2306 //-----------------------------------------------------------------------------
2307 uno::Reference< XCONTENT > SAL_CALL SfxDocTplService::getContent()
2308 throw( RUNTIMEEXCEPTION )
2310 if ( pImp->init() )
2311 return pImp->getContent().get();
2312 else
2313 return NULL;
2316 //-----------------------------------------------------------------------------
2317 sal_Bool SAL_CALL SfxDocTplService::storeTemplate( const OUString& GroupName,
2318 const OUString& TemplateName,
2319 const uno::Reference< XSTORABLE >& Storable )
2320 throw( RUNTIMEEXCEPTION )
2322 if ( pImp->init() )
2323 return pImp->storeTemplate( GroupName, TemplateName, Storable );
2324 else
2325 return sal_False;
2328 //-----------------------------------------------------------------------------
2329 sal_Bool SAL_CALL SfxDocTplService::addTemplate( const OUString& rGroupName,
2330 const OUString& rTemplateName,
2331 const OUString& rSourceURL )
2332 throw( RUNTIMEEXCEPTION )
2334 if ( pImp->init() )
2335 return pImp->addTemplate( rGroupName, rTemplateName, rSourceURL );
2336 else
2337 return sal_False;
2340 //-----------------------------------------------------------------------------
2341 sal_Bool SAL_CALL SfxDocTplService::removeTemplate( const OUString& rGroupName,
2342 const OUString& rTemplateName )
2343 throw( RUNTIMEEXCEPTION )
2345 if ( pImp->init() )
2346 return pImp->removeTemplate( rGroupName, rTemplateName );
2347 else
2348 return sal_False;
2351 //-----------------------------------------------------------------------------
2352 sal_Bool SAL_CALL SfxDocTplService::renameTemplate( const OUString& rGroupName,
2353 const OUString& rOldName,
2354 const OUString& rNewName )
2355 throw( RUNTIMEEXCEPTION )
2357 if ( rOldName == rNewName )
2358 return sal_True;
2360 if ( pImp->init() )
2361 return pImp->renameTemplate( rGroupName, rOldName, rNewName );
2362 else
2363 return sal_False;
2366 //-----------------------------------------------------------------------------
2367 sal_Bool SAL_CALL SfxDocTplService::addGroup( const OUString& rGroupName )
2368 throw( RUNTIMEEXCEPTION )
2370 if ( pImp->init() )
2371 return pImp->addGroup( rGroupName );
2372 else
2373 return sal_False;
2376 //-----------------------------------------------------------------------------
2377 sal_Bool SAL_CALL SfxDocTplService::removeGroup( const OUString& rGroupName )
2378 throw( RUNTIMEEXCEPTION )
2380 if ( pImp->init() )
2381 return pImp->removeGroup( rGroupName );
2382 else
2383 return sal_False;
2386 //-----------------------------------------------------------------------------
2387 sal_Bool SAL_CALL SfxDocTplService::renameGroup( const OUString& rOldName,
2388 const OUString& rNewName )
2389 throw( RUNTIMEEXCEPTION )
2391 if ( rOldName == rNewName )
2392 return sal_True;
2394 if ( pImp->init() )
2395 return pImp->renameGroup( rOldName, rNewName );
2396 else
2397 return sal_False;
2400 //-----------------------------------------------------------------------------
2401 void SAL_CALL SfxDocTplService::update()
2402 throw( RUNTIMEEXCEPTION )
2404 if ( pImp->init() )
2405 pImp->update( sal_True );
2408 //-----------------------------------------------------------------------------
2409 //-----------------------------------------------------------------------------
2410 //------------------------------------------------------------------------
2412 Updater_Impl::Updater_Impl( SfxDocTplService_Impl* pTemplates )
2414 mpDocTemplates = pTemplates;
2417 //------------------------------------------------------------------------
2418 Updater_Impl::~Updater_Impl()
2422 //------------------------------------------------------------------------
2423 void SAL_CALL Updater_Impl::run()
2425 mpDocTemplates->doUpdate();
2428 //------------------------------------------------------------------------
2429 void SAL_CALL Updater_Impl::onTerminated()
2431 mpDocTemplates->finished();
2432 delete this;
2435 //-----------------------------------------------------------------------------
2436 //-----------------------------------------------------------------------------
2437 //-----------------------------------------------------------------------------
2438 WaitWindow_Impl::WaitWindow_Impl()
2439 : WorkWindow( NULL, WB_BORDER | WB_3DLOOK )
2441 Rectangle aRect = Rectangle( 0, 0, 300, 30000 );
2442 _nTextStyle = TEXT_DRAW_CENTER | TEXT_DRAW_VCENTER | TEXT_DRAW_WORDBREAK | TEXT_DRAW_MULTILINE;
2443 _aText = String( SfxResId( RID_CNT_STR_WAITING ) );
2444 _aRect = GetTextRect( aRect, _aText, _nTextStyle );
2445 aRect = _aRect;
2446 aRect.Right() += 2*X_OFFSET;
2447 aRect.Bottom() += 2*Y_OFFSET;
2448 _aRect.SetPos( Point( X_OFFSET, Y_OFFSET ) );
2449 SetOutputSizePixel( aRect.GetSize() );
2450 Show();
2451 Update();
2452 Flush();
2455 //-----------------------------------------------------------------------------
2456 WaitWindow_Impl::~WaitWindow_Impl()
2458 Hide();
2461 //-----------------------------------------------------------------------------
2462 void WaitWindow_Impl::Paint( const Rectangle& /*rRect*/ )
2464 DrawText( _aRect, _aText, _nTextStyle );
2467 //-----------------------------------------------------------------------------
2468 //-----------------------------------------------------------------------------
2469 //-----------------------------------------------------------------------------
2470 void SfxDocTplService_Impl::addHierGroup( GroupList_Impl& rList,
2471 const OUString& rTitle,
2472 const OUString& rOwnURL )
2474 // now get the content of the Group
2475 Content aContent;
2476 uno::Reference< XResultSet > xResultSet;
2477 Sequence< OUString > aProps(3);
2479 aProps[0] = OUString::createFromAscii( TITLE );
2480 aProps[1] = OUString::createFromAscii( TARGET_URL );
2481 aProps[2] = OUString::createFromAscii( PROPERTY_TYPE );
2485 aContent = Content( rOwnURL, maCmdEnv );
2486 ResultSetInclude eInclude = INCLUDE_DOCUMENTS_ONLY;
2487 xResultSet = aContent.createCursor( aProps, eInclude );
2489 catch ( ContentCreationException& )
2491 DBG_ERRORFILE( "addHierGroup: ContentCreationException" );
2493 catch ( Exception& ) {}
2495 if ( xResultSet.is() )
2497 GroupData_Impl *pGroup = new GroupData_Impl( rTitle );
2498 pGroup->setHierarchy( sal_True );
2499 pGroup->setHierarchyURL( rOwnURL );
2500 rList.Insert( pGroup );
2502 uno::Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY );
2503 uno::Reference< XRow > xRow( xResultSet, UNO_QUERY );
2507 while ( xResultSet->next() )
2509 BOOL bUpdateType = sal_False;
2510 DocTemplates_EntryData_Impl *pData;
2512 OUString aTitle( xRow->getString( 1 ) );
2513 OUString aTargetDir( xRow->getString( 2 ) );
2514 OUString aType( xRow->getString( 3 ) );
2515 OUString aHierURL = xContentAccess->queryContentIdentifierString();
2517 if ( !aType.getLength() )
2519 OUString aTmpTitle;
2521 sal_Bool bDocHasTitle = sal_False;
2522 if( !getTitleFromURL( aTargetDir, aTmpTitle, aType, bDocHasTitle ) )
2524 DBG_ERRORFILE( "addHierGroup(): template of alien format" );
2525 continue;
2528 if ( aType.getLength() )
2529 bUpdateType = sal_True;
2532 pData = pGroup->addEntry( aTitle, aTargetDir, aType, aHierURL );
2533 pData->setUpdateType( bUpdateType );
2536 catch ( Exception& ) {}
2540 //-----------------------------------------------------------------------------
2541 void SfxDocTplService_Impl::addFsysGroup( GroupList_Impl& rList,
2542 const OUString& rTitle,
2543 const OUString& rUITitle,
2544 const OUString& rOwnURL,
2545 sal_Bool bWriteableGroup )
2547 ::rtl::OUString aTitle;
2549 if ( !rUITitle.getLength() )
2551 // reserved FS names that should not be used
2552 if ( rTitle.compareToAscii( "wizard" ) == 0 )
2553 return;
2554 else if ( rTitle.compareToAscii( "internal" ) == 0 )
2555 return;
2557 aTitle = getLongName( rTitle );
2559 else
2560 aTitle = rUITitle;
2562 if ( !aTitle.getLength() )
2563 return;
2565 GroupData_Impl *pGroup = rList.First();
2567 while ( pGroup && pGroup->getTitle() != aTitle )
2568 pGroup = rList.Next();
2570 if ( !pGroup )
2572 pGroup = new GroupData_Impl( aTitle );
2573 rList.Insert( pGroup );
2576 if ( bWriteableGroup )
2577 pGroup->setTargetURL( rOwnURL );
2579 pGroup->setInUse();
2581 // now get the content of the Group
2582 Content aContent;
2583 uno::Reference< XResultSet > xResultSet;
2584 Sequence< OUString > aProps(1);
2585 aProps[0] = OUString::createFromAscii( TITLE );
2589 // this method is only used during checking of the available template-folders
2590 // that should happen quietly
2591 uno::Reference< XCommandEnvironment > aQuietEnv;
2592 aContent = Content( rOwnURL, aQuietEnv );
2593 ResultSetInclude eInclude = INCLUDE_DOCUMENTS_ONLY;
2594 xResultSet = aContent.createCursor( aProps, eInclude );
2596 catch ( Exception& ) {}
2598 if ( xResultSet.is() )
2600 uno::Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY );
2601 uno::Reference< XRow > xRow( xResultSet, UNO_QUERY );
2605 while ( xResultSet->next() )
2607 OUString aChildTitle( xRow->getString( 1 ) );
2608 OUString aTargetURL = xContentAccess->queryContentIdentifierString();
2609 OUString aType;
2610 OUString aHierURL;
2612 if ( aChildTitle.compareToAscii( "sfx.tlx" ) == 0
2613 || aChildTitle.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "groupuinames.xml" ) ) )
2614 continue;
2616 // only StarOffice templates are accepted
2617 sal_Bool bDocHasTitle = sal_False;
2618 if( !getTitleFromURL( aTargetURL, aChildTitle, aType, bDocHasTitle ) )
2619 continue;
2621 pGroup->addEntry( aChildTitle, aTargetURL, aType, aHierURL );
2624 catch ( Exception& ) {}
2628 // -----------------------------------------------------------------------
2629 void SfxDocTplService_Impl::createFromContent( GroupList_Impl& rList,
2630 Content &rContent,
2631 sal_Bool bHierarchy,
2632 sal_Bool bWriteableContent )
2634 OUString aTargetURL = rContent.get()->getIdentifier()->getContentIdentifier();
2636 // when scanning the file system, we have to add the 'standard' group, too
2637 if ( ! bHierarchy )
2639 OUString aUIStdTitle = getLongName( OUString( RTL_CONSTASCII_USTRINGPARAM( STANDARD_FOLDER ) ) );
2640 addFsysGroup( rList, ::rtl::OUString(), aUIStdTitle, aTargetURL, bWriteableContent );
2643 // search for predefined UI names
2644 INetURLObject aLayerObj( aTargetURL );
2646 // TODO/LATER: Use hashmap in future
2647 uno::Sequence< beans::StringPair > aUINames;
2648 if ( !bHierarchy )
2649 aUINames = ReadUINamesForTemplateDir_Impl( aLayerObj.GetMainURL( INetURLObject::NO_DECODE ) );
2651 uno::Reference< XResultSet > xResultSet;
2652 Sequence< OUString > aProps(1);
2653 aProps[0] = OUString::createFromAscii( TITLE );
2657 ResultSetInclude eInclude = INCLUDE_FOLDERS_ONLY;
2658 xResultSet = rContent.createCursor( aProps, eInclude );
2660 catch ( Exception& ) {}
2662 if ( xResultSet.is() )
2664 uno::Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY );
2665 uno::Reference< XRow > xRow( xResultSet, UNO_QUERY );
2669 while ( xResultSet->next() )
2671 // TODO/LATER: clarify the encoding of the Title
2672 OUString aTitle( xRow->getString( 1 ) );
2673 OUString aTargetSubfolderURL( xContentAccess->queryContentIdentifierString() );
2675 if ( bHierarchy )
2676 addHierGroup( rList, aTitle, aTargetSubfolderURL );
2677 else
2679 ::rtl::OUString aUITitle;
2680 for ( sal_Int32 nInd = 0; nInd < aUINames.getLength(); nInd++ )
2681 if ( aUINames[nInd].First.equals( aTitle ) )
2683 aUITitle = aUINames[nInd].Second;
2684 break;
2687 addFsysGroup( rList, aTitle, aUITitle, aTargetSubfolderURL, bWriteableContent );
2691 catch ( Exception& ) {}
2695 //-----------------------------------------------------------------------------
2696 void SfxDocTplService_Impl::removeFromHierarchy( DocTemplates_EntryData_Impl *pData )
2698 Content aTemplate;
2700 if ( Content::create( pData->getHierarchyURL(), maCmdEnv, aTemplate ) )
2702 removeContent( aTemplate );
2706 //-----------------------------------------------------------------------------
2707 void SfxDocTplService_Impl::addToHierarchy( GroupData_Impl *pGroup,
2708 DocTemplates_EntryData_Impl *pData )
2710 Content aGroup, aTemplate;
2712 if ( ! Content::create( pGroup->getHierarchyURL(), maCmdEnv, aGroup ) )
2713 return;
2715 // Check, if there's a template with the given name in this group
2716 // Return if there is already a template
2717 INetURLObject aGroupObj( pGroup->getHierarchyURL() );
2719 aGroupObj.insertName( pData->getTitle(), false,
2720 INetURLObject::LAST_SEGMENT, true,
2721 INetURLObject::ENCODE_ALL );
2723 OUString aTemplateURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE );
2725 if ( Content::create( aTemplateURL, maCmdEnv, aTemplate ) )
2726 return;
2728 addEntry( aGroup, pData->getTitle(),
2729 pData->getTargetURL(),
2730 pData->getType() );
2733 //-----------------------------------------------------------------------------
2734 void SfxDocTplService_Impl::updateData( DocTemplates_EntryData_Impl *pData )
2736 Content aTemplate;
2738 if ( ! Content::create( pData->getHierarchyURL(), maCmdEnv, aTemplate ) )
2739 return;
2741 OUString aPropName;
2743 if ( pData->getUpdateType() )
2745 aPropName = OUString( RTL_CONSTASCII_USTRINGPARAM( PROPERTY_TYPE ) );
2746 setProperty( aTemplate, aPropName, makeAny( pData->getType() ) );
2749 if ( pData->getUpdateLink() )
2751 aPropName = OUString( RTL_CONSTASCII_USTRINGPARAM( TARGET_URL ) );
2752 setProperty( aTemplate, aPropName, makeAny( pData->getTargetURL() ) );
2756 //-----------------------------------------------------------------------------
2757 void SfxDocTplService_Impl::addGroupToHierarchy( GroupData_Impl *pGroup )
2759 OUString aAdditionalProp( RTL_CONSTASCII_USTRINGPARAM( TARGET_DIR_URL ) );
2760 Content aGroup;
2762 INetURLObject aNewGroupObj( maRootURL );
2763 aNewGroupObj.insertName( pGroup->getTitle(), false,
2764 INetURLObject::LAST_SEGMENT, true,
2765 INetURLObject::ENCODE_ALL );
2767 OUString aNewGroupURL = aNewGroupObj.GetMainURL( INetURLObject::NO_DECODE );
2769 if ( createFolder( aNewGroupURL, sal_False, sal_False, aGroup ) )
2771 setProperty( aGroup, aAdditionalProp, makeAny( pGroup->getTargetURL() ) );
2772 pGroup->setHierarchyURL( aNewGroupURL );
2774 ULONG nCount = pGroup->count();
2775 for ( ULONG i=0; i<nCount; i++ )
2777 DocTemplates_EntryData_Impl *pData = pGroup->getEntry( i );
2778 addToHierarchy( pGroup, pData ); // add entry to hierarchy
2783 //-----------------------------------------------------------------------------
2784 void SfxDocTplService_Impl::removeFromHierarchy( GroupData_Impl *pGroup )
2786 Content aGroup;
2788 if ( Content::create( pGroup->getHierarchyURL(), maCmdEnv, aGroup ) )
2790 removeContent( aGroup );
2794 // -----------------------------------------------------------------------
2795 // -----------------------------------------------------------------------
2796 // -----------------------------------------------------------------------
2797 GroupData_Impl::GroupData_Impl( const OUString& rTitle )
2799 maTitle = rTitle;
2800 mbInUse = sal_False;
2801 mbInHierarchy = sal_False;
2804 // -----------------------------------------------------------------------
2805 GroupData_Impl::~GroupData_Impl()
2807 DocTemplates_EntryData_Impl *pData = maEntries.First();
2808 while ( pData )
2810 delete pData;
2811 pData = maEntries.Next();
2815 // -----------------------------------------------------------------------
2816 DocTemplates_EntryData_Impl* GroupData_Impl::addEntry( const OUString& rTitle,
2817 const OUString& rTargetURL,
2818 const OUString& rType,
2819 const OUString& rHierURL )
2821 DocTemplates_EntryData_Impl *pData = maEntries.First();
2823 while ( pData && pData->getTitle() != rTitle )
2824 pData = maEntries.Next();
2826 if ( !pData )
2828 pData = new DocTemplates_EntryData_Impl( rTitle );
2829 pData->setTargetURL( rTargetURL );
2830 pData->setType( rType );
2831 if ( rHierURL.getLength() )
2833 pData->setHierarchyURL( rHierURL );
2834 pData->setHierarchy( sal_True );
2836 maEntries.Insert( pData );
2838 else
2840 if ( rHierURL.getLength() )
2842 pData->setHierarchyURL( rHierURL );
2843 pData->setHierarchy( sal_True );
2846 if ( pData->getInHierarchy() )
2847 pData->setInUse();
2849 if ( rTargetURL != pData->getTargetURL() )
2851 pData->setTargetURL( rTargetURL );
2852 pData->setUpdateLink( sal_True );
2856 return pData;
2859 // -----------------------------------------------------------------------
2860 // -----------------------------------------------------------------------
2861 // -----------------------------------------------------------------------
2862 DocTemplates_EntryData_Impl::DocTemplates_EntryData_Impl( const OUString& rTitle )
2864 maTitle = rTitle;
2865 mbInUse = sal_False;
2866 mbInHierarchy = sal_False;
2867 mbUpdateType = sal_False;
2868 mbUpdateLink = sal_False;
2871 // -----------------------------------------------------------------------
2872 SfxURLRelocator_Impl::SfxURLRelocator_Impl( uno::Reference< XMultiServiceFactory > xFactory )
2873 : mxFactory( xFactory )
2877 // -----------------------------------------------------------------------
2878 SfxURLRelocator_Impl::~SfxURLRelocator_Impl()
2882 // -----------------------------------------------------------------------
2883 void SfxURLRelocator_Impl::initOfficeInstDirs()
2885 if ( !mxOfficeInstDirs.is() )
2887 osl::MutexGuard aGuard( maMutex );
2888 if ( !mxOfficeInstDirs.is() )
2890 OSL_ENSURE( mxFactory.is(), "No service manager!" );
2892 uno::Reference< XComponentContext > xCtx;
2893 uno::Reference< XPropertySet > xPropSet( mxFactory, UNO_QUERY );
2894 if ( xPropSet.is() )
2896 xPropSet->getPropertyValue(
2897 rtl::OUString(
2898 RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ) ) )
2899 >>= xCtx;
2902 OSL_ENSURE( xCtx.is(),
2903 "Unable to obtain component context from "
2904 "service manager!" );
2906 if ( xCtx.is() )
2908 xCtx->getValueByName(
2909 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
2910 "/singletons/"
2911 "com.sun.star.util.theOfficeInstallationDirectories" ) ) )
2912 >>= mxOfficeInstDirs;
2915 OSL_ENSURE( mxOfficeInstDirs.is(),
2916 "Unable to obtain office installation directory "
2917 "singleton!" );
2922 // -----------------------------------------------------------------------
2923 void SfxURLRelocator_Impl::makeRelocatableURL( rtl::OUString & rURL )
2925 if ( rURL.getLength() > 0 )
2927 initOfficeInstDirs();
2928 rURL = mxOfficeInstDirs->makeRelocatableURL( rURL );
2932 // -----------------------------------------------------------------------
2933 void SfxURLRelocator_Impl::makeAbsoluteURL( rtl::OUString & rURL )
2935 if ( rURL.getLength() > 0 )
2937 initOfficeInstDirs();
2938 rURL = mxOfficeInstDirs->makeAbsoluteURL( rURL );