LCOV - code coverage report
Current view: top level - sfx2/source/doc - doctemplates.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 88 1284 6.9 %
Date: 2015-06-13 12:38:46 Functions: 20 121 16.5 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.11