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