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