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

Generated by: LCOV version 1.10