Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include "doctemplates.hxx"
22 : #include <osl/mutex.hxx>
23 : #include <tools/debug.hxx>
24 : #include <tools/diagnose_ex.h>
25 : #include <tools/urlobj.hxx>
26 : #include <rtl/ustring.hxx>
27 : #include <rtl/ustrbuf.hxx>
28 : #include <tools/resary.hxx>
29 : #include <vcl/svapp.hxx>
30 : #include <vcl/wrkwin.hxx>
31 : #include <unotools/pathoptions.hxx>
32 : #include <comphelper/componentcontext.hxx>
33 : #include <comphelper/processfactory.hxx>
34 : #include <comphelper/sequenceashashmap.hxx>
35 : #include <comphelper/string.hxx>
36 : #include <com/sun/star/beans/PropertyAttribute.hpp>
37 : #include <com/sun/star/beans/XPropertySet.hpp>
38 : #include <com/sun/star/beans/XPropertySetInfo.hpp>
39 : #include <com/sun/star/beans/XPropertyContainer.hpp>
40 : #include <com/sun/star/beans/StringPair.hpp>
41 : #include <com/sun/star/util/XMacroExpander.hpp>
42 : #include <com/sun/star/configuration/theDefaultProvider.hpp>
43 : #include <com/sun/star/container/XContainerQuery.hpp>
44 : #include <com/sun/star/document/XTypeDetection.hpp>
45 : #include <com/sun/star/document/DocumentProperties.hpp>
46 : #include <com/sun/star/io/TempFile.hpp>
47 : #include <com/sun/star/sdbc/XResultSet.hpp>
48 : #include <com/sun/star/sdbc/XRow.hpp>
49 : #include <com/sun/star/ucb/NameClash.hpp>
50 : #include <com/sun/star/ucb/NameClashException.hpp>
51 : #include <com/sun/star/ucb/TransferInfo.hpp>
52 : #include <com/sun/star/ucb/XCommandEnvironment.hpp>
53 : #include <com/sun/star/ucb/XContentAccess.hpp>
54 : #include <com/sun/star/frame/ModuleManager.hpp>
55 : #include <com/sun/star/uno/Exception.hpp>
56 :
57 : #include <svtools/templatefoldercache.hxx>
58 : #include <unotools/configmgr.hxx>
59 : #include <unotools/ucbhelper.hxx>
60 :
61 : #include "sfx2/sfxresid.hxx"
62 : #include "sfxurlrelocator.hxx"
63 : #include "doctemplateslocal.hxx"
64 : #include <sfx2/docfac.hxx>
65 : #include <sfx2/docfile.hxx>
66 : #include "doc.hrc"
67 :
68 : #include <vector>
69 :
70 : //-----------------------------------------------------------------------------
71 :
72 : //=============================================================================
73 :
74 : #define TEMPLATE_SERVICE_NAME "com.sun.star.frame.DocumentTemplates"
75 : #define TEMPLATE_IMPLEMENTATION_NAME "com.sun.star.comp.sfx2.DocumentTemplates"
76 :
77 : #define SERVICENAME_TYPEDETECTION "com.sun.star.document.TypeDetection"
78 :
79 : #define TEMPLATE_ROOT_URL "vnd.sun.star.hier:/templates"
80 : #define TITLE "Title"
81 : #define IS_FOLDER "IsFolder"
82 : #define IS_DOCUMENT "IsDocument"
83 : #define TARGET_URL "TargetURL"
84 : #define TEMPLATE_VERSION "TemplateComponentVersion"
85 : #define TEMPLATE_VERSION_VALUE "2"
86 : #define TYPE_FOLDER "application/vnd.sun.star.hier-folder"
87 : #define TYPE_LINK "application/vnd.sun.star.hier-link"
88 : #define TYPE_FSYS_FOLDER "application/vnd.sun.staroffice.fsys-folder"
89 : #define TYPE_FSYS_FILE "application/vnd.sun.staroffice.fsys-file"
90 :
91 : #define PROPERTY_DIRLIST "DirectoryList"
92 : #define PROPERTY_NEEDSUPDATE "NeedsUpdate"
93 : #define PROPERTY_TYPE "TypeDescription"
94 :
95 : #define TARGET_DIR_URL "TargetDirURL"
96 : #define COMMAND_DELETE "delete"
97 : #define COMMAND_TRANSFER "transfer"
98 :
99 : #define STANDARD_FOLDER "standard"
100 :
101 : #define C_DELIM ';'
102 :
103 : //=============================================================================
104 :
105 : using namespace ::com::sun::star;
106 : using namespace ::com::sun::star::beans;
107 : using namespace ::com::sun::star::document;
108 : using namespace ::com::sun::star::io;
109 : using namespace ::com::sun::star::lang;
110 : using namespace ::com::sun::star::sdbc;
111 : using namespace ::com::sun::star::ucb;
112 : using namespace ::com::sun::star::uno;
113 : using namespace ::com::sun::star::container;
114 : using namespace ::com::sun::star::util;
115 :
116 : using namespace ::rtl;
117 : using namespace ::ucbhelper;
118 : using namespace ::comphelper;
119 :
120 : using ::std::vector;
121 :
122 : //=============================================================================
123 :
124 : class WaitWindow_Impl : public WorkWindow
125 : {
126 : Rectangle _aRect;
127 : sal_uInt16 _nTextStyle;
128 : String _aText;
129 :
130 : public:
131 : WaitWindow_Impl();
132 : ~WaitWindow_Impl();
133 : virtual void Paint( const Rectangle& rRect );
134 : };
135 :
136 : #define X_OFFSET 15
137 : #define Y_OFFSET 15
138 :
139 : //=============================================================================
140 :
141 0 : struct NamePair_Impl
142 : {
143 : OUString maShortName;
144 : OUString maLongName;
145 : };
146 :
147 : class Updater_Impl;
148 : class DocTemplates_EntryData_Impl;
149 : class GroupData_Impl;
150 :
151 : typedef vector< NamePair_Impl* > NameList_Impl;
152 : typedef vector< GroupData_Impl* > GroupList_Impl;
153 :
154 : //=============================================================================
155 : #include <com/sun/star/task/InteractionHandler.hpp>
156 : #include <com/sun/star/ucb/XProgressHandler.hpp>
157 :
158 6 : class TplTaskEnvironment : public ::cppu::WeakImplHelper1< ucb::XCommandEnvironment >
159 : {
160 : uno::Reference< task::XInteractionHandler > m_xInteractionHandler;
161 : uno::Reference< ucb::XProgressHandler > m_xProgressHandler;
162 :
163 : public:
164 4 : TplTaskEnvironment( const uno::Reference< task::XInteractionHandler>& rxInteractionHandler )
165 4 : : m_xInteractionHandler( rxInteractionHandler )
166 4 : {}
167 :
168 0 : virtual uno::Reference<task::XInteractionHandler> SAL_CALL getInteractionHandler() throw (uno::RuntimeException)
169 0 : { return m_xInteractionHandler; }
170 :
171 0 : virtual uno::Reference<ucb::XProgressHandler> SAL_CALL getProgressHandler() throw (uno::RuntimeException)
172 0 : { return m_xProgressHandler; }
173 : };
174 :
175 : class SfxDocTplService_Impl
176 : {
177 : uno::Reference< XMultiServiceFactory > mxFactory;
178 : uno::Reference< XCommandEnvironment > maCmdEnv;
179 : uno::Reference<XDocumentProperties> m_xDocProps;
180 : uno::Reference< XTypeDetection > mxType;
181 :
182 : ::osl::Mutex maMutex;
183 : Sequence< OUString > maTemplateDirs;
184 : OUString maRootURL;
185 : NameList_Impl maNames;
186 : Locale maLocale;
187 : Content maRootContent;
188 : Updater_Impl* mpUpdater;
189 : sal_Bool mbIsInitialized : 1;
190 : sal_Bool mbLocaleSet : 1;
191 :
192 : SfxURLRelocator_Impl maRelocator;
193 :
194 : void init_Impl();
195 : void getDefaultLocale();
196 : void getDirList();
197 : void readFolderList();
198 : sal_Bool needsUpdate();
199 : OUString getLongName( const OUString& rShortName );
200 : sal_Bool setTitleForURL( const OUString& rURL, const OUString& aTitle );
201 : sal_Bool getTitleFromURL( const OUString& rURL, OUString& aTitle, OUString& aType, sal_Bool& bDocHasTitle );
202 :
203 : sal_Bool addEntry( Content& rParentFolder,
204 : const OUString& rTitle,
205 : const OUString& rTargetURL,
206 : const OUString& rType );
207 :
208 : sal_Bool createFolder( const OUString& rNewFolderURL,
209 : sal_Bool bCreateParent,
210 : sal_Bool bFsysFolder,
211 : Content &rNewFolder );
212 :
213 : sal_Bool CreateNewUniqueFolderWithPrefix( const ::rtl::OUString& aPath,
214 : const ::rtl::OUString& aPrefix,
215 : ::rtl::OUString& aNewFolderName,
216 : ::rtl::OUString& aNewFolderURL,
217 : Content& aNewFolder );
218 : ::rtl::OUString CreateNewUniqueFileWithPrefix( const ::rtl::OUString& aPath,
219 : const ::rtl::OUString& aPrefix,
220 : const ::rtl::OUString& aExt );
221 :
222 : uno::Sequence< beans::StringPair > ReadUINamesForTemplateDir_Impl( const ::rtl::OUString& aUserPath );
223 : sal_Bool UpdateUINamesForTemplateDir_Impl( const ::rtl::OUString& aUserPath,
224 : const ::rtl::OUString& aGroupName,
225 : const ::rtl::OUString& aNewFolderName );
226 : sal_Bool ReplaceUINamesForTemplateDir_Impl( const ::rtl::OUString& aUserPath,
227 : const ::rtl::OUString& aFsysGroupName,
228 : const ::rtl::OUString& aOldGroupName,
229 : const ::rtl::OUString& aNewGroupName );
230 : sal_Bool RemoveUINamesForTemplateDir_Impl( const ::rtl::OUString& aUserPath,
231 : const ::rtl::OUString& aGroupName );
232 : sal_Bool WriteUINamesForTemplateDir_Impl( const ::rtl::OUString& aUserPath,
233 : const uno::Sequence< beans::StringPair >& aUINames );
234 :
235 : ::rtl::OUString CreateNewGroupFsys( const ::rtl::OUString& rGroupName, Content& aGroup );
236 :
237 : sal_Bool removeContent( Content& rContent );
238 : sal_Bool removeContent( const OUString& rContentURL );
239 :
240 : sal_Bool setProperty( Content& rContent,
241 : const OUString& rPropName,
242 : const Any& rPropValue );
243 : sal_Bool getProperty( Content& rContent,
244 : const OUString& rPropName,
245 : Any& rPropValue );
246 :
247 : void createFromContent( GroupList_Impl& rList,
248 : Content &rContent,
249 : sal_Bool bHierarchy,
250 : sal_Bool bWriteableContent = sal_False );
251 : void addHierGroup( GroupList_Impl& rList,
252 : const OUString& rTitle,
253 : const OUString& rOwnURL );
254 : void addFsysGroup( GroupList_Impl& rList,
255 : const OUString& rTitle,
256 : const OUString& rUITitle,
257 : const OUString& rOwnURL,
258 : sal_Bool bWriteableGroup = sal_False );
259 : void removeFromHierarchy( DocTemplates_EntryData_Impl *pData );
260 : void addToHierarchy( GroupData_Impl *pGroup,
261 : DocTemplates_EntryData_Impl *pData );
262 :
263 : void removeFromHierarchy( GroupData_Impl *pGroup );
264 : void addGroupToHierarchy( GroupData_Impl *pGroup );
265 :
266 : void updateData( DocTemplates_EntryData_Impl *pData );
267 :
268 : public:
269 : SfxDocTplService_Impl( uno::Reference< XMultiServiceFactory > xFactory );
270 : ~SfxDocTplService_Impl();
271 :
272 4 : sal_Bool init() { if ( !mbIsInitialized ) init_Impl(); return mbIsInitialized; }
273 0 : Content getContent() const { return maRootContent; }
274 :
275 : void setLocale( const Locale & rLocale );
276 : Locale getLocale();
277 :
278 : sal_Bool storeTemplate( const OUString& rGroupName,
279 : const OUString& rTemplateName,
280 : const uno::Reference< XSTORABLE >& rStorable );
281 :
282 : sal_Bool addTemplate( const OUString& rGroupName,
283 : const OUString& rTemplateName,
284 : const OUString& rSourceURL );
285 : sal_Bool removeTemplate( const OUString& rGroupName,
286 : const OUString& rTemplateName );
287 : sal_Bool renameTemplate( const OUString& rGroupName,
288 : const OUString& rOldName,
289 : const OUString& rNewName );
290 :
291 : sal_Bool addGroup( const OUString& rGroupName );
292 : sal_Bool removeGroup( const OUString& rGroupName );
293 : sal_Bool renameGroup( const OUString& rOldName,
294 : const OUString& rNewName );
295 :
296 : void update( sal_Bool bUpdateNow );
297 : void doUpdate();
298 0 : void finished() { mpUpdater = NULL; }
299 : };
300 :
301 : //=============================================================================
302 :
303 : class Updater_Impl : public ::osl::Thread
304 : {
305 : private:
306 : SfxDocTplService_Impl *mpDocTemplates;
307 :
308 : public:
309 : Updater_Impl( SfxDocTplService_Impl* pTemplates );
310 : ~Updater_Impl();
311 :
312 : virtual void SAL_CALL run();
313 : virtual void SAL_CALL onTerminated();
314 : };
315 :
316 : //=============================================================================
317 :
318 0 : class DocTemplates_EntryData_Impl
319 : {
320 : OUString maTitle;
321 : OUString maType;
322 : OUString maTargetURL;
323 : OUString maHierarchyURL;
324 :
325 : sal_Bool mbInHierarchy : 1;
326 : sal_Bool mbInUse : 1;
327 : sal_Bool mbUpdateType : 1;
328 : sal_Bool mbUpdateLink : 1;
329 :
330 : public:
331 : DocTemplates_EntryData_Impl( const OUString& rTitle );
332 :
333 0 : void setInUse() { mbInUse = sal_True; }
334 0 : void setHierarchy( sal_Bool bInHierarchy ) { mbInHierarchy = bInHierarchy; }
335 0 : void setUpdateLink( sal_Bool bUpdateLink ) { mbUpdateLink = bUpdateLink; }
336 0 : void setUpdateType( sal_Bool bUpdateType ) { mbUpdateType = bUpdateType; }
337 :
338 0 : sal_Bool getInUse() const { return mbInUse; }
339 0 : sal_Bool getInHierarchy() const { return mbInHierarchy; }
340 0 : sal_Bool getUpdateLink() const { return mbUpdateLink; }
341 0 : sal_Bool getUpdateType() const { return mbUpdateType; }
342 :
343 0 : const OUString& getHierarchyURL() const { return maHierarchyURL; }
344 0 : const OUString& getTargetURL() const { return maTargetURL; }
345 0 : const OUString& getTitle() const { return maTitle; }
346 0 : const OUString& getType() const { return maType; }
347 :
348 0 : void setHierarchyURL( const OUString& rURL ) { maHierarchyURL = rURL; }
349 0 : void setTargetURL( const OUString& rURL ) { maTargetURL = rURL; }
350 0 : void setType( const OUString& rType ) { maType = rType; }
351 : };
352 :
353 : //=============================================================================
354 :
355 : class GroupData_Impl
356 : {
357 : vector< DocTemplates_EntryData_Impl* > maEntries;
358 : OUString maTitle;
359 : OUString maHierarchyURL;
360 : OUString maTargetURL;
361 : sal_Bool mbInUse : 1;
362 : sal_Bool mbInHierarchy : 1;
363 :
364 : public:
365 : GroupData_Impl( const OUString& rTitle );
366 : ~GroupData_Impl();
367 :
368 0 : void setInUse() { mbInUse = sal_True; }
369 0 : void setHierarchy( sal_Bool bInHierarchy ) { mbInHierarchy = bInHierarchy; }
370 0 : void setHierarchyURL( const OUString& rURL ) { maHierarchyURL = rURL; }
371 0 : void setTargetURL( const OUString& rURL ) { maTargetURL = rURL; }
372 :
373 0 : sal_Bool getInUse() const { return mbInUse; }
374 0 : sal_Bool getInHierarchy() const { return mbInHierarchy; }
375 0 : const OUString& getHierarchyURL() const { return maHierarchyURL; }
376 0 : const OUString& getTargetURL() const { return maTargetURL; }
377 0 : const OUString& getTitle() const { return maTitle; }
378 :
379 : DocTemplates_EntryData_Impl* addEntry( const OUString& rTitle,
380 : const OUString& rTargetURL,
381 : const OUString& rType,
382 : const OUString& rHierURL );
383 0 : size_t count() { return maEntries.size(); }
384 0 : DocTemplates_EntryData_Impl* getEntry( size_t nPos ) { return maEntries[ nPos ]; }
385 : };
386 :
387 : //-----------------------------------------------------------------------------
388 : // private SfxDocTplService_Impl
389 : //-----------------------------------------------------------------------------
390 4 : void SfxDocTplService_Impl::init_Impl()
391 : {
392 4 : uno::Reference< uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
393 : uno::Reference < task::XInteractionHandler > xInteractionHandler(
394 4 : task::InteractionHandler::createWithParent(xContext, 0), uno::UNO_QUERY_THROW );
395 4 : maCmdEnv = new TplTaskEnvironment( xInteractionHandler );
396 :
397 4 : ::osl::ClearableMutexGuard aGuard( maMutex );
398 4 : sal_Bool bIsInitialized = sal_False;
399 4 : sal_Bool bNeedsUpdate = sal_False;
400 :
401 4 : if ( !mbLocaleSet )
402 0 : getDefaultLocale();
403 :
404 : // convert locale to string
405 4 : OUString aLang = maLocale.Language;
406 4 : aLang += OUString( '-' );
407 4 : aLang += maLocale.Country;
408 :
409 : // set maRootContent to the root of the templates hierarchy. Create the
410 : // entry if necessary
411 :
412 4 : maRootURL = OUString( TEMPLATE_ROOT_URL );
413 4 : maRootURL += OUString( '/' );
414 4 : maRootURL += aLang;
415 :
416 4 : ::rtl::OUString aTemplVersPropName( TEMPLATE_VERSION );
417 4 : ::rtl::OUString aTemplVers( TEMPLATE_VERSION_VALUE );
418 4 : if ( Content::create( maRootURL, maCmdEnv, comphelper::getProcessComponentContext(), maRootContent ) )
419 : {
420 0 : uno::Any aValue;
421 0 : ::rtl::OUString aPropValue;
422 0 : if ( getProperty( maRootContent, aTemplVersPropName, aValue )
423 0 : && ( aValue >>= aPropValue )
424 0 : && aPropValue.equals( aTemplVers ) )
425 : {
426 0 : bIsInitialized = sal_True;
427 : }
428 : else
429 0 : removeContent( maRootContent );
430 : }
431 :
432 4 : if ( !bIsInitialized )
433 : {
434 8 : if ( createFolder( maRootURL, sal_True, sal_False, maRootContent )
435 4 : && setProperty( maRootContent, aTemplVersPropName, uno::makeAny( aTemplVers ) ) )
436 0 : bIsInitialized = sal_True;
437 :
438 4 : bNeedsUpdate = sal_True;
439 : }
440 :
441 4 : if ( bIsInitialized )
442 : {
443 : try {
444 : m_xDocProps.set(document::DocumentProperties::create(
445 0 : ::comphelper::getProcessComponentContext()));
446 0 : } catch (uno::RuntimeException const& e) {
447 : SAL_WARN("sfx2.doc", "SfxDocTplService_Impl::init_Impl: "
448 : "cannot create DocumentProperties service:" << e.Message);
449 : }
450 :
451 0 : OUString const aService = OUString( SERVICENAME_TYPEDETECTION );
452 0 : mxType = uno::Reference< XTypeDetection > ( mxFactory->createInstance( aService ), UNO_QUERY );
453 :
454 0 : getDirList();
455 0 : readFolderList();
456 :
457 0 : if ( bNeedsUpdate )
458 : {
459 0 : aGuard.clear();
460 0 : SolarMutexClearableGuard aSolarGuard;
461 :
462 0 : WaitWindow_Impl* pWin = new WaitWindow_Impl();
463 :
464 0 : aSolarGuard.clear();
465 0 : ::osl::ClearableMutexGuard anotherGuard( maMutex );
466 :
467 0 : update( sal_True );
468 :
469 0 : anotherGuard.clear();
470 0 : SolarMutexGuard aSecondSolarGuard;
471 :
472 0 : delete pWin;
473 : }
474 0 : else if ( needsUpdate() )
475 : // the UI should be shown only on the first update
476 0 : update( sal_True );
477 : }
478 : else
479 : {
480 : SAL_WARN( "sfx2.doc", "init_Impl(): Could not create root" );
481 : }
482 :
483 4 : mbIsInitialized = bIsInitialized;
484 4 : }
485 :
486 : //-----------------------------------------------------------------------------
487 4 : void SfxDocTplService_Impl::getDefaultLocale()
488 : {
489 4 : if ( !mbLocaleSet )
490 : {
491 4 : ::osl::MutexGuard aGuard( maMutex );
492 4 : if ( !mbLocaleSet )
493 : {
494 4 : rtl::OUString aLocale( utl::ConfigManager::getLocale() );
495 4 : if ( !aLocale.isEmpty() )
496 : {
497 0 : sal_Int32 nPos = aLocale.indexOf( sal_Unicode( '-' ) );
498 0 : if ( nPos != -1 )
499 : {
500 0 : maLocale.Language = aLocale.copy( 0, nPos );
501 0 : nPos = aLocale.indexOf( sal_Unicode( '_' ), nPos + 1 );
502 0 : if ( nPos != -1 )
503 : {
504 : maLocale.Country
505 0 : = aLocale.copy( maLocale.Language.getLength() + 1,
506 0 : nPos - maLocale.Language.getLength() - 1 );
507 : maLocale.Variant
508 0 : = aLocale.copy( nPos + 1 );
509 : }
510 : else
511 : {
512 : maLocale.Country
513 0 : = aLocale.copy( maLocale.Language.getLength() + 1 );
514 : }
515 : }
516 :
517 : }
518 :
519 4 : mbLocaleSet = sal_True;
520 4 : }
521 : }
522 4 : }
523 :
524 : // -----------------------------------------------------------------------
525 0 : void SfxDocTplService_Impl::readFolderList()
526 : {
527 0 : SolarMutexGuard aGuard;
528 :
529 0 : ResStringArray aShortNames( SfxResId( TEMPLATE_SHORT_NAMES_ARY ) );
530 0 : ResStringArray aLongNames( SfxResId( TEMPLATE_LONG_NAMES_ARY ) );
531 :
532 : NamePair_Impl* pPair;
533 :
534 0 : sal_uInt16 nCount = (sal_uInt16)( Min( aShortNames.Count(), aLongNames.Count() ) );
535 :
536 0 : for ( sal_uInt16 i=0; i<nCount; i++ )
537 : {
538 0 : pPair = new NamePair_Impl;
539 0 : pPair->maShortName = aShortNames.GetString( i );
540 0 : pPair->maLongName = aLongNames.GetString( i );
541 :
542 0 : maNames.push_back( pPair );
543 0 : }
544 0 : }
545 :
546 : // -----------------------------------------------------------------------
547 0 : OUString SfxDocTplService_Impl::getLongName( const OUString& rShortName )
548 : {
549 0 : OUString aRet;
550 :
551 0 : for ( size_t i = 0, n = maNames.size(); i < n; ++i )
552 : {
553 0 : NamePair_Impl* pPair = maNames[ i ];
554 0 : if ( pPair->maShortName == rShortName )
555 : {
556 0 : aRet = pPair->maLongName;
557 0 : break;
558 : }
559 : }
560 :
561 0 : if ( aRet.isEmpty() )
562 0 : aRet = rShortName;
563 :
564 0 : return aRet;
565 : }
566 :
567 : //-----------------------------------------------------------------------------
568 0 : void SfxDocTplService_Impl::getDirList()
569 : {
570 0 : OUString aPropName( PROPERTY_DIRLIST );
571 0 : Any aValue;
572 :
573 : // Get the template dir list
574 : // TODO/LATER: let use service, register listener
575 0 : INetURLObject aURL;
576 0 : String aDirs = SvtPathOptions().GetTemplatePath();
577 0 : sal_uInt16 nCount = comphelper::string::getTokenCount(aDirs, C_DELIM);
578 :
579 0 : maTemplateDirs = Sequence< OUString >( nCount );
580 :
581 : uno::Reference< XComponentContext > xCtx(
582 0 : comphelper::getComponentContext( mxFactory ) );
583 0 : uno::Reference< util::XMacroExpander > xExpander;
584 : const rtl::OUString aPrefix(
585 0 : "vnd.sun.star.expand:" );
586 :
587 0 : xCtx->getValueByName(
588 0 : rtl::OUString( "/singletons/com.sun.star.util.theMacroExpander" ) )
589 0 : >>= xExpander;
590 :
591 : OSL_ENSURE( xExpander.is(),
592 : "Unable to obtain macro expander singleton!" );
593 :
594 0 : for ( sal_uInt16 i=0; i<nCount; i++ )
595 : {
596 0 : aURL.SetSmartProtocol( INET_PROT_FILE );
597 0 : aURL.SetURL( aDirs.GetToken( i, C_DELIM ) );
598 0 : maTemplateDirs[i] = aURL.GetMainURL( INetURLObject::NO_DECODE );
599 :
600 0 : sal_Int32 nIndex = maTemplateDirs[i].indexOf( aPrefix );
601 0 : if ( nIndex != -1 && xExpander.is() )
602 : {
603 0 : maTemplateDirs[i] = maTemplateDirs[i].replaceAt(nIndex,
604 : aPrefix.getLength(),
605 0 : rtl::OUString());
606 0 : maTemplateDirs[i] = xExpander->expandMacros( maTemplateDirs[i] );
607 : }
608 : }
609 :
610 0 : aValue <<= maTemplateDirs;
611 :
612 : // Store the template dir list
613 0 : setProperty( maRootContent, aPropName, aValue );
614 0 : }
615 :
616 : //-----------------------------------------------------------------------------
617 0 : sal_Bool SfxDocTplService_Impl::needsUpdate()
618 : {
619 0 : OUString aPropName( PROPERTY_NEEDSUPDATE );
620 0 : sal_Bool bNeedsUpdate = sal_True;
621 0 : Any aValue;
622 :
623 : // Get the template dir list
624 0 : sal_Bool bHasProperty = getProperty( maRootContent, aPropName, aValue );
625 :
626 0 : if ( bHasProperty )
627 0 : aValue >>= bNeedsUpdate;
628 :
629 : // the old template component also checks this state, but it is initialized from this component
630 : // so if this componend was already updated the old component does not need such an update
631 0 : ::svt::TemplateFolderCache aTempCache;
632 0 : if ( !bNeedsUpdate )
633 0 : bNeedsUpdate = aTempCache.needsUpdate();
634 :
635 0 : if ( bNeedsUpdate )
636 0 : aTempCache.storeState();
637 :
638 0 : return bNeedsUpdate;
639 : }
640 :
641 : // -----------------------------------------------------------------------
642 0 : sal_Bool SfxDocTplService_Impl::setTitleForURL( const OUString& rURL, const OUString& aTitle )
643 : {
644 0 : if (m_xDocProps.is())
645 : {
646 : try
647 : {
648 0 : m_xDocProps->loadFromMedium(rURL, Sequence<PropertyValue>());
649 0 : m_xDocProps->setTitle(aTitle );
650 0 : m_xDocProps->storeToMedium(rURL, Sequence<PropertyValue>());
651 0 : return true;
652 : }
653 0 : catch ( Exception& )
654 : {
655 : }
656 : }
657 0 : return false;
658 : }
659 :
660 : // -----------------------------------------------------------------------
661 0 : sal_Bool SfxDocTplService_Impl::getTitleFromURL( const OUString& rURL, OUString& aTitle, OUString& aType, sal_Bool& bDocHasTitle )
662 : {
663 0 : bDocHasTitle = sal_False;
664 :
665 0 : if (m_xDocProps.is())
666 : {
667 : try
668 : {
669 0 : m_xDocProps->loadFromMedium(rURL, Sequence<PropertyValue>());
670 0 : aTitle = m_xDocProps->getTitle();
671 : }
672 0 : catch ( Exception& )
673 : {
674 : }
675 : }
676 :
677 0 : if ( aType.isEmpty() && mxType.is() )
678 : {
679 0 : ::rtl::OUString aDocType = mxType->queryTypeByURL( rURL );
680 0 : if ( !aDocType.isEmpty() )
681 : try
682 : {
683 0 : uno::Reference< container::XNameAccess > xTypeDetection( mxType, uno::UNO_QUERY_THROW );
684 0 : SequenceAsHashMap aTypeProps( xTypeDetection->getByName( aDocType ) );
685 : aType = aTypeProps.getUnpackedValueOrDefault(
686 : ::rtl::OUString("MediaType"),
687 0 : ::rtl::OUString() );
688 : }
689 0 : catch( uno::Exception& )
690 0 : {}
691 : }
692 :
693 0 : if ( aTitle.isEmpty() )
694 : {
695 0 : INetURLObject aURL( rURL );
696 0 : aURL.CutExtension();
697 : aTitle = aURL.getName( INetURLObject::LAST_SEGMENT, true,
698 0 : INetURLObject::DECODE_WITH_CHARSET );
699 : }
700 : else
701 0 : bDocHasTitle = sal_True;
702 :
703 0 : return sal_True;
704 : }
705 :
706 : // -----------------------------------------------------------------------
707 0 : sal_Bool SfxDocTplService_Impl::addEntry( Content& rParentFolder,
708 : const OUString& rTitle,
709 : const OUString& rTargetURL,
710 : const OUString& rType )
711 : {
712 0 : sal_Bool bAddedEntry = sal_False;
713 :
714 0 : INetURLObject aLinkObj( rParentFolder.getURL() );
715 : aLinkObj.insertName( rTitle, false,
716 : INetURLObject::LAST_SEGMENT, true,
717 0 : INetURLObject::ENCODE_ALL );
718 0 : OUString aLinkURL = aLinkObj.GetMainURL( INetURLObject::NO_DECODE );
719 :
720 0 : Content aLink;
721 :
722 0 : if ( ! Content::create( aLinkURL, maCmdEnv, comphelper::getProcessComponentContext(), aLink ) )
723 : {
724 0 : Sequence< OUString > aNames(3);
725 0 : aNames[0] = OUString( TITLE );
726 0 : aNames[1] = OUString( IS_FOLDER );
727 0 : aNames[2] = OUString( TARGET_URL );
728 :
729 0 : Sequence< Any > aValues(3);
730 0 : aValues[0] = makeAny( rTitle );
731 0 : aValues[1] = makeAny( sal_Bool( sal_False ) );
732 0 : aValues[2] = makeAny( rTargetURL );
733 :
734 0 : OUString aType( TYPE_LINK );
735 0 : OUString aAdditionalProp( PROPERTY_TYPE );
736 :
737 : try
738 : {
739 0 : rParentFolder.insertNewContent( aType, aNames, aValues, aLink );
740 0 : setProperty( aLink, aAdditionalProp, makeAny( rType ) );
741 0 : bAddedEntry = sal_True;
742 : }
743 0 : catch( Exception& )
744 0 : {}
745 : }
746 0 : return bAddedEntry;
747 : }
748 :
749 : // -----------------------------------------------------------------------
750 8 : sal_Bool SfxDocTplService_Impl::createFolder( const OUString& rNewFolderURL,
751 : sal_Bool bCreateParent,
752 : sal_Bool bFsysFolder,
753 : Content &rNewFolder )
754 : {
755 8 : Content aParent;
756 8 : sal_Bool bCreatedFolder = sal_False;
757 8 : INetURLObject aParentURL( rNewFolderURL );
758 : OUString aFolderName = aParentURL.getName( INetURLObject::LAST_SEGMENT, true,
759 8 : INetURLObject::DECODE_WITH_CHARSET );
760 :
761 : // compute the parent folder url from the new folder url
762 : // and remove the final slash, because Content::create doesn't
763 : // like it
764 8 : aParentURL.removeSegment();
765 8 : if ( aParentURL.getSegmentCount() >= 1 )
766 4 : aParentURL.removeFinalSlash();
767 :
768 : // if the parent exists, we can continue with the creation of the
769 : // new folder, we have to create the parent otherwise ( as long as
770 : // bCreateParent is set to true )
771 8 : if ( Content::create( aParentURL.GetMainURL( INetURLObject::NO_DECODE ), maCmdEnv, comphelper::getProcessComponentContext(), aParent ) )
772 : {
773 : try
774 : {
775 0 : Sequence< OUString > aNames(2);
776 0 : aNames[0] = OUString( TITLE );
777 0 : aNames[1] = OUString( IS_FOLDER );
778 :
779 0 : Sequence< Any > aValues(2);
780 0 : aValues[0] = makeAny( aFolderName );
781 0 : aValues[1] = makeAny( sal_Bool( sal_True ) );
782 :
783 0 : OUString aType;
784 :
785 0 : if ( bFsysFolder )
786 0 : aType = OUString( TYPE_FSYS_FOLDER );
787 : else
788 0 : aType = OUString( TYPE_FOLDER );
789 :
790 0 : aParent.insertNewContent( aType, aNames, aValues, rNewFolder );
791 0 : bCreatedFolder = sal_True;
792 : }
793 0 : catch( RuntimeException& )
794 : {
795 : SAL_WARN( "sfx2.doc", "createFolder(): got runtime exception" );
796 : }
797 0 : catch( Exception& )
798 : {
799 : SAL_WARN( "sfx2.doc", "createFolder(): Could not create new folder" );
800 : }
801 : }
802 8 : else if ( bCreateParent )
803 : {
804 : // if the parent doesn't exists and bCreateParent is set to true,
805 : // we try to create the parent and if this was successful, we
806 : // try to create the new folder again ( but this time, we set
807 : // bCreateParent to false to avoid endless recusions )
808 24 : if ( ( aParentURL.getSegmentCount() >= 1 ) &&
809 16 : createFolder( aParentURL.GetMainURL( INetURLObject::NO_DECODE ), bCreateParent, bFsysFolder, aParent ) )
810 : {
811 0 : bCreatedFolder = createFolder( rNewFolderURL, sal_False, bFsysFolder, rNewFolder );
812 : }
813 : }
814 :
815 8 : return bCreatedFolder;
816 : }
817 :
818 : // -----------------------------------------------------------------------
819 0 : sal_Bool SfxDocTplService_Impl::CreateNewUniqueFolderWithPrefix( const ::rtl::OUString& aPath,
820 : const ::rtl::OUString& aPrefix,
821 : ::rtl::OUString& aNewFolderName,
822 : ::rtl::OUString& aNewFolderURL,
823 : Content& aNewFolder )
824 : {
825 0 : sal_Bool bCreated = sal_False;
826 0 : INetURLObject aDirPath( aPath );
827 :
828 0 : Content aParent;
829 0 : uno::Reference< XCommandEnvironment > aQuietEnv;
830 0 : if ( Content::create( aDirPath.GetMainURL( INetURLObject::NO_DECODE ), aQuietEnv, comphelper::getProcessComponentContext(), aParent ) )
831 : {
832 0 : for ( sal_Int32 nInd = 0; nInd < 32000; nInd++ )
833 : {
834 0 : ::rtl::OUString aTryName = aPrefix;
835 0 : if ( nInd )
836 0 : aTryName += ::rtl::OUString::valueOf( nInd );
837 :
838 : try
839 : {
840 0 : Sequence< OUString > aNames(2);
841 0 : aNames[0] = OUString( TITLE );
842 0 : aNames[1] = OUString( IS_FOLDER );
843 :
844 0 : Sequence< Any > aValues(2);
845 0 : aValues[0] = makeAny( aTryName );
846 0 : aValues[1] = makeAny( sal_Bool( sal_True ) );
847 :
848 0 : OUString aType( TYPE_FSYS_FOLDER );
849 :
850 0 : bCreated = aParent.insertNewContent( aType, aNames, aValues, aNewFolder );
851 : }
852 0 : catch( ucb::NameClashException& )
853 : {
854 : // if there is already an element, retry
855 : }
856 0 : catch( Exception& )
857 : {
858 0 : INetURLObject aObjPath( aDirPath );
859 : aObjPath.insertName( aTryName, false,
860 : INetURLObject::LAST_SEGMENT, true,
861 0 : INetURLObject::ENCODE_ALL );
862 : // if there is already an element, retry
863 : // if there was another error, do not try any more
864 0 : if ( !::utl::UCBContentHelper::Exists( aObjPath.GetMainURL( INetURLObject::NO_DECODE ) ) )
865 0 : break;
866 : }
867 :
868 0 : if ( bCreated )
869 : {
870 0 : aNewFolderName = aTryName;
871 0 : aNewFolderURL = aNewFolder.get()->getIdentifier()->getContentIdentifier();
872 : break;
873 : }
874 0 : }
875 : }
876 :
877 0 : return bCreated;
878 : }
879 :
880 : // -----------------------------------------------------------------------
881 0 : ::rtl::OUString SfxDocTplService_Impl::CreateNewUniqueFileWithPrefix( const ::rtl::OUString& aPath,
882 : const ::rtl::OUString& aPrefix,
883 : const ::rtl::OUString& aExt )
884 : {
885 0 : ::rtl::OUString aNewFileURL;
886 0 : INetURLObject aDirPath( aPath );
887 :
888 0 : Content aParent;
889 :
890 0 : uno::Reference< XCommandEnvironment > aQuietEnv;
891 0 : if ( Content::create( aDirPath.GetMainURL( INetURLObject::NO_DECODE ), aQuietEnv, comphelper::getProcessComponentContext(), aParent ) )
892 : {
893 0 : for ( sal_Int32 nInd = 0; nInd < 32000; nInd++ )
894 : {
895 0 : Content aNewFile;
896 0 : sal_Bool bCreated = sal_False;
897 0 : ::rtl::OUString aTryName = aPrefix;
898 0 : if ( nInd )
899 0 : aTryName += ::rtl::OUString::valueOf( nInd );
900 0 : if ( aExt.toChar() != '.' )
901 0 : aTryName += ::rtl::OUString( "." );
902 0 : aTryName += aExt;
903 :
904 : try
905 : {
906 0 : Sequence< OUString > aNames(2);
907 0 : aNames[0] = OUString( TITLE );
908 0 : aNames[1] = OUString( IS_DOCUMENT );
909 :
910 0 : Sequence< Any > aValues(2);
911 0 : aValues[0] = makeAny( aTryName );
912 0 : aValues[1] = makeAny( sal_Bool( sal_True ) );
913 :
914 0 : OUString aType( TYPE_FSYS_FILE );
915 :
916 0 : bCreated = aParent.insertNewContent( aType, aNames, aValues, aNewFile );
917 : }
918 0 : catch( ucb::NameClashException& )
919 : {
920 : // if there is already an element, retry
921 : }
922 0 : catch( Exception& )
923 : {
924 0 : INetURLObject aObjPath( aPath );
925 : aObjPath.insertName( aTryName, false,
926 : INetURLObject::LAST_SEGMENT, true,
927 0 : INetURLObject::ENCODE_ALL );
928 : // if there is already an element, retry
929 : // if there was another error, do not try any more
930 0 : if ( !::utl::UCBContentHelper::Exists( aObjPath.GetMainURL( INetURLObject::NO_DECODE ) ) )
931 0 : break;
932 : }
933 :
934 0 : if ( bCreated )
935 : {
936 0 : aNewFileURL = aNewFile.get()->getIdentifier()->getContentIdentifier();
937 : break;
938 : }
939 0 : }
940 : }
941 :
942 0 : return aNewFileURL;
943 : }
944 :
945 : // -----------------------------------------------------------------------
946 0 : sal_Bool SfxDocTplService_Impl::removeContent( Content& rContent )
947 : {
948 0 : sal_Bool bRemoved = sal_False;
949 : try
950 : {
951 0 : OUString aCmd( COMMAND_DELETE );
952 0 : Any aArg = makeAny( sal_Bool( sal_True ) );
953 :
954 0 : rContent.executeCommand( aCmd, aArg );
955 0 : bRemoved = sal_True;
956 : }
957 0 : catch ( RuntimeException& ) {}
958 0 : catch ( Exception& ) {}
959 :
960 0 : return bRemoved;
961 : }
962 :
963 : // -----------------------------------------------------------------------
964 0 : sal_Bool SfxDocTplService_Impl::removeContent( const OUString& rContentURL )
965 : {
966 0 : Content aContent;
967 :
968 0 : if ( Content::create( rContentURL, maCmdEnv, comphelper::getProcessComponentContext(), aContent ) )
969 0 : return removeContent( aContent );
970 : else
971 0 : return sal_False;
972 : }
973 :
974 : // -----------------------------------------------------------------------
975 0 : sal_Bool SfxDocTplService_Impl::setProperty( Content& rContent,
976 : const OUString& rPropName,
977 : const Any& rPropValue )
978 : {
979 0 : sal_Bool bPropertySet = sal_False;
980 :
981 : // Store the property
982 : try
983 : {
984 0 : Any aPropValue( rPropValue );
985 0 : uno::Reference< XPropertySetInfo > aPropInfo = rContent.getProperties();
986 :
987 : // check, whether or not the property exists, create it, when not
988 0 : if ( !aPropInfo.is() || !aPropInfo->hasPropertyByName( rPropName ) )
989 : {
990 0 : uno::Reference< XPropertyContainer > xProperties( rContent.get(), UNO_QUERY );
991 0 : if ( xProperties.is() )
992 : {
993 : try
994 : {
995 0 : xProperties->addProperty( rPropName, PropertyAttribute::MAYBEVOID, rPropValue );
996 : }
997 0 : catch( PropertyExistException& ) {}
998 0 : catch( IllegalTypeException& ) {
999 : SAL_WARN( "sfx2.doc", "IllegalTypeException" );
1000 : }
1001 0 : catch( IllegalArgumentException& ) {
1002 : SAL_WARN( "sfx2.doc", "IllegalArgumentException" );
1003 : }
1004 0 : }
1005 : }
1006 :
1007 : // To ensure a reloctable office installation, the path to the
1008 : // office installtion directory must never be stored directly.
1009 0 : if ( SfxURLRelocator_Impl::propertyCanContainOfficeDir( rPropName ) )
1010 : {
1011 0 : OUString aValue;
1012 0 : if ( rPropValue >>= aValue )
1013 : {
1014 0 : maRelocator.makeRelocatableURL( aValue );
1015 0 : aPropValue = makeAny( aValue );
1016 : }
1017 : else
1018 : {
1019 0 : Sequence< OUString > aValues;
1020 0 : if ( rPropValue >>= aValues )
1021 : {
1022 0 : for ( sal_Int32 n = 0; n < aValues.getLength(); n++ )
1023 : {
1024 0 : maRelocator.makeRelocatableURL( aValues[ n ] );
1025 : }
1026 0 : aPropValue = makeAny( aValues );
1027 : }
1028 : else
1029 : {
1030 : OSL_FAIL( "Unsupported property value type" );
1031 0 : }
1032 0 : }
1033 : }
1034 :
1035 : // now set the property
1036 :
1037 0 : rContent.setPropertyValue( rPropName, aPropValue );
1038 0 : bPropertySet = sal_True;
1039 : }
1040 0 : catch ( RuntimeException& ) {}
1041 0 : catch ( Exception& ) {}
1042 :
1043 0 : return bPropertySet;
1044 : }
1045 :
1046 : // -----------------------------------------------------------------------
1047 0 : sal_Bool SfxDocTplService_Impl::getProperty( Content& rContent,
1048 : const OUString& rPropName,
1049 : Any& rPropValue )
1050 : {
1051 0 : sal_Bool bGotProperty = sal_False;
1052 :
1053 : // Get the property
1054 : try
1055 : {
1056 0 : uno::Reference< XPropertySetInfo > aPropInfo = rContent.getProperties();
1057 :
1058 : // check, whether or not the property exists
1059 0 : if ( !aPropInfo.is() || !aPropInfo->hasPropertyByName( rPropName ) )
1060 : {
1061 0 : return sal_False;
1062 : }
1063 :
1064 : // now get the property
1065 :
1066 0 : rPropValue = rContent.getPropertyValue( rPropName );
1067 :
1068 : // To ensure a reloctable office installation, the path to the
1069 : // office installtion directory must never be stored directly.
1070 0 : if ( SfxURLRelocator_Impl::propertyCanContainOfficeDir( rPropName ) )
1071 : {
1072 0 : OUString aValue;
1073 0 : if ( rPropValue >>= aValue )
1074 : {
1075 0 : maRelocator.makeAbsoluteURL( aValue );
1076 0 : rPropValue = makeAny( aValue );
1077 : }
1078 : else
1079 : {
1080 0 : Sequence< OUString > aValues;
1081 0 : if ( rPropValue >>= aValues )
1082 : {
1083 0 : for ( sal_Int32 n = 0; n < aValues.getLength(); n++ )
1084 : {
1085 0 : maRelocator.makeAbsoluteURL( aValues[ n ] );
1086 : }
1087 0 : rPropValue = makeAny( aValues );
1088 : }
1089 : else
1090 : {
1091 : OSL_FAIL( "Unsupported property value type" );
1092 0 : }
1093 0 : }
1094 : }
1095 :
1096 0 : bGotProperty = sal_True;
1097 : }
1098 0 : catch ( RuntimeException& ) {}
1099 0 : catch ( Exception& ) {}
1100 :
1101 0 : return bGotProperty;
1102 : }
1103 :
1104 : // -----------------------------------------------------------------------
1105 : // static
1106 0 : bool SfxURLRelocator_Impl::propertyCanContainOfficeDir(
1107 : const rtl::OUString & rPropName )
1108 : {
1109 : // Note: TargetURL is handled by UCB itself (because it is a property
1110 : // with a predefined semantic). Additional Core properties introduced
1111 : // be a client app must be handled by the client app itself, because
1112 : // the UCB does not know the semantics of those properties.
1113 0 : return ( rPropName == TARGET_DIR_URL || rPropName == PROPERTY_DIRLIST );
1114 : }
1115 :
1116 : //-----------------------------------------------------------------------------
1117 : // public SfxDocTplService_Impl
1118 : //-----------------------------------------------------------------------------
1119 :
1120 4 : SfxDocTplService_Impl::SfxDocTplService_Impl( uno::Reference< XMultiServiceFactory > xFactory )
1121 4 : : maRelocator( xFactory )
1122 : {
1123 4 : mxFactory = xFactory;
1124 4 : mpUpdater = NULL;
1125 4 : mbIsInitialized = sal_False;
1126 4 : mbLocaleSet = sal_False;
1127 4 : }
1128 :
1129 : //-----------------------------------------------------------------------------
1130 6 : SfxDocTplService_Impl::~SfxDocTplService_Impl()
1131 : {
1132 3 : ::osl::MutexGuard aGuard( maMutex );
1133 :
1134 3 : if ( mpUpdater )
1135 : {
1136 0 : mpUpdater->terminate();
1137 0 : mpUpdater->join();
1138 0 : delete mpUpdater;
1139 : }
1140 :
1141 3 : for ( size_t i = 0, n = maNames.size(); i < n; ++i )
1142 0 : delete maNames[ i ];
1143 3 : maNames.clear();
1144 3 : }
1145 :
1146 : //-----------------------------------------------------------------------------
1147 4 : Locale SfxDocTplService_Impl::getLocale()
1148 : {
1149 4 : ::osl::MutexGuard aGuard( maMutex );
1150 :
1151 4 : if ( !mbLocaleSet )
1152 4 : getDefaultLocale();
1153 :
1154 4 : return maLocale;
1155 : }
1156 :
1157 : //-----------------------------------------------------------------------------
1158 0 : void SfxDocTplService_Impl::setLocale( const Locale &rLocale )
1159 : {
1160 0 : ::osl::MutexGuard aGuard( maMutex );
1161 :
1162 0 : if ( mbLocaleSet &&
1163 0 : ( maLocale.Language != rLocale.Language ) &&
1164 0 : ( maLocale.Country != rLocale.Country ) )
1165 0 : mbIsInitialized = sal_False;
1166 :
1167 0 : maLocale = rLocale;
1168 0 : mbLocaleSet = sal_True;
1169 0 : }
1170 :
1171 : //-----------------------------------------------------------------------------
1172 0 : void SfxDocTplService_Impl::update( sal_Bool bUpdateNow )
1173 : {
1174 0 : ::osl::MutexGuard aGuard( maMutex );
1175 :
1176 0 : if ( bUpdateNow )
1177 0 : doUpdate();
1178 : else
1179 : {
1180 0 : mpUpdater = new Updater_Impl( this );
1181 0 : mpUpdater->create();
1182 0 : }
1183 0 : }
1184 :
1185 : //-----------------------------------------------------------------------------
1186 0 : void SfxDocTplService_Impl::doUpdate()
1187 : {
1188 0 : ::osl::MutexGuard aGuard( maMutex );
1189 :
1190 0 : OUString aPropName( PROPERTY_NEEDSUPDATE );
1191 0 : Any aValue;
1192 :
1193 0 : aValue <<= sal_True;
1194 0 : setProperty( maRootContent, aPropName, aValue );
1195 :
1196 0 : GroupList_Impl aGroupList;
1197 :
1198 : // get the entries from the hierarchy
1199 0 : createFromContent( aGroupList, maRootContent, sal_True );
1200 :
1201 : // get the entries from the template directories
1202 0 : sal_Int32 nCountDir = maTemplateDirs.getLength();
1203 0 : OUString* pDirs = maTemplateDirs.getArray();
1204 0 : Content aDirContent;
1205 :
1206 : // the last directory in the list must be writable
1207 0 : sal_Bool bWriteableDirectory = sal_True;
1208 :
1209 : // the target folder might not exist, for this reason no interaction handler should be used
1210 0 : uno::Reference< XCommandEnvironment > aQuietEnv;
1211 :
1212 0 : while ( nCountDir )
1213 : {
1214 0 : nCountDir--;
1215 0 : if ( Content::create( pDirs[ nCountDir ], aQuietEnv, comphelper::getProcessComponentContext(), aDirContent ) )
1216 : {
1217 0 : createFromContent( aGroupList, aDirContent, sal_False, bWriteableDirectory );
1218 : }
1219 :
1220 0 : bWriteableDirectory = sal_False;
1221 : }
1222 :
1223 : // now check the list
1224 0 : for( size_t j = 0, n = aGroupList.size(); j < n; ++j )
1225 : {
1226 0 : GroupData_Impl *pGroup = aGroupList[ j ];
1227 0 : if ( pGroup->getInUse() )
1228 : {
1229 0 : if ( pGroup->getInHierarchy() )
1230 : {
1231 0 : Content aGroup;
1232 0 : if ( Content::create( pGroup->getHierarchyURL(), maCmdEnv, comphelper::getProcessComponentContext(), aGroup ) )
1233 : setProperty( aGroup,
1234 : OUString( TARGET_DIR_URL ),
1235 0 : makeAny( pGroup->getTargetURL() ) );
1236 :
1237 0 : size_t nCount = pGroup->count();
1238 0 : for ( size_t i=0; i<nCount; i++ )
1239 : {
1240 0 : DocTemplates_EntryData_Impl *pData = pGroup->getEntry( i );
1241 0 : if ( ! pData->getInUse() )
1242 : {
1243 0 : if ( pData->getInHierarchy() )
1244 0 : removeFromHierarchy( pData ); // delete entry in hierarchy
1245 : else
1246 0 : addToHierarchy( pGroup, pData ); // add entry to hierarchy
1247 : }
1248 0 : else if ( pData->getUpdateType() ||
1249 0 : pData->getUpdateLink() )
1250 : {
1251 0 : updateData( pData );
1252 : }
1253 0 : }
1254 : }
1255 : else
1256 : {
1257 0 : addGroupToHierarchy( pGroup ); // add group to hierarchy
1258 : }
1259 : }
1260 : else
1261 0 : removeFromHierarchy( pGroup ); // delete group from hierarchy
1262 :
1263 0 : delete pGroup;
1264 : }
1265 0 : aGroupList.clear();
1266 :
1267 0 : aValue <<= sal_False;
1268 0 : setProperty( maRootContent, aPropName, aValue );
1269 0 : }
1270 :
1271 : //-----------------------------------------------------------------------------
1272 0 : uno::Sequence< beans::StringPair > SfxDocTplService_Impl::ReadUINamesForTemplateDir_Impl( const ::rtl::OUString& aUserPath )
1273 : {
1274 0 : INetURLObject aLocObj( aUserPath );
1275 : aLocObj.insertName( ::rtl::OUString( "groupuinames.xml" ), false,
1276 : INetURLObject::LAST_SEGMENT, true,
1277 0 : INetURLObject::ENCODE_ALL );
1278 0 : Content aLocContent;
1279 :
1280 : // TODO/LATER: Use hashmap in future
1281 0 : uno::Sequence< beans::StringPair > aUINames;
1282 0 : if ( Content::create( aLocObj.GetMainURL( INetURLObject::NO_DECODE ), uno::Reference < ucb::XCommandEnvironment >(), comphelper::getProcessComponentContext(), aLocContent ) )
1283 : {
1284 : try
1285 : {
1286 0 : uno::Reference< io::XInputStream > xLocStream = aLocContent.openStream();
1287 0 : if ( xLocStream.is() )
1288 0 : aUINames = DocTemplLocaleHelper::ReadGroupLocalizationSequence( xLocStream, comphelper::getComponentContext(mxFactory) );
1289 : }
1290 0 : catch( uno::Exception& )
1291 : {}
1292 : }
1293 :
1294 0 : return aUINames;
1295 : }
1296 :
1297 : //-----------------------------------------------------------------------------
1298 0 : sal_Bool SfxDocTplService_Impl::UpdateUINamesForTemplateDir_Impl( const ::rtl::OUString& aUserPath,
1299 : const ::rtl::OUString& aGroupName,
1300 : const ::rtl::OUString& aNewFolderName )
1301 : {
1302 0 : uno::Sequence< beans::StringPair > aUINames = ReadUINamesForTemplateDir_Impl( aUserPath );
1303 0 : sal_Int32 nLen = aUINames.getLength();
1304 :
1305 : // it is possible that the name is used already, but it should be checked before
1306 0 : for ( sal_Int32 nInd = 0; nInd < nLen; nInd++ )
1307 0 : if ( aUINames[nInd].First.equals( aNewFolderName ) )
1308 0 : return sal_False;
1309 :
1310 0 : aUINames.realloc( ++nLen );
1311 0 : aUINames[nLen-1].First = aNewFolderName;
1312 0 : aUINames[nLen-1].Second = aGroupName;
1313 :
1314 0 : return WriteUINamesForTemplateDir_Impl( aUserPath, aUINames );
1315 : }
1316 :
1317 : //-----------------------------------------------------------------------------
1318 0 : sal_Bool SfxDocTplService_Impl::ReplaceUINamesForTemplateDir_Impl( const ::rtl::OUString& aUserPath,
1319 : const ::rtl::OUString& aDefaultFsysGroupName,
1320 : const ::rtl::OUString& aOldGroupName,
1321 : const ::rtl::OUString& aNewGroupName )
1322 : {
1323 0 : uno::Sequence< beans::StringPair > aUINames = ReadUINamesForTemplateDir_Impl( aUserPath );
1324 0 : sal_Int32 nLen = aUINames.getLength();
1325 :
1326 0 : sal_Bool bChanged = sal_False;
1327 0 : for ( sal_Int32 nInd = 0; nInd < nLen; nInd++ )
1328 0 : if ( aUINames[nInd].Second.equals( aOldGroupName ) )
1329 : {
1330 0 : aUINames[nInd].Second = aNewGroupName;
1331 0 : bChanged = sal_True;
1332 : }
1333 :
1334 0 : if ( !bChanged )
1335 : {
1336 0 : aUINames.realloc( ++nLen );
1337 0 : aUINames[nLen-1].First = aDefaultFsysGroupName;
1338 0 : aUINames[nLen-1].Second = aNewGroupName;
1339 : }
1340 0 : return WriteUINamesForTemplateDir_Impl( aUserPath, aUINames );
1341 : }
1342 :
1343 : //-----------------------------------------------------------------------------
1344 0 : sal_Bool SfxDocTplService_Impl::RemoveUINamesForTemplateDir_Impl( const ::rtl::OUString& aUserPath,
1345 : const ::rtl::OUString& aGroupName )
1346 : {
1347 0 : uno::Sequence< beans::StringPair > aUINames = ReadUINamesForTemplateDir_Impl( aUserPath );
1348 0 : sal_Int32 nLen = aUINames.getLength();
1349 0 : uno::Sequence< beans::StringPair > aNewUINames( nLen );
1350 0 : sal_Int32 nNewLen = 0;
1351 :
1352 0 : sal_Bool bChanged = sal_False;
1353 0 : for ( sal_Int32 nInd = 0; nInd < nLen; nInd++ )
1354 0 : if ( aUINames[nInd].Second.equals( aGroupName ) )
1355 0 : bChanged = sal_True;
1356 : else
1357 : {
1358 0 : nNewLen++;
1359 0 : aNewUINames[nNewLen-1].First = aUINames[nInd].First;
1360 0 : aNewUINames[nNewLen-1].Second = aUINames[nInd].Second;
1361 : }
1362 :
1363 0 : aNewUINames.realloc( nNewLen );
1364 :
1365 0 : return bChanged ? WriteUINamesForTemplateDir_Impl( aUserPath, aNewUINames ) : sal_True;
1366 : }
1367 :
1368 :
1369 : //-----------------------------------------------------------------------------
1370 0 : sal_Bool SfxDocTplService_Impl::WriteUINamesForTemplateDir_Impl( const ::rtl::OUString& aUserPath,
1371 : const uno::Sequence< beans::StringPair >& aUINames )
1372 : {
1373 0 : sal_Bool bResult = sal_False;
1374 : try {
1375 : uno::Reference< beans::XPropertySet > xTempFile(
1376 : io::TempFile::create(comphelper::getComponentContext(mxFactory)),
1377 0 : uno::UNO_QUERY_THROW );
1378 :
1379 0 : ::rtl::OUString aTempURL;
1380 0 : uno::Any aUrl = xTempFile->getPropertyValue( ::rtl::OUString("Uri") );
1381 0 : aUrl >>= aTempURL;
1382 :
1383 0 : uno::Reference< io::XStream > xStream( xTempFile, uno::UNO_QUERY_THROW );
1384 0 : uno::Reference< io::XOutputStream > xOutStream = xStream->getOutputStream();
1385 0 : if ( !xOutStream.is() )
1386 0 : throw uno::RuntimeException();
1387 :
1388 0 : DocTemplLocaleHelper::WriteGroupLocalizationSequence( xOutStream, aUINames, comphelper::getComponentContext(mxFactory));
1389 : try {
1390 : // the SAX writer might close the stream
1391 0 : xOutStream->closeOutput();
1392 0 : } catch( uno::Exception& )
1393 : {}
1394 :
1395 0 : Content aTargetContent( aUserPath, maCmdEnv, comphelper::getProcessComponentContext() );
1396 0 : Content aSourceContent( aTempURL, maCmdEnv, comphelper::getProcessComponentContext() );
1397 : aTargetContent.transferContent( aSourceContent,
1398 : InsertOperation_COPY,
1399 : ::rtl::OUString( "groupuinames.xml" ),
1400 : ucb::NameClash::OVERWRITE,
1401 0 : ::rtl::OUString( "text/xml" ) );
1402 0 : bResult = sal_True;
1403 : }
1404 0 : catch ( uno::Exception& )
1405 : {
1406 : }
1407 :
1408 0 : return bResult;
1409 : }
1410 :
1411 : //-----------------------------------------------------------------------------
1412 0 : ::rtl::OUString SfxDocTplService_Impl::CreateNewGroupFsys( const ::rtl::OUString& rGroupName, Content& aGroup )
1413 : {
1414 0 : ::rtl::OUString aResultURL;
1415 :
1416 0 : if ( maTemplateDirs.getLength() )
1417 : {
1418 0 : ::rtl::OUString aTargetPath = maTemplateDirs[ maTemplateDirs.getLength() - 1 ];
1419 :
1420 : // create a new folder with the given name
1421 0 : Content aNewFolder;
1422 0 : ::rtl::OUString aNewFolderName;
1423 :
1424 : // the Fsys name instead of GroupName should be used, the groupuinames must be added also
1425 0 : if ( !CreateNewUniqueFolderWithPrefix( aTargetPath,
1426 : rGroupName,
1427 : aNewFolderName,
1428 : aResultURL,
1429 0 : aNewFolder )
1430 : && !CreateNewUniqueFolderWithPrefix( aTargetPath,
1431 : ::rtl::OUString( "UserGroup" ),
1432 : aNewFolderName,
1433 : aResultURL,
1434 0 : aNewFolder ) )
1435 :
1436 0 : return ::rtl::OUString();
1437 :
1438 0 : if ( !UpdateUINamesForTemplateDir_Impl( aTargetPath, rGroupName, aNewFolderName ) )
1439 : {
1440 : // we could not create the groupuinames for the folder, so we delete the group in the
1441 : // the folder and return
1442 0 : removeContent( aNewFolder );
1443 0 : return ::rtl::OUString();
1444 : }
1445 :
1446 : // Now set the target url for this group and we are done
1447 0 : OUString aPropName( TARGET_DIR_URL );
1448 0 : Any aValue = makeAny( aResultURL );
1449 :
1450 0 : if ( ! setProperty( aGroup, aPropName, aValue ) )
1451 : {
1452 0 : removeContent( aNewFolder );
1453 0 : return ::rtl::OUString();
1454 0 : }
1455 : }
1456 :
1457 0 : return aResultURL;
1458 : }
1459 :
1460 : //-----------------------------------------------------------------------------
1461 0 : sal_Bool SfxDocTplService_Impl::addGroup( const OUString& rGroupName )
1462 : {
1463 0 : ::osl::MutexGuard aGuard( maMutex );
1464 :
1465 : // Check, whether or not there is a group with this name
1466 0 : Content aNewGroup;
1467 0 : OUString aNewGroupURL;
1468 0 : INetURLObject aNewGroupObj( maRootURL );
1469 :
1470 : aNewGroupObj.insertName( rGroupName, false,
1471 : INetURLObject::LAST_SEGMENT, true,
1472 0 : INetURLObject::ENCODE_ALL );
1473 :
1474 0 : aNewGroupURL = aNewGroupObj.GetMainURL( INetURLObject::NO_DECODE );
1475 :
1476 0 : if ( Content::create( aNewGroupURL, maCmdEnv, comphelper::getProcessComponentContext(), aNewGroup ) ||
1477 0 : ! createFolder( aNewGroupURL, sal_False, sal_False, aNewGroup ) )
1478 : {
1479 : // if there already was a group with this name or the new group
1480 : // could not be created, we return here
1481 0 : return sal_False;
1482 : }
1483 :
1484 : // Get the user template path entry ( new group will always
1485 : // be added in the user template path )
1486 : sal_Int32 nIndex;
1487 0 : OUString aUserPath;
1488 :
1489 0 : nIndex = maTemplateDirs.getLength();
1490 0 : if ( nIndex )
1491 0 : nIndex--;
1492 : else
1493 0 : return sal_False; // We don't know where to add the group
1494 :
1495 0 : aUserPath = maTemplateDirs[ nIndex ];
1496 :
1497 : // create a new folder with the given name
1498 0 : Content aNewFolder;
1499 0 : OUString aNewFolderName;
1500 0 : OUString aNewFolderURL;
1501 :
1502 : // the Fsys name instead of GroupName should be used, the groupuinames must be added also
1503 0 : if ( !CreateNewUniqueFolderWithPrefix( aUserPath,
1504 : rGroupName,
1505 : aNewFolderName,
1506 : aNewFolderURL,
1507 0 : aNewFolder )
1508 : && !CreateNewUniqueFolderWithPrefix( aUserPath,
1509 : ::rtl::OUString( "UserGroup" ),
1510 : aNewFolderName,
1511 : aNewFolderURL,
1512 0 : aNewFolder ) )
1513 : {
1514 : // we could not create the folder, so we delete the group in the
1515 : // hierarchy and return
1516 0 : removeContent( aNewGroup );
1517 0 : return sal_False;
1518 : }
1519 :
1520 0 : if ( !UpdateUINamesForTemplateDir_Impl( aUserPath, rGroupName, aNewFolderName ) )
1521 : {
1522 : // we could not create the groupuinames for the folder, so we delete the group in the
1523 : // hierarchy, the folder and return
1524 0 : removeContent( aNewGroup );
1525 0 : removeContent( aNewFolder );
1526 0 : return sal_False;
1527 : }
1528 :
1529 : // Now set the target url for this group and we are done
1530 0 : OUString aPropName( TARGET_DIR_URL );
1531 0 : Any aValue = makeAny( aNewFolderURL );
1532 :
1533 0 : if ( ! setProperty( aNewGroup, aPropName, aValue ) )
1534 : {
1535 0 : removeContent( aNewGroup );
1536 0 : removeContent( aNewFolder );
1537 0 : return sal_False;
1538 : }
1539 :
1540 0 : return sal_True;
1541 : }
1542 :
1543 : //-----------------------------------------------------------------------------
1544 0 : sal_Bool SfxDocTplService_Impl::removeGroup( const OUString& rGroupName )
1545 : {
1546 : // remove all the elements that have the prefix aTargetURL
1547 : // if the group does not have other elements remove it
1548 :
1549 0 : ::osl::MutexGuard aGuard( maMutex );
1550 :
1551 0 : sal_Bool bResult = sal_False;
1552 :
1553 : // create the group url
1554 0 : INetURLObject aGroupObj( maRootURL );
1555 : aGroupObj.insertName( rGroupName, false,
1556 : INetURLObject::LAST_SEGMENT, true,
1557 0 : INetURLObject::ENCODE_ALL );
1558 :
1559 : // Get the target url
1560 0 : Content aGroup;
1561 0 : OUString aGroupURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE );
1562 :
1563 0 : if ( Content::create( aGroupURL, maCmdEnv, comphelper::getProcessComponentContext(), aGroup ) )
1564 : {
1565 0 : OUString aPropName( TARGET_DIR_URL );
1566 0 : Any aValue;
1567 :
1568 0 : OUString aGroupTargetURL;
1569 0 : if ( getProperty( aGroup, aPropName, aValue ) )
1570 0 : aValue >>= aGroupTargetURL;
1571 :
1572 0 : if ( aGroupTargetURL.isEmpty() )
1573 0 : return sal_False; // nothing is allowed to be removed
1574 :
1575 0 : if ( !maTemplateDirs.getLength() )
1576 0 : return sal_False;
1577 0 : ::rtl::OUString aGeneralTempPath = maTemplateDirs[ maTemplateDirs.getLength() - 1 ];
1578 :
1579 : // check that the fs location is in writeble folder and this is not a "My templates" folder
1580 0 : INetURLObject aGroupParentFolder( aGroupTargetURL );
1581 0 : if ( !aGroupParentFolder.removeSegment()
1582 : || !::utl::UCBContentHelper::IsSubPath( aGeneralTempPath,
1583 0 : aGroupParentFolder.GetMainURL( INetURLObject::NO_DECODE ) ) )
1584 0 : return sal_False;
1585 :
1586 : // now get the content of the Group
1587 0 : uno::Reference< XResultSet > xResultSet;
1588 0 : Sequence< OUString > aProps( 1 );
1589 :
1590 0 : aProps[0] = OUString(TARGET_URL );
1591 :
1592 : try
1593 : {
1594 0 : sal_Bool bHasNonRemovable = sal_False;
1595 0 : sal_Bool bHasShared = sal_False;
1596 :
1597 0 : ResultSetInclude eInclude = INCLUDE_DOCUMENTS_ONLY;
1598 0 : xResultSet = aGroup.createCursor( aProps, eInclude );
1599 :
1600 0 : if ( xResultSet.is() )
1601 : {
1602 0 : uno::Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY_THROW );
1603 0 : uno::Reference< XRow > xRow( xResultSet, UNO_QUERY_THROW );
1604 :
1605 0 : while ( xResultSet->next() )
1606 : {
1607 0 : OUString aTemplTargetURL( xRow->getString( 1 ) );
1608 0 : OUString aHierURL = xContentAccess->queryContentIdentifierString();
1609 :
1610 0 : if ( ::utl::UCBContentHelper::IsSubPath( aGroupTargetURL, aTemplTargetURL ) )
1611 : {
1612 : // this is a user template, and it can be removed
1613 0 : if ( removeContent( aTemplTargetURL ) )
1614 0 : removeContent( aHierURL );
1615 : else
1616 0 : bHasNonRemovable = sal_True;
1617 : }
1618 : else
1619 0 : bHasShared = sal_True;
1620 0 : }
1621 :
1622 0 : if ( !bHasNonRemovable && !bHasShared )
1623 : {
1624 0 : if ( removeContent( aGroupTargetURL )
1625 0 : || !::utl::UCBContentHelper::Exists( aGroupTargetURL ) )
1626 : {
1627 0 : removeContent( aGroupURL );
1628 0 : RemoveUINamesForTemplateDir_Impl( aGeneralTempPath, rGroupName );
1629 0 : bResult = sal_True; // the operation is successful only if the whole group is removed
1630 : }
1631 : }
1632 0 : else if ( !bHasNonRemovable )
1633 : {
1634 0 : if ( removeContent( aGroupTargetURL )
1635 0 : || !::utl::UCBContentHelper::Exists( aGroupTargetURL ) )
1636 : {
1637 0 : RemoveUINamesForTemplateDir_Impl( aGeneralTempPath, rGroupName );
1638 0 : setProperty( aGroup, aPropName, uno::makeAny( ::rtl::OUString() ) );
1639 : }
1640 0 : }
1641 : }
1642 : }
1643 0 : catch ( Exception& ) {}
1644 : }
1645 :
1646 0 : return bResult;
1647 : }
1648 :
1649 : //-----------------------------------------------------------------------------
1650 0 : sal_Bool SfxDocTplService_Impl::renameGroup( const OUString& rOldName,
1651 : const OUString& rNewName )
1652 : {
1653 0 : ::osl::MutexGuard aGuard( maMutex );
1654 :
1655 : // create the group url
1656 0 : Content aGroup;
1657 0 : INetURLObject aGroupObj( maRootURL );
1658 : aGroupObj.insertName( rNewName, false,
1659 : INetURLObject::LAST_SEGMENT, true,
1660 0 : INetURLObject::ENCODE_ALL );
1661 0 : OUString aGroupURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE );
1662 :
1663 : // Check, if there is a group with the new name, return false
1664 : // if there is one.
1665 0 : if ( Content::create( aGroupURL, maCmdEnv, comphelper::getProcessComponentContext(), aGroup ) )
1666 0 : return sal_False;
1667 :
1668 0 : aGroupObj.removeSegment();
1669 : aGroupObj.insertName( rOldName, false,
1670 : INetURLObject::LAST_SEGMENT, true,
1671 0 : INetURLObject::ENCODE_ALL );
1672 0 : aGroupURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE );
1673 :
1674 : // When there is no group with the old name, we can't rename it
1675 0 : if ( ! Content::create( aGroupURL, maCmdEnv, comphelper::getProcessComponentContext(), aGroup ) )
1676 0 : return sal_False;
1677 :
1678 0 : OUString aGroupTargetURL;
1679 : // there is no need to check whether target dir url is in target path, since if the target path is changed
1680 : // the target dir url should be already generated new
1681 0 : OUString aPropName( TARGET_DIR_URL );
1682 0 : Any aValue;
1683 0 : if ( getProperty( aGroup, aPropName, aValue ) )
1684 0 : aValue >>= aGroupTargetURL;
1685 :
1686 0 : if ( aGroupTargetURL.isEmpty() )
1687 0 : return sal_False;
1688 :
1689 0 : if ( !maTemplateDirs.getLength() )
1690 0 : return sal_False;
1691 0 : ::rtl::OUString aGeneralTempPath = maTemplateDirs[ maTemplateDirs.getLength() - 1 ];
1692 :
1693 : // check that the fs location is in writeble folder and this is not a "My templates" folder
1694 0 : INetURLObject aGroupParentFolder( aGroupTargetURL );
1695 0 : if ( !aGroupParentFolder.removeSegment()
1696 : || !::utl::UCBContentHelper::IsSubPath( aGeneralTempPath,
1697 0 : aGroupParentFolder.GetMainURL( INetURLObject::NO_DECODE ) ) )
1698 0 : return sal_False;
1699 :
1700 : // check that the group can be renamed ( all the contents must be in target location )
1701 0 : sal_Bool bCanBeRenamed = sal_False;
1702 : try
1703 : {
1704 0 : uno::Reference< XResultSet > xResultSet;
1705 0 : Sequence< OUString > aProps( 1 );
1706 :
1707 0 : aProps[0] = OUString(TARGET_URL );
1708 0 : ResultSetInclude eInclude = INCLUDE_DOCUMENTS_ONLY;
1709 0 : xResultSet = aGroup.createCursor( aProps, eInclude );
1710 :
1711 0 : if ( xResultSet.is() )
1712 : {
1713 0 : uno::Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY_THROW );
1714 0 : uno::Reference< XRow > xRow( xResultSet, UNO_QUERY_THROW );
1715 :
1716 0 : while ( xResultSet->next() )
1717 : {
1718 0 : OUString aTemplTargetURL( xRow->getString( 1 ) );
1719 :
1720 0 : if ( !::utl::UCBContentHelper::IsSubPath( aGroupTargetURL, aTemplTargetURL ) )
1721 0 : throw uno::Exception();
1722 0 : }
1723 :
1724 0 : bCanBeRenamed = sal_True;
1725 0 : }
1726 : }
1727 0 : catch ( Exception& ) {}
1728 :
1729 0 : if ( bCanBeRenamed )
1730 : {
1731 0 : INetURLObject aGroupTargetObj( aGroupTargetURL );
1732 0 : ::rtl::OUString aFsysName = aGroupTargetObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
1733 :
1734 0 : if ( aGroupTargetObj.removeSegment()
1735 : && ReplaceUINamesForTemplateDir_Impl( aGroupTargetObj.GetMainURL( INetURLObject::NO_DECODE ),
1736 : aFsysName,
1737 : rOldName,
1738 0 : rNewName ) )
1739 : {
1740 : // rename the group in the hierarchy
1741 0 : OUString aTitleProp( TITLE );
1742 0 : Any aTitleValue;
1743 0 : aTitleValue <<= rNewName;
1744 :
1745 0 : return setProperty( aGroup, aTitleProp, aTitleValue );
1746 0 : }
1747 : }
1748 :
1749 0 : return sal_False;
1750 : }
1751 :
1752 : //-----------------------------------------------------------------------------
1753 0 : sal_Bool SfxDocTplService_Impl::storeTemplate( const OUString& rGroupName,
1754 : const OUString& rTemplateName,
1755 : const uno::Reference< XSTORABLE >& rStorable )
1756 : {
1757 0 : ::osl::MutexGuard aGuard( maMutex );
1758 :
1759 : // Check, whether or not there is a group with this name
1760 : // Return false, if there is no group with the given name
1761 0 : Content aGroup, aTemplate, aTargetGroup, aTemplateToRemove;
1762 0 : OUString aGroupURL, aTemplateURL, aTemplateToRemoveTargetURL;
1763 0 : INetURLObject aGroupObj( maRootURL );
1764 0 : sal_Bool bRemoveOldTemplateContent = sal_False;
1765 0 : ::rtl::OUString sDocServiceName;
1766 :
1767 : aGroupObj.insertName( rGroupName, false,
1768 : INetURLObject::LAST_SEGMENT, true,
1769 0 : INetURLObject::ENCODE_ALL );
1770 0 : aGroupURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE );
1771 :
1772 0 : if ( ! Content::create( aGroupURL, maCmdEnv, comphelper::getProcessComponentContext(), aGroup ) )
1773 0 : return sal_False;
1774 :
1775 0 : ::rtl::OUString aGroupTargetURL;
1776 0 : ::rtl::OUString aPropName( TARGET_DIR_URL );
1777 0 : Any aValue;
1778 0 : if ( getProperty( aGroup, aPropName, aValue ) )
1779 0 : aValue >>= aGroupTargetURL;
1780 :
1781 :
1782 : // Check, if there's a template with the given name in this group
1783 : // the target template should be overwritten if it is imported by user
1784 : // in case the template is installed by office installation of by an add-in
1785 : // it can not be replaced
1786 : aGroupObj.insertName( rTemplateName, false,
1787 : INetURLObject::LAST_SEGMENT, true,
1788 0 : INetURLObject::ENCODE_ALL );
1789 0 : aTemplateURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE );
1790 :
1791 0 : if ( Content::create( aTemplateURL, maCmdEnv, comphelper::getProcessComponentContext(), aTemplateToRemove ) )
1792 : {
1793 0 : OUString aTargetTemplPropName( TARGET_URL );
1794 :
1795 0 : bRemoveOldTemplateContent = sal_True;
1796 0 : if ( getProperty( aTemplateToRemove, aTargetTemplPropName, aValue ) )
1797 0 : aValue >>= aTemplateToRemoveTargetURL;
1798 :
1799 0 : if ( aGroupTargetURL.isEmpty() || !maTemplateDirs.getLength()
1800 0 : || (!aTemplateToRemoveTargetURL.isEmpty() && !::utl::UCBContentHelper::IsSubPath( maTemplateDirs[ maTemplateDirs.getLength() - 1 ], aTemplateToRemoveTargetURL )) )
1801 0 : return sal_False; // it is not allowed to remove the template
1802 : }
1803 :
1804 : try
1805 : {
1806 0 : uno::Reference< lang::XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory();
1807 0 : if ( !xFactory.is() )
1808 0 : throw uno::RuntimeException();
1809 :
1810 : // get document service name
1811 : uno::Reference< frame::XModuleManager2 > xModuleManager(
1812 0 : frame::ModuleManager::create(comphelper::getComponentContext(xFactory)) );
1813 0 : sDocServiceName = xModuleManager->identify( uno::Reference< uno::XInterface >( rStorable, uno::UNO_QUERY ) );
1814 0 : if ( sDocServiceName.isEmpty() )
1815 0 : throw uno::RuntimeException();
1816 :
1817 : // get the actual filter name
1818 0 : ::rtl::OUString aFilterName;
1819 :
1820 : uno::Reference< lang::XMultiServiceFactory > xConfigProvider =
1821 0 : configuration::theDefaultProvider::get( comphelper::getComponentContext(xFactory) );
1822 :
1823 0 : uno::Sequence< uno::Any > aArgs( 1 );
1824 0 : beans::PropertyValue aPathProp;
1825 0 : aPathProp.Name = ::rtl::OUString("nodepath");
1826 0 : aPathProp.Value <<= ::rtl::OUString( "/org.openoffice.Setup/Office/Factories/" );
1827 0 : aArgs[0] <<= aPathProp;
1828 :
1829 : uno::Reference< container::XNameAccess > xSOFConfig(
1830 0 : xConfigProvider->createInstanceWithArguments(
1831 : ::rtl::OUString("com.sun.star.configuration.ConfigurationAccess"),
1832 0 : aArgs ),
1833 0 : uno::UNO_QUERY_THROW );
1834 :
1835 0 : uno::Reference< container::XNameAccess > xApplConfig;
1836 0 : xSOFConfig->getByName( sDocServiceName ) >>= xApplConfig;
1837 0 : if ( !xApplConfig.is() )
1838 0 : throw uno::RuntimeException();
1839 :
1840 0 : xApplConfig->getByName( ::rtl::OUString( "ooSetupFactoryActualTemplateFilter" ) ) >>= aFilterName;
1841 0 : if ( aFilterName.isEmpty() )
1842 0 : throw uno::RuntimeException();
1843 :
1844 : // find the related type name
1845 0 : ::rtl::OUString aTypeName;
1846 : uno::Reference< container::XNameAccess > xFilterFactory(
1847 0 : xFactory->createInstance( ::rtl::OUString("com.sun.star.document.FilterFactory") ),
1848 0 : uno::UNO_QUERY_THROW );
1849 :
1850 0 : uno::Sequence< beans::PropertyValue > aFilterData;
1851 0 : xFilterFactory->getByName( aFilterName ) >>= aFilterData;
1852 0 : for ( sal_Int32 nInd = 0; nInd < aFilterData.getLength(); nInd++ )
1853 0 : if ( aFilterData[nInd].Name == "Type" )
1854 0 : aFilterData[nInd].Value >>= aTypeName;
1855 :
1856 0 : if ( aTypeName.isEmpty() )
1857 0 : throw uno::RuntimeException();
1858 :
1859 : // find the mediatype and extension
1860 0 : uno::Reference< container::XNameAccess > xTypeDetection;
1861 :
1862 : xTypeDetection =
1863 0 : mxType.is() ?
1864 : uno::Reference< container::XNameAccess >( mxType, uno::UNO_QUERY_THROW ) :
1865 : uno::Reference< container::XNameAccess >(
1866 0 : xFactory->createInstance( ::rtl::OUString("com.sun.star.document.TypeDetection") ),
1867 0 : uno::UNO_QUERY_THROW );
1868 :
1869 0 : SequenceAsHashMap aTypeProps( xTypeDetection->getByName( aTypeName ) );
1870 : uno::Sequence< ::rtl::OUString > aAllExt =
1871 0 : aTypeProps.getUnpackedValueOrDefault( ::rtl::OUString("Extensions"), Sequence< ::rtl::OUString >() );
1872 0 : if ( !aAllExt.getLength() )
1873 0 : throw uno::RuntimeException();
1874 :
1875 0 : ::rtl::OUString aMediaType = aTypeProps.getUnpackedValueOrDefault( ::rtl::OUString("MediaType"), ::rtl::OUString() );
1876 0 : ::rtl::OUString aExt = aAllExt[0];
1877 :
1878 0 : if ( aMediaType.isEmpty() || aExt.isEmpty() )
1879 0 : throw uno::RuntimeException();
1880 :
1881 : // construct destination url
1882 0 : if ( aGroupTargetURL.isEmpty() )
1883 : {
1884 0 : aGroupTargetURL = CreateNewGroupFsys( rGroupName, aGroup );
1885 :
1886 0 : if ( aGroupTargetURL.isEmpty() )
1887 0 : throw uno::RuntimeException();
1888 : }
1889 :
1890 0 : ::rtl::OUString aNewTemplateTargetURL = CreateNewUniqueFileWithPrefix( aGroupTargetURL, rTemplateName, aExt );
1891 0 : if ( aNewTemplateTargetURL.isEmpty() )
1892 : {
1893 0 : aNewTemplateTargetURL = CreateNewUniqueFileWithPrefix( aGroupTargetURL, ::rtl::OUString( "UserTemplate" ), aExt );
1894 :
1895 0 : if ( aNewTemplateTargetURL.isEmpty() )
1896 0 : throw uno::RuntimeException();
1897 : }
1898 :
1899 : // store template
1900 0 : uno::Sequence< PropertyValue > aStoreArgs( 2 );
1901 0 : aStoreArgs[0].Name = ::rtl::OUString("FilterName");
1902 0 : aStoreArgs[0].Value <<= aFilterName;
1903 0 : aStoreArgs[1].Name = ::rtl::OUString("DocumentTitle");
1904 0 : aStoreArgs[1].Value <<= rTemplateName;
1905 :
1906 0 : if( !::utl::UCBContentHelper::EqualURLs( aNewTemplateTargetURL, rStorable->getLocation() ))
1907 0 : rStorable->storeToURL( aNewTemplateTargetURL, aStoreArgs );
1908 : else
1909 0 : rStorable->store();
1910 :
1911 : // the storing was successful, now the old template with the same name can be removed if it existed
1912 0 : if ( !aTemplateToRemoveTargetURL.isEmpty() )
1913 : {
1914 0 : removeContent( aTemplateToRemoveTargetURL );
1915 :
1916 : /*
1917 : * pb: #i79496#
1918 : * if the old template was the standard template
1919 : * it is necessary to change the standard template with the new file name
1920 : */
1921 0 : String sStdTmplFile = SfxObjectFactory::GetStandardTemplate( sDocServiceName );
1922 0 : if ( INetURLObject( sStdTmplFile ) == INetURLObject( aTemplateToRemoveTargetURL ) )
1923 : {
1924 0 : SfxObjectFactory::SetStandardTemplate( sDocServiceName, aNewTemplateTargetURL );
1925 0 : }
1926 : }
1927 :
1928 0 : if ( bRemoveOldTemplateContent )
1929 0 : removeContent( aTemplateToRemove );
1930 :
1931 : // add the template to hierarchy
1932 0 : return addEntry( aGroup, rTemplateName, aNewTemplateTargetURL, aMediaType );
1933 : }
1934 0 : catch( Exception& )
1935 : {
1936 : // the template was not stored
1937 0 : return sal_False;
1938 0 : }
1939 : }
1940 :
1941 : //-----------------------------------------------------------------------------
1942 0 : sal_Bool SfxDocTplService_Impl::addTemplate( const OUString& rGroupName,
1943 : const OUString& rTemplateName,
1944 : const OUString& rSourceURL )
1945 : {
1946 0 : ::osl::MutexGuard aGuard( maMutex );
1947 :
1948 : // Check, whether or not there is a group with this name
1949 : // Return false, if there is no group with the given name
1950 0 : Content aGroup, aTemplate, aTargetGroup;
1951 0 : OUString aGroupURL, aTemplateURL;
1952 0 : INetURLObject aGroupObj( maRootURL );
1953 :
1954 : aGroupObj.insertName( rGroupName, false,
1955 : INetURLObject::LAST_SEGMENT, true,
1956 0 : INetURLObject::ENCODE_ALL );
1957 0 : aGroupURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE );
1958 :
1959 0 : if ( ! Content::create( aGroupURL, maCmdEnv, comphelper::getProcessComponentContext(), aGroup ) )
1960 0 : return sal_False;
1961 :
1962 : // Check, if there's a template with the given name in this group
1963 : // Return false, if there already is a template
1964 : aGroupObj.insertName( rTemplateName, false,
1965 : INetURLObject::LAST_SEGMENT, true,
1966 0 : INetURLObject::ENCODE_ALL );
1967 0 : aTemplateURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE );
1968 :
1969 0 : if ( Content::create( aTemplateURL, maCmdEnv, comphelper::getProcessComponentContext(), aTemplate ) )
1970 0 : return sal_False;
1971 :
1972 : // get the target url of the group
1973 0 : OUString aTargetURL;
1974 0 : OUString aPropName( TARGET_DIR_URL );
1975 0 : Any aValue;
1976 :
1977 0 : if ( getProperty( aGroup, aPropName, aValue ) )
1978 0 : aValue >>= aTargetURL;
1979 :
1980 0 : if ( aTargetURL.isEmpty() )
1981 : {
1982 0 : aTargetURL = CreateNewGroupFsys( rGroupName, aGroup );
1983 :
1984 0 : if ( aTargetURL.isEmpty() )
1985 0 : return sal_False;
1986 : }
1987 :
1988 : // Get the content type
1989 0 : OUString aTitle, aType, aTargetURL2;
1990 :
1991 0 : sal_Bool bDocHasTitle = sal_False;
1992 0 : if( !getTitleFromURL( rSourceURL, aTitle, aType, bDocHasTitle ) )
1993 0 : return sal_False;
1994 :
1995 0 : INetURLObject aSourceObj( rSourceURL );
1996 0 : if ( rTemplateName.equals( aTitle ) )
1997 : {
1998 : // addTemplate will sometimes be called just to add an entry in the
1999 : // hierarchy; the target URL and the source URL will be the same in
2000 : // this scenario
2001 : // TODO/LATER: get rid of this old hack
2002 :
2003 0 : INetURLObject aTargetObj( aTargetURL );
2004 :
2005 : aTargetObj.insertName( rTemplateName, false,
2006 : INetURLObject::LAST_SEGMENT, true,
2007 0 : INetURLObject::ENCODE_ALL );
2008 0 : aTargetObj.setExtension( aSourceObj.getExtension() );
2009 :
2010 0 : aTargetURL2 = aTargetObj.GetMainURL( INetURLObject::NO_DECODE );
2011 :
2012 0 : if ( aTargetURL2 == rSourceURL )
2013 0 : return addEntry( aGroup, rTemplateName, aTargetURL2, aType );
2014 : }
2015 :
2016 : // copy the template into the new group (targeturl)
2017 :
2018 0 : INetURLObject aTmpURL( aSourceObj );
2019 0 : aTmpURL.CutExtension();
2020 0 : ::rtl::OUString aPattern = aTmpURL.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
2021 :
2022 0 : ::rtl::OUString aNewTemplateTargetURL = CreateNewUniqueFileWithPrefix( aTargetURL, aPattern, aSourceObj.getExtension() );
2023 0 : INetURLObject aNewTemplateTargetObj( aNewTemplateTargetURL );
2024 0 : ::rtl::OUString aNewTemplateTargetName = aNewTemplateTargetObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
2025 0 : if ( aNewTemplateTargetURL.isEmpty() || aNewTemplateTargetName.isEmpty() )
2026 0 : return sal_False;
2027 :
2028 : // get access to source file
2029 0 : Content aSourceContent;
2030 0 : uno::Reference < ucb::XCommandEnvironment > xEnv;
2031 0 : INetURLObject aSourceURL( rSourceURL );
2032 0 : if( ! Content::create( aSourceURL.GetMainURL( INetURLObject::NO_DECODE ), xEnv, comphelper::getProcessComponentContext(), aSourceContent ) )
2033 0 : return sal_False;
2034 :
2035 0 : if( ! Content::create( aTargetURL, xEnv, comphelper::getProcessComponentContext(), aTargetGroup ) )
2036 0 : return sal_False;
2037 :
2038 : // transfer source file
2039 : try
2040 : {
2041 0 : if( ! aTargetGroup.transferContent( aSourceContent,
2042 : InsertOperation_COPY,
2043 : aNewTemplateTargetName,
2044 : NameClash::OVERWRITE,
2045 0 : aType ) )
2046 0 : return sal_False;
2047 :
2048 : // allow to edit the added template
2049 0 : Content aResultContent;
2050 0 : if ( Content::create( aNewTemplateTargetURL, xEnv, comphelper::getProcessComponentContext(), aResultContent ) )
2051 : {
2052 0 : ::rtl::OUString aPropertyName( "IsReadOnly" );
2053 0 : uno::Any aProperty;
2054 0 : sal_Bool bReadOnly = sal_False;
2055 0 : if ( getProperty( aResultContent, aPropertyName, aProperty ) && ( aProperty >>= bReadOnly ) && bReadOnly )
2056 0 : setProperty( aResultContent, aPropertyName, uno::makeAny( (sal_Bool)sal_False ) );
2057 0 : }
2058 : }
2059 0 : catch ( ContentCreationException& )
2060 0 : { return sal_False; }
2061 0 : catch ( Exception& )
2062 0 : { return sal_False; }
2063 :
2064 :
2065 : // either the document has title and it is the same as requested, or we have to set it
2066 0 : sal_Bool bCorrectTitle = ( bDocHasTitle && aTitle.equals( rTemplateName ) );
2067 0 : if ( !bCorrectTitle )
2068 : {
2069 0 : if ( !bDocHasTitle )
2070 : {
2071 0 : INetURLObject aNewTmpObj( aNewTemplateTargetObj );
2072 0 : aNewTmpObj.CutExtension();
2073 0 : bCorrectTitle = ( aNewTmpObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET ).equals( rTemplateName ) );
2074 : }
2075 :
2076 0 : if ( !bCorrectTitle )
2077 0 : bCorrectTitle = setTitleForURL( aNewTemplateTargetURL, rTemplateName );
2078 : }
2079 :
2080 0 : if ( bCorrectTitle )
2081 : {
2082 : // create a new entry in the hierarchy
2083 0 : return addEntry( aGroup, rTemplateName, aNewTemplateTargetURL, aType );
2084 : }
2085 :
2086 : // TODO/LATER: The user could be notified here that the renaming has failed
2087 : // create a new entry in the hierarchy
2088 0 : addEntry( aGroup, aTitle, aNewTemplateTargetURL, aType );
2089 0 : return sal_False;
2090 : }
2091 :
2092 : //-----------------------------------------------------------------------------
2093 0 : sal_Bool SfxDocTplService_Impl::removeTemplate( const OUString& rGroupName,
2094 : const OUString& rTemplateName )
2095 : {
2096 0 : ::osl::MutexGuard aGuard( maMutex );
2097 :
2098 : // Check, whether or not there is a group with this name
2099 : // Return false, if there is no group with the given name
2100 0 : Content aGroup, aTemplate;
2101 0 : OUString aGroupURL, aTemplateURL;
2102 0 : INetURLObject aGroupObj( maRootURL );
2103 :
2104 : aGroupObj.insertName( rGroupName, false,
2105 : INetURLObject::LAST_SEGMENT, true,
2106 0 : INetURLObject::ENCODE_ALL );
2107 0 : aGroupURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE );
2108 :
2109 0 : if ( ! Content::create( aGroupURL, maCmdEnv, comphelper::getProcessComponentContext(), aGroup ) )
2110 0 : return sal_False;
2111 :
2112 : // Check, if there's a template with the given name in this group
2113 : // Return false, if there is no template
2114 : aGroupObj.insertName( rTemplateName, false,
2115 : INetURLObject::LAST_SEGMENT, true,
2116 0 : INetURLObject::ENCODE_ALL );
2117 0 : aTemplateURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE );
2118 :
2119 0 : if ( !Content::create( aTemplateURL, maCmdEnv, comphelper::getProcessComponentContext(), aTemplate ) )
2120 0 : return sal_False;
2121 :
2122 : // get the target URL from the template
2123 0 : OUString aTargetURL;
2124 0 : OUString aPropName( TARGET_URL );
2125 0 : Any aValue;
2126 :
2127 0 : if ( getProperty( aTemplate, aPropName, aValue ) )
2128 0 : aValue >>= aTargetURL;
2129 :
2130 : // delete the target template
2131 0 : if ( !aTargetURL.isEmpty() )
2132 : {
2133 0 : if ( !maTemplateDirs.getLength()
2134 0 : || !::utl::UCBContentHelper::IsSubPath( maTemplateDirs[ maTemplateDirs.getLength() - 1 ], aTargetURL ) )
2135 0 : return sal_False;
2136 :
2137 0 : removeContent( aTargetURL );
2138 : }
2139 :
2140 : // delete the template entry
2141 0 : return removeContent( aTemplate );
2142 : }
2143 :
2144 : //-----------------------------------------------------------------------------
2145 0 : sal_Bool SfxDocTplService_Impl::renameTemplate( const OUString& rGroupName,
2146 : const OUString& rOldName,
2147 : const OUString& rNewName )
2148 : {
2149 0 : ::osl::MutexGuard aGuard( maMutex );
2150 :
2151 : // Check, whether or not there is a group with this name
2152 : // Return false, if there is no group with the given name
2153 0 : Content aGroup, aTemplate;
2154 0 : OUString aGroupURL, aTemplateURL;
2155 0 : INetURLObject aGroupObj( maRootURL );
2156 :
2157 : aGroupObj.insertName( rGroupName, false,
2158 : INetURLObject::LAST_SEGMENT, true,
2159 0 : INetURLObject::ENCODE_ALL );
2160 0 : aGroupURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE );
2161 :
2162 0 : if ( ! Content::create( aGroupURL, maCmdEnv, comphelper::getProcessComponentContext(), aGroup ) )
2163 0 : return sal_False;
2164 :
2165 : // Check, if there's a template with the new name in this group
2166 : // Return false, if there is one
2167 : aGroupObj.insertName( rNewName, false,
2168 : INetURLObject::LAST_SEGMENT, true,
2169 0 : INetURLObject::ENCODE_ALL );
2170 0 : aTemplateURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE );
2171 :
2172 0 : if ( Content::create( aTemplateURL, maCmdEnv, comphelper::getProcessComponentContext(), aTemplate ) )
2173 0 : return sal_False;
2174 :
2175 : // Check, if there's a template with the old name in this group
2176 : // Return false, if there is no template
2177 0 : aGroupObj.removeSegment();
2178 : aGroupObj.insertName( rOldName, false,
2179 : INetURLObject::LAST_SEGMENT, true,
2180 0 : INetURLObject::ENCODE_ALL );
2181 0 : aTemplateURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE );
2182 :
2183 0 : if ( !Content::create( aTemplateURL, maCmdEnv, comphelper::getProcessComponentContext(), aTemplate ) )
2184 0 : return sal_False;
2185 :
2186 0 : OUString aTemplateTargetURL;
2187 0 : OUString aTargetProp( TARGET_URL );
2188 0 : Any aTargetValue;
2189 :
2190 0 : if ( getProperty( aTemplate, aTargetProp, aTargetValue ) )
2191 0 : aTargetValue >>= aTemplateTargetURL;
2192 :
2193 0 : if ( !setTitleForURL( aTemplateTargetURL, rNewName ) )
2194 0 : return sal_False;
2195 :
2196 : // rename the template entry in the cache
2197 0 : OUString aTitleProp( TITLE );
2198 0 : Any aTitleValue;
2199 0 : aTitleValue <<= rNewName;
2200 :
2201 0 : return setProperty( aTemplate, aTitleProp, aTitleValue );
2202 : }
2203 :
2204 : //-----------------------------------------------------------------------------
2205 :
2206 52 : SFX_IMPL_XSERVICEINFO( SfxDocTplService, TEMPLATE_SERVICE_NAME, TEMPLATE_IMPLEMENTATION_NAME )
2207 2 : SFX_IMPL_SINGLEFACTORY( SfxDocTplService )
2208 :
2209 : //-----------------------------------------------------------------------------
2210 4 : SfxDocTplService::SfxDocTplService( const uno::Reference< XMultiServiceFactory >& xFactory )
2211 : {
2212 4 : pImp = new SfxDocTplService_Impl( xFactory );
2213 4 : }
2214 :
2215 : //-----------------------------------------------------------------------------
2216 :
2217 9 : SfxDocTplService::~SfxDocTplService()
2218 : {
2219 3 : delete pImp;
2220 6 : }
2221 :
2222 : //-----------------------------------------------------------------------------
2223 : //--- XLocalizable ---
2224 : //-----------------------------------------------------------------------------
2225 :
2226 4 : Locale SAL_CALL SfxDocTplService::getLocale()
2227 : throw( RUNTIMEEXCEPTION )
2228 : {
2229 4 : return pImp->getLocale();
2230 : }
2231 :
2232 : //-----------------------------------------------------------------------------
2233 :
2234 0 : void SAL_CALL SfxDocTplService::setLocale( const Locale & rLocale )
2235 : throw( RUNTIMEEXCEPTION )
2236 : {
2237 0 : pImp->setLocale( rLocale );
2238 0 : }
2239 :
2240 : //-----------------------------------------------------------------------------
2241 : //--- XDocumentTemplates ---
2242 : //-----------------------------------------------------------------------------
2243 4 : uno::Reference< XCONTENT > SAL_CALL SfxDocTplService::getContent()
2244 : throw( RUNTIMEEXCEPTION )
2245 : {
2246 4 : if ( pImp->init() )
2247 0 : return pImp->getContent().get();
2248 : else
2249 4 : return NULL;
2250 : }
2251 :
2252 : //-----------------------------------------------------------------------------
2253 0 : sal_Bool SAL_CALL SfxDocTplService::storeTemplate( const OUString& GroupName,
2254 : const OUString& TemplateName,
2255 : const uno::Reference< XSTORABLE >& Storable )
2256 : throw( RUNTIMEEXCEPTION )
2257 : {
2258 0 : if ( pImp->init() )
2259 0 : return pImp->storeTemplate( GroupName, TemplateName, Storable );
2260 : else
2261 0 : return sal_False;
2262 : }
2263 :
2264 : //-----------------------------------------------------------------------------
2265 0 : sal_Bool SAL_CALL SfxDocTplService::addTemplate( const OUString& rGroupName,
2266 : const OUString& rTemplateName,
2267 : const OUString& rSourceURL )
2268 : throw( RUNTIMEEXCEPTION )
2269 : {
2270 0 : if ( pImp->init() )
2271 0 : return pImp->addTemplate( rGroupName, rTemplateName, rSourceURL );
2272 : else
2273 0 : return sal_False;
2274 : }
2275 :
2276 : //-----------------------------------------------------------------------------
2277 0 : sal_Bool SAL_CALL SfxDocTplService::removeTemplate( const OUString& rGroupName,
2278 : const OUString& rTemplateName )
2279 : throw( RUNTIMEEXCEPTION )
2280 : {
2281 0 : if ( pImp->init() )
2282 0 : return pImp->removeTemplate( rGroupName, rTemplateName );
2283 : else
2284 0 : return sal_False;
2285 : }
2286 :
2287 : //-----------------------------------------------------------------------------
2288 0 : sal_Bool SAL_CALL SfxDocTplService::renameTemplate( const OUString& rGroupName,
2289 : const OUString& rOldName,
2290 : const OUString& rNewName )
2291 : throw( RUNTIMEEXCEPTION )
2292 : {
2293 0 : if ( rOldName == rNewName )
2294 0 : return sal_True;
2295 :
2296 0 : if ( pImp->init() )
2297 0 : return pImp->renameTemplate( rGroupName, rOldName, rNewName );
2298 : else
2299 0 : return sal_False;
2300 : }
2301 :
2302 : //-----------------------------------------------------------------------------
2303 0 : sal_Bool SAL_CALL SfxDocTplService::addGroup( const OUString& rGroupName )
2304 : throw( RUNTIMEEXCEPTION )
2305 : {
2306 0 : if ( pImp->init() )
2307 0 : return pImp->addGroup( rGroupName );
2308 : else
2309 0 : return sal_False;
2310 : }
2311 :
2312 : //-----------------------------------------------------------------------------
2313 0 : sal_Bool SAL_CALL SfxDocTplService::removeGroup( const OUString& rGroupName )
2314 : throw( RUNTIMEEXCEPTION )
2315 : {
2316 0 : if ( pImp->init() )
2317 0 : return pImp->removeGroup( rGroupName );
2318 : else
2319 0 : return sal_False;
2320 : }
2321 :
2322 : //-----------------------------------------------------------------------------
2323 0 : sal_Bool SAL_CALL SfxDocTplService::renameGroup( const OUString& rOldName,
2324 : const OUString& rNewName )
2325 : throw( RUNTIMEEXCEPTION )
2326 : {
2327 0 : if ( rOldName == rNewName )
2328 0 : return sal_True;
2329 :
2330 0 : if ( pImp->init() )
2331 0 : return pImp->renameGroup( rOldName, rNewName );
2332 : else
2333 0 : return sal_False;
2334 : }
2335 :
2336 : //-----------------------------------------------------------------------------
2337 0 : void SAL_CALL SfxDocTplService::update()
2338 : throw( RUNTIMEEXCEPTION )
2339 : {
2340 0 : if ( pImp->init() )
2341 0 : pImp->update( sal_True );
2342 0 : }
2343 :
2344 : //------------------------------------------------------------------------
2345 :
2346 0 : Updater_Impl::Updater_Impl( SfxDocTplService_Impl* pTemplates )
2347 : {
2348 0 : mpDocTemplates = pTemplates;
2349 0 : }
2350 :
2351 : //------------------------------------------------------------------------
2352 0 : Updater_Impl::~Updater_Impl()
2353 : {
2354 0 : }
2355 :
2356 : //------------------------------------------------------------------------
2357 0 : void SAL_CALL Updater_Impl::run()
2358 : {
2359 0 : mpDocTemplates->doUpdate();
2360 0 : }
2361 :
2362 : //------------------------------------------------------------------------
2363 0 : void SAL_CALL Updater_Impl::onTerminated()
2364 : {
2365 0 : mpDocTemplates->finished();
2366 0 : delete this;
2367 0 : }
2368 :
2369 : //-----------------------------------------------------------------------------
2370 0 : WaitWindow_Impl::WaitWindow_Impl()
2371 0 : : WorkWindow( NULL, WB_BORDER | WB_3DLOOK )
2372 : {
2373 0 : Rectangle aRect = Rectangle( 0, 0, 300, 30000 );
2374 0 : _nTextStyle = TEXT_DRAW_CENTER | TEXT_DRAW_VCENTER | TEXT_DRAW_WORDBREAK | TEXT_DRAW_MULTILINE;
2375 0 : _aText = SfxResId( RID_CNT_STR_WAITING ).toString();
2376 0 : _aRect = GetTextRect( aRect, _aText, _nTextStyle );
2377 0 : aRect = _aRect;
2378 0 : aRect.Right() += 2*X_OFFSET;
2379 0 : aRect.Bottom() += 2*Y_OFFSET;
2380 0 : _aRect.SetPos( Point( X_OFFSET, Y_OFFSET ) );
2381 0 : SetOutputSizePixel( aRect.GetSize() );
2382 0 : Show();
2383 0 : Update();
2384 0 : Flush();
2385 0 : }
2386 :
2387 : //-----------------------------------------------------------------------------
2388 0 : WaitWindow_Impl::~WaitWindow_Impl()
2389 : {
2390 0 : Hide();
2391 0 : }
2392 :
2393 : //-----------------------------------------------------------------------------
2394 0 : void WaitWindow_Impl::Paint( const Rectangle& /*rRect*/ )
2395 : {
2396 0 : DrawText( _aRect, _aText, _nTextStyle );
2397 0 : }
2398 :
2399 : //-----------------------------------------------------------------------------
2400 0 : void SfxDocTplService_Impl::addHierGroup( GroupList_Impl& rList,
2401 : const OUString& rTitle,
2402 : const OUString& rOwnURL )
2403 : {
2404 : // now get the content of the Group
2405 0 : Content aContent;
2406 0 : uno::Reference< XResultSet > xResultSet;
2407 0 : Sequence< OUString > aProps(3);
2408 :
2409 0 : aProps[0] = OUString(TITLE );
2410 0 : aProps[1] = OUString(TARGET_URL );
2411 0 : aProps[2] = OUString(PROPERTY_TYPE );
2412 :
2413 : try
2414 : {
2415 0 : aContent = Content( rOwnURL, maCmdEnv, comphelper::getProcessComponentContext() );
2416 0 : ResultSetInclude eInclude = INCLUDE_DOCUMENTS_ONLY;
2417 0 : xResultSet = aContent.createCursor( aProps, eInclude );
2418 : }
2419 0 : catch ( ContentCreationException& )
2420 : {
2421 : SAL_WARN( "sfx2.doc", "addHierGroup: ContentCreationException" );
2422 : }
2423 0 : catch ( Exception& ) {}
2424 :
2425 0 : if ( xResultSet.is() )
2426 : {
2427 0 : GroupData_Impl *pGroup = new GroupData_Impl( rTitle );
2428 0 : pGroup->setHierarchy( sal_True );
2429 0 : pGroup->setHierarchyURL( rOwnURL );
2430 0 : rList.push_back( pGroup );
2431 :
2432 0 : uno::Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY );
2433 0 : uno::Reference< XRow > xRow( xResultSet, UNO_QUERY );
2434 :
2435 : try
2436 : {
2437 0 : while ( xResultSet->next() )
2438 : {
2439 0 : sal_Bool bUpdateType = sal_False;
2440 : DocTemplates_EntryData_Impl *pData;
2441 :
2442 0 : OUString aTitle( xRow->getString( 1 ) );
2443 0 : OUString aTargetDir( xRow->getString( 2 ) );
2444 0 : OUString aType( xRow->getString( 3 ) );
2445 0 : OUString aHierURL = xContentAccess->queryContentIdentifierString();
2446 :
2447 0 : if ( aType.isEmpty() )
2448 : {
2449 0 : OUString aTmpTitle;
2450 :
2451 0 : sal_Bool bDocHasTitle = sal_False;
2452 0 : if( !getTitleFromURL( aTargetDir, aTmpTitle, aType, bDocHasTitle ) )
2453 : {
2454 : SAL_WARN( "sfx2.doc", "addHierGroup(): template of alien format" );
2455 0 : continue;
2456 : }
2457 :
2458 0 : if ( !aType.isEmpty() )
2459 0 : bUpdateType = sal_True;
2460 : }
2461 :
2462 0 : pData = pGroup->addEntry( aTitle, aTargetDir, aType, aHierURL );
2463 0 : pData->setUpdateType( bUpdateType );
2464 0 : }
2465 : }
2466 0 : catch ( Exception& ) {}
2467 0 : }
2468 0 : }
2469 :
2470 : //-----------------------------------------------------------------------------
2471 0 : void SfxDocTplService_Impl::addFsysGroup( GroupList_Impl& rList,
2472 : const OUString& rTitle,
2473 : const OUString& rUITitle,
2474 : const OUString& rOwnURL,
2475 : sal_Bool bWriteableGroup )
2476 : {
2477 0 : ::rtl::OUString aTitle;
2478 :
2479 0 : if ( rUITitle.isEmpty() )
2480 : {
2481 : // reserved FS names that should not be used
2482 0 : if ( rTitle.compareToAscii( "wizard" ) == 0 )
2483 : return;
2484 0 : else if ( rTitle.compareToAscii( "internal" ) == 0 )
2485 : return;
2486 :
2487 0 : aTitle = getLongName( rTitle );
2488 : }
2489 : else
2490 0 : aTitle = rUITitle;
2491 :
2492 0 : if ( aTitle.isEmpty() )
2493 : return;
2494 :
2495 0 : GroupData_Impl* pGroup = NULL;
2496 0 : for ( size_t i = 0, n = rList.size(); i < n; ++i )
2497 : {
2498 0 : if ( rList[ i ]->getTitle() == aTitle )
2499 : {
2500 0 : pGroup = rList[ i ];
2501 0 : break;
2502 : }
2503 : }
2504 :
2505 0 : if ( !pGroup )
2506 : {
2507 0 : pGroup = new GroupData_Impl( aTitle );
2508 0 : rList.push_back( pGroup );
2509 : }
2510 :
2511 0 : if ( bWriteableGroup )
2512 0 : pGroup->setTargetURL( rOwnURL );
2513 :
2514 0 : pGroup->setInUse();
2515 :
2516 : // now get the content of the Group
2517 0 : Content aContent;
2518 0 : uno::Reference< XResultSet > xResultSet;
2519 0 : Sequence< OUString > aProps(1);
2520 0 : aProps[0] = OUString(TITLE );
2521 :
2522 : try
2523 : {
2524 : // this method is only used during checking of the available template-folders
2525 : // that should happen quietly
2526 0 : uno::Reference< XCommandEnvironment > aQuietEnv;
2527 0 : aContent = Content( rOwnURL, aQuietEnv, comphelper::getProcessComponentContext() );
2528 0 : ResultSetInclude eInclude = INCLUDE_DOCUMENTS_ONLY;
2529 0 : xResultSet = aContent.createCursor( aProps, eInclude );
2530 : }
2531 0 : catch ( Exception& ) {}
2532 :
2533 0 : if ( xResultSet.is() )
2534 : {
2535 0 : uno::Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY );
2536 0 : uno::Reference< XRow > xRow( xResultSet, UNO_QUERY );
2537 :
2538 : try
2539 : {
2540 0 : while ( xResultSet->next() )
2541 : {
2542 0 : OUString aChildTitle( xRow->getString( 1 ) );
2543 0 : OUString aTargetURL = xContentAccess->queryContentIdentifierString();
2544 0 : OUString aType;
2545 0 : OUString aHierURL;
2546 :
2547 0 : if ( aChildTitle.compareToAscii( "sfx.tlx" ) == 0 || aChildTitle == "groupuinames.xml" )
2548 0 : continue;
2549 :
2550 0 : sal_Bool bDocHasTitle = sal_False;
2551 0 : if( !getTitleFromURL( aTargetURL, aChildTitle, aType, bDocHasTitle ) )
2552 0 : continue;
2553 :
2554 0 : pGroup->addEntry( aChildTitle, aTargetURL, aType, aHierURL );
2555 0 : }
2556 : }
2557 0 : catch ( Exception& ) {}
2558 0 : }
2559 : }
2560 :
2561 : // -----------------------------------------------------------------------
2562 0 : void SfxDocTplService_Impl::createFromContent( GroupList_Impl& rList,
2563 : Content &rContent,
2564 : sal_Bool bHierarchy,
2565 : sal_Bool bWriteableContent )
2566 : {
2567 0 : OUString aTargetURL = rContent.get()->getIdentifier()->getContentIdentifier();
2568 :
2569 : // when scanning the file system, we have to add the 'standard' group, too
2570 0 : if ( ! bHierarchy )
2571 : {
2572 0 : OUString aUIStdTitle = getLongName( OUString( STANDARD_FOLDER ) );
2573 0 : addFsysGroup( rList, ::rtl::OUString(), aUIStdTitle, aTargetURL, bWriteableContent );
2574 : }
2575 :
2576 : // search for predefined UI names
2577 0 : INetURLObject aLayerObj( aTargetURL );
2578 :
2579 : // TODO/LATER: Use hashmap in future
2580 0 : uno::Sequence< beans::StringPair > aUINames;
2581 0 : if ( !bHierarchy )
2582 0 : aUINames = ReadUINamesForTemplateDir_Impl( aLayerObj.GetMainURL( INetURLObject::NO_DECODE ) );
2583 :
2584 0 : uno::Reference< XResultSet > xResultSet;
2585 0 : Sequence< OUString > aProps(1);
2586 0 : aProps[0] = OUString(TITLE );
2587 :
2588 : try
2589 : {
2590 0 : ResultSetInclude eInclude = INCLUDE_FOLDERS_ONLY;
2591 0 : xResultSet = rContent.createCursor( aProps, eInclude );
2592 : }
2593 0 : catch ( Exception& ) {}
2594 :
2595 0 : if ( xResultSet.is() )
2596 : {
2597 0 : uno::Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY );
2598 0 : uno::Reference< XRow > xRow( xResultSet, UNO_QUERY );
2599 :
2600 : try
2601 : {
2602 0 : while ( xResultSet->next() )
2603 : {
2604 : // TODO/LATER: clarify the encoding of the Title
2605 0 : OUString aTitle( xRow->getString( 1 ) );
2606 0 : OUString aTargetSubfolderURL( xContentAccess->queryContentIdentifierString() );
2607 :
2608 0 : if ( bHierarchy )
2609 0 : addHierGroup( rList, aTitle, aTargetSubfolderURL );
2610 : else
2611 : {
2612 0 : ::rtl::OUString aUITitle;
2613 0 : for ( sal_Int32 nInd = 0; nInd < aUINames.getLength(); nInd++ )
2614 0 : if ( aUINames[nInd].First.equals( aTitle ) )
2615 : {
2616 0 : aUITitle = aUINames[nInd].Second;
2617 0 : break;
2618 : }
2619 :
2620 0 : addFsysGroup( rList, aTitle, aUITitle, aTargetSubfolderURL, bWriteableContent );
2621 : }
2622 0 : }
2623 : }
2624 0 : catch ( Exception& ) {}
2625 0 : }
2626 0 : }
2627 :
2628 : //-----------------------------------------------------------------------------
2629 0 : void SfxDocTplService_Impl::removeFromHierarchy( DocTemplates_EntryData_Impl *pData )
2630 : {
2631 0 : Content aTemplate;
2632 :
2633 0 : if ( Content::create( pData->getHierarchyURL(), maCmdEnv, comphelper::getProcessComponentContext(), aTemplate ) )
2634 : {
2635 0 : removeContent( aTemplate );
2636 0 : }
2637 0 : }
2638 :
2639 : //-----------------------------------------------------------------------------
2640 0 : void SfxDocTplService_Impl::addToHierarchy( GroupData_Impl *pGroup,
2641 : DocTemplates_EntryData_Impl *pData )
2642 : {
2643 0 : Content aGroup, aTemplate;
2644 :
2645 0 : if ( ! Content::create( pGroup->getHierarchyURL(), maCmdEnv, comphelper::getProcessComponentContext(), aGroup ) )
2646 : return;
2647 :
2648 : // Check, if there's a template with the given name in this group
2649 : // Return if there is already a template
2650 0 : INetURLObject aGroupObj( pGroup->getHierarchyURL() );
2651 :
2652 0 : aGroupObj.insertName( pData->getTitle(), false,
2653 : INetURLObject::LAST_SEGMENT, true,
2654 0 : INetURLObject::ENCODE_ALL );
2655 :
2656 0 : OUString aTemplateURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE );
2657 :
2658 0 : if ( Content::create( aTemplateURL, maCmdEnv, comphelper::getProcessComponentContext(), aTemplate ) )
2659 : return;
2660 :
2661 0 : addEntry( aGroup, pData->getTitle(),
2662 0 : pData->getTargetURL(),
2663 0 : pData->getType() );
2664 : }
2665 :
2666 : //-----------------------------------------------------------------------------
2667 0 : void SfxDocTplService_Impl::updateData( DocTemplates_EntryData_Impl *pData )
2668 : {
2669 0 : Content aTemplate;
2670 :
2671 0 : if ( ! Content::create( pData->getHierarchyURL(), maCmdEnv, comphelper::getProcessComponentContext(), aTemplate ) )
2672 0 : return;
2673 :
2674 0 : OUString aPropName;
2675 :
2676 0 : if ( pData->getUpdateType() )
2677 : {
2678 0 : aPropName = OUString( PROPERTY_TYPE );
2679 0 : setProperty( aTemplate, aPropName, makeAny( pData->getType() ) );
2680 : }
2681 :
2682 0 : if ( pData->getUpdateLink() )
2683 : {
2684 0 : aPropName = OUString( TARGET_URL );
2685 0 : setProperty( aTemplate, aPropName, makeAny( pData->getTargetURL() ) );
2686 0 : }
2687 : }
2688 :
2689 : //-----------------------------------------------------------------------------
2690 0 : void SfxDocTplService_Impl::addGroupToHierarchy( GroupData_Impl *pGroup )
2691 : {
2692 0 : OUString aAdditionalProp( TARGET_DIR_URL );
2693 0 : Content aGroup;
2694 :
2695 0 : INetURLObject aNewGroupObj( maRootURL );
2696 0 : aNewGroupObj.insertName( pGroup->getTitle(), false,
2697 : INetURLObject::LAST_SEGMENT, true,
2698 0 : INetURLObject::ENCODE_ALL );
2699 :
2700 0 : OUString aNewGroupURL = aNewGroupObj.GetMainURL( INetURLObject::NO_DECODE );
2701 :
2702 0 : if ( createFolder( aNewGroupURL, sal_False, sal_False, aGroup ) )
2703 : {
2704 0 : setProperty( aGroup, aAdditionalProp, makeAny( pGroup->getTargetURL() ) );
2705 0 : pGroup->setHierarchyURL( aNewGroupURL );
2706 :
2707 0 : sal_uIntPtr nCount = pGroup->count();
2708 0 : for ( sal_uIntPtr i=0; i<nCount; i++ )
2709 : {
2710 0 : DocTemplates_EntryData_Impl *pData = pGroup->getEntry( i );
2711 0 : addToHierarchy( pGroup, pData ); // add entry to hierarchy
2712 : }
2713 0 : }
2714 0 : }
2715 :
2716 : //-----------------------------------------------------------------------------
2717 0 : void SfxDocTplService_Impl::removeFromHierarchy( GroupData_Impl *pGroup )
2718 : {
2719 0 : Content aGroup;
2720 :
2721 0 : if ( Content::create( pGroup->getHierarchyURL(), maCmdEnv, comphelper::getProcessComponentContext(), aGroup ) )
2722 : {
2723 0 : removeContent( aGroup );
2724 0 : }
2725 0 : }
2726 :
2727 : // -----------------------------------------------------------------------
2728 0 : GroupData_Impl::GroupData_Impl( const OUString& rTitle )
2729 : {
2730 0 : maTitle = rTitle;
2731 0 : mbInUse = sal_False;
2732 0 : mbInHierarchy = sal_False;
2733 0 : }
2734 :
2735 : // -----------------------------------------------------------------------
2736 0 : GroupData_Impl::~GroupData_Impl()
2737 : {
2738 0 : for ( size_t i = 0, n = maEntries.size(); i < n; ++i )
2739 0 : delete maEntries[ i ];
2740 0 : maEntries.clear();
2741 0 : }
2742 :
2743 : // -----------------------------------------------------------------------
2744 0 : DocTemplates_EntryData_Impl* GroupData_Impl::addEntry( const OUString& rTitle,
2745 : const OUString& rTargetURL,
2746 : const OUString& rType,
2747 : const OUString& rHierURL )
2748 : {
2749 0 : DocTemplates_EntryData_Impl* pData = NULL;
2750 0 : bool EntryFound = false;
2751 :
2752 0 : for ( size_t i = 0, n = maEntries.size(); i < n; ++i )
2753 : {
2754 0 : pData = maEntries[ i ];
2755 0 : if ( pData->getTitle() == rTitle )
2756 : {
2757 0 : EntryFound = true;
2758 0 : break;
2759 : }
2760 : }
2761 :
2762 0 : if ( !EntryFound )
2763 : {
2764 0 : pData = new DocTemplates_EntryData_Impl( rTitle );
2765 0 : pData->setTargetURL( rTargetURL );
2766 0 : pData->setType( rType );
2767 0 : if ( !rHierURL.isEmpty() )
2768 : {
2769 0 : pData->setHierarchyURL( rHierURL );
2770 0 : pData->setHierarchy( sal_True );
2771 : }
2772 0 : maEntries.push_back( pData );
2773 : }
2774 : else
2775 : {
2776 0 : if ( !rHierURL.isEmpty() )
2777 : {
2778 0 : pData->setHierarchyURL( rHierURL );
2779 0 : pData->setHierarchy( sal_True );
2780 : }
2781 :
2782 0 : if ( pData->getInHierarchy() )
2783 0 : pData->setInUse();
2784 :
2785 0 : if ( rTargetURL != pData->getTargetURL() )
2786 : {
2787 0 : pData->setTargetURL( rTargetURL );
2788 0 : pData->setUpdateLink( sal_True );
2789 : }
2790 : }
2791 :
2792 0 : return pData;
2793 : }
2794 :
2795 : // -----------------------------------------------------------------------
2796 0 : DocTemplates_EntryData_Impl::DocTemplates_EntryData_Impl( const OUString& rTitle )
2797 : {
2798 0 : maTitle = rTitle;
2799 0 : mbInUse = sal_False;
2800 0 : mbInHierarchy = sal_False;
2801 0 : mbUpdateType = sal_False;
2802 0 : mbUpdateLink = sal_False;
2803 0 : }
2804 :
2805 : // -----------------------------------------------------------------------
2806 4 : SfxURLRelocator_Impl::SfxURLRelocator_Impl( uno::Reference< XMultiServiceFactory > xFactory )
2807 4 : : mxFactory( xFactory )
2808 : {
2809 4 : }
2810 :
2811 : // -----------------------------------------------------------------------
2812 3 : SfxURLRelocator_Impl::~SfxURLRelocator_Impl()
2813 : {
2814 3 : }
2815 :
2816 : // -----------------------------------------------------------------------
2817 0 : void SfxURLRelocator_Impl::initOfficeInstDirs()
2818 : {
2819 0 : if ( !mxOfficeInstDirs.is() )
2820 : {
2821 0 : osl::MutexGuard aGuard( maMutex );
2822 0 : if ( !mxOfficeInstDirs.is() )
2823 : {
2824 : OSL_ENSURE( mxFactory.is(), "No service manager!" );
2825 :
2826 : uno::Reference< XComponentContext > xCtx(
2827 0 : comphelper::getComponentContext( mxFactory ) );
2828 :
2829 0 : xCtx->getValueByName(
2830 : rtl::OUString(
2831 : "/singletons/"
2832 0 : "com.sun.star.util.theOfficeInstallationDirectories" ) )
2833 0 : >>= mxOfficeInstDirs;
2834 :
2835 : OSL_ENSURE( mxOfficeInstDirs.is(),
2836 : "Unable to obtain office installation directory "
2837 0 : "singleton!" );
2838 0 : }
2839 : }
2840 0 : }
2841 :
2842 : // -----------------------------------------------------------------------
2843 0 : void SfxURLRelocator_Impl::implExpandURL( ::rtl::OUString& io_url )
2844 : {
2845 0 : const INetURLObject aParser( io_url );
2846 0 : if ( aParser.GetProtocol() != INET_PROT_VND_SUN_STAR_EXPAND )
2847 0 : return;
2848 :
2849 0 : io_url = aParser.GetURLPath( INetURLObject::DECODE_WITH_CHARSET );
2850 : try
2851 : {
2852 0 : if ( !mxMacroExpander.is() )
2853 : {
2854 0 : ::comphelper::ComponentContext aContext( mxFactory );
2855 0 : mxMacroExpander.set( aContext.getSingleton( "com.sun.star.util.theMacroExpander" ), UNO_QUERY_THROW );
2856 : }
2857 0 : io_url = mxMacroExpander->expandMacros( io_url );
2858 : }
2859 0 : catch( const Exception& )
2860 : {
2861 : DBG_UNHANDLED_EXCEPTION();
2862 0 : }
2863 : }
2864 :
2865 : // -----------------------------------------------------------------------
2866 0 : void SfxURLRelocator_Impl::makeRelocatableURL( rtl::OUString & rURL )
2867 : {
2868 0 : if ( !rURL.isEmpty() )
2869 : {
2870 0 : initOfficeInstDirs();
2871 0 : implExpandURL( rURL );
2872 0 : rURL = mxOfficeInstDirs->makeRelocatableURL( rURL );
2873 : }
2874 0 : }
2875 :
2876 : // -----------------------------------------------------------------------
2877 0 : void SfxURLRelocator_Impl::makeAbsoluteURL( rtl::OUString & rURL )
2878 : {
2879 0 : if ( !rURL.isEmpty() )
2880 : {
2881 0 : initOfficeInstDirs();
2882 0 : implExpandURL( rURL );
2883 0 : rURL = mxOfficeInstDirs->makeAbsoluteURL( rURL );
2884 : }
2885 0 : }
2886 :
2887 :
2888 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|