1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_comphelper.hxx"
26 
27 #include "comphelper_module.hxx"
28 
29 /**************************************************************************
30                                 TODO
31  **************************************************************************
32 
33  *************************************************************************/
34 
35 #include "osl/file.hxx"
36 #include "com/sun/star/beans/XPropertySet.hpp"
37 #include "com/sun/star/util/XMacroExpander.hpp"
38 
39 #include "officeinstallationdirectories.hxx"
40 
41 using namespace com::sun::star;
42 
43 using namespace comphelper;
44 
45 //=========================================================================
46 // helpers
47 //=========================================================================
48 
49 //=========================================================================
makeCanonicalFileURL(rtl::OUString & rURL)50 static bool makeCanonicalFileURL( rtl::OUString & rURL )
51 {
52     OSL_ENSURE( rURL.matchAsciiL( "file:", sizeof( "file:" ) - 1 , 0 ) ,
53                 "File URL expected!" );
54 
55     rtl::OUString aNormalizedURL;
56     if ( osl::FileBase::getAbsoluteFileURL( rtl::OUString(),
57                                             rURL,
58                                             aNormalizedURL )
59             == osl::DirectoryItem::E_None )
60     {
61         osl::DirectoryItem aDirItem;
62         if ( osl::DirectoryItem::get( aNormalizedURL, aDirItem )
63                 == osl::DirectoryItem::E_None )
64         {
65             osl::FileStatus aFileStatus( FileStatusMask_FileURL );
66 
67             if ( aDirItem.getFileStatus( aFileStatus )
68                     == osl::DirectoryItem::E_None )
69             {
70                 aNormalizedURL = aFileStatus.getFileURL();
71 
72                 if ( !aNormalizedURL.isEmpty() )
73                 {
74                     if ( aNormalizedURL
75                             .getStr()[ aNormalizedURL.getLength() - 1 ]
76                                 != sal_Unicode( '/' ) )
77                         rURL = aNormalizedURL;
78                     else
79                         rURL = aNormalizedURL
80                                 .copy( 0, aNormalizedURL.getLength() - 1 );
81 
82                     return true;
83                 }
84             }
85         }
86     }
87     return false;
88 }
89 
90 //=========================================================================
91 //=========================================================================
92 //
93 // OfficeInstallationDirectories Implementation.
94 //
95 //=========================================================================
96 //=========================================================================
97 
OfficeInstallationDirectories(const uno::Reference<uno::XComponentContext> & xCtx)98 OfficeInstallationDirectories::OfficeInstallationDirectories(
99         const uno::Reference< uno::XComponentContext > & xCtx )
100 : m_aOfficeBrandDirMacro( RTL_CONSTASCII_USTRINGPARAM( "$(brandbaseurl)" ) ),
101   m_aOfficeBaseDirMacro( RTL_CONSTASCII_USTRINGPARAM( "$(baseinsturl)" ) ),
102   m_aUserDirMacro( RTL_CONSTASCII_USTRINGPARAM( "$(userdataurl)" ) ),
103   m_xCtx( xCtx ),
104   m_pOfficeBrandDir( 0 ),
105   m_pOfficeBaseDir( 0 ),
106   m_pUserDir( 0 )
107 {
108 }
109 
110 //=========================================================================
111 // virtual
~OfficeInstallationDirectories()112 OfficeInstallationDirectories::~OfficeInstallationDirectories()
113 {
114     delete m_pOfficeBrandDir;
115     delete m_pOfficeBaseDir;
116     delete m_pUserDir;
117 }
118 
119 //=========================================================================
120 // util::XOfficeInstallationDirectories
121 //=========================================================================
122 
123 // virtual
124 rtl::OUString SAL_CALL
getOfficeInstallationDirectoryURL()125 OfficeInstallationDirectories::getOfficeInstallationDirectoryURL()
126     throw ( uno::RuntimeException )
127 {
128     initDirs();
129     return rtl::OUString( *m_pOfficeBrandDir );
130 }
131 
132 //=========================================================================
133 // virtual
134 rtl::OUString SAL_CALL
getOfficeUserDataDirectoryURL()135 OfficeInstallationDirectories::getOfficeUserDataDirectoryURL()
136     throw ( uno::RuntimeException )
137 {
138     initDirs();
139     return rtl::OUString( *m_pUserDir );
140 }
141 
142 
143 //=========================================================================
144 // virtual
145 rtl::OUString SAL_CALL
makeRelocatableURL(const rtl::OUString & URL)146 OfficeInstallationDirectories::makeRelocatableURL( const rtl::OUString& URL )
147     throw ( uno::RuntimeException )
148 {
149     if ( !URL.isEmpty() )
150     {
151         initDirs();
152 
153         rtl::OUString aCanonicalURL( URL );
154         makeCanonicalFileURL( aCanonicalURL );
155 
156         sal_Int32 nIndex = aCanonicalURL.indexOf( *m_pOfficeBrandDir );
157         if ( nIndex  != -1 )
158         {
159             return rtl::OUString(
160                 URL.replaceAt( nIndex,
161                                m_pOfficeBrandDir->getLength(),
162                                m_aOfficeBrandDirMacro ) );
163         }
164         else
165         {
166             nIndex = aCanonicalURL.indexOf( *m_pOfficeBaseDir );
167             if ( nIndex  != -1 )
168             {
169                 return rtl::OUString(
170                     URL.replaceAt( nIndex,
171                                    m_pOfficeBaseDir->getLength(),
172                                    m_aOfficeBaseDirMacro ) );
173             }
174             else
175             {
176                 nIndex = aCanonicalURL.indexOf( *m_pUserDir );
177                 if ( nIndex  != -1 )
178                 {
179                     return rtl::OUString(
180                         URL.replaceAt( nIndex,
181                                        m_pUserDir->getLength(),
182                                        m_aUserDirMacro ) );
183                 }
184             }
185         }
186     }
187     return rtl::OUString( URL );
188 }
189 
190 //=========================================================================
191 // virtual
192 rtl::OUString SAL_CALL
makeAbsoluteURL(const rtl::OUString & URL)193 OfficeInstallationDirectories::makeAbsoluteURL( const rtl::OUString& URL )
194     throw ( uno::RuntimeException )
195 {
196     if ( !URL.isEmpty() )
197     {
198         sal_Int32 nIndex = URL.indexOf( m_aOfficeBrandDirMacro );
199         if ( nIndex != -1 )
200         {
201             initDirs();
202 
203             return rtl::OUString(
204                 URL.replaceAt( nIndex,
205                                m_aOfficeBrandDirMacro.getLength(),
206                                *m_pOfficeBrandDir ) );
207         }
208         else
209         {
210             nIndex = URL.indexOf( m_aOfficeBaseDirMacro );
211             if ( nIndex != -1 )
212             {
213                 initDirs();
214 
215                 return rtl::OUString(
216                     URL.replaceAt( nIndex,
217                                    m_aOfficeBaseDirMacro.getLength(),
218                                    *m_pOfficeBaseDir ) );
219             }
220             else
221             {
222                 nIndex = URL.indexOf( m_aUserDirMacro );
223                 if ( nIndex != -1 )
224                 {
225                     initDirs();
226 
227                     return rtl::OUString(
228                         URL.replaceAt( nIndex,
229                                        m_aUserDirMacro.getLength(),
230                                        *m_pUserDir ) );
231                 }
232             }
233         }
234     }
235     return rtl::OUString( URL );
236 }
237 
238 //=========================================================================
239 // lang::XServiceInfo
240 //=========================================================================
241 
242 // virtual
243 rtl::OUString SAL_CALL
getImplementationName()244 OfficeInstallationDirectories::getImplementationName()
245     throw ( uno::RuntimeException )
246 {
247     return getImplementationName_static();
248 }
249 
250 //=========================================================================
251 // virtual
252 sal_Bool SAL_CALL
supportsService(const rtl::OUString & ServiceName)253 OfficeInstallationDirectories::supportsService( const rtl::OUString& ServiceName )
254     throw ( uno::RuntimeException )
255 {
256     const uno::Sequence< rtl::OUString > & aNames
257         = getSupportedServiceNames();
258     const rtl::OUString * p = aNames.getConstArray();
259     for ( sal_Int32 nPos = 0; nPos < aNames.getLength(); nPos++ )
260     {
261         if ( p[ nPos ].equals( ServiceName ) )
262             return sal_True;
263     }
264     return sal_False;
265 
266 }
267 
268 //=========================================================================
269 // virtual
270 uno::Sequence< ::rtl::OUString > SAL_CALL
getSupportedServiceNames()271 OfficeInstallationDirectories::getSupportedServiceNames()
272     throw ( uno::RuntimeException )
273 {
274     return getSupportedServiceNames_static();
275 }
276 
277 //=========================================================================
278 // static
279 rtl::OUString SAL_CALL
getImplementationName_static()280 OfficeInstallationDirectories::getImplementationName_static()
281 {
282     return rtl::OUString(
283         RTL_CONSTASCII_USTRINGPARAM(
284             "com.sun.star.comp.util.OfficeInstallationDirectories" ) );
285 }
286 
287 //=========================================================================
288 // static
289 uno::Sequence< ::rtl::OUString > SAL_CALL
getSupportedServiceNames_static()290 OfficeInstallationDirectories::getSupportedServiceNames_static()
291 {
292     const rtl::OUString aServiceName(
293         RTL_CONSTASCII_USTRINGPARAM(
294             "com.sun.star.util.OfficeInstallationDirectories" ) );
295     return uno::Sequence< rtl::OUString >( &aServiceName, 1 );
296 }
297 
298 //=========================================================================
299 // static
getSingletonName_static()300 rtl::OUString SAL_CALL OfficeInstallationDirectories::getSingletonName_static()
301 {
302     return rtl::OUString(
303         RTL_CONSTASCII_USTRINGPARAM(
304             "com.sun.star.util.theOfficeInstallationDirectories" ) );
305 }
306 
307 //=========================================================================
308 // static
309 uno::Reference< uno::XInterface > SAL_CALL
Create(const uno::Reference<uno::XComponentContext> & rxContext)310 OfficeInstallationDirectories::Create(
311         const uno::Reference< uno::XComponentContext > & rxContext )
312 {
313     return static_cast< cppu::OWeakObject * >(
314         new OfficeInstallationDirectories( rxContext ) );
315 }
316 
317 //=========================================================================
318 // non-UNO
319 //=========================================================================
320 
initDirs()321 void OfficeInstallationDirectories::initDirs()
322 {
323     if ( m_pOfficeBrandDir == 0 )
324     {
325         osl::MutexGuard aGuard( m_aMutex );
326         if ( m_pOfficeBrandDir == 0 )
327         {
328             m_pOfficeBrandDir = new rtl::OUString;
329             m_pOfficeBaseDir  = new rtl::OUString;
330             m_pUserDir        = new rtl::OUString;
331 
332             uno::Reference< util::XMacroExpander > xExpander;
333 
334             m_xCtx->getValueByName(
335                 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
336                     "/singletons/com.sun.star.util.theMacroExpander" ) ) )
337             >>= xExpander;
338 
339             OSL_ENSURE( xExpander.is(),
340                         "Unable to obtain macro expander singleton!" );
341 
342             if ( xExpander.is() )
343             {
344                 *m_pOfficeBrandDir =
345                     xExpander->expandMacros(
346                          rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "$OOO_BASE_DIR" ) ) );
347 
348                 OSL_ENSURE( !m_pOfficeBrandDir->isEmpty(),
349                             "Unable to obtain office brand installation directory!" );
350 
351                 makeCanonicalFileURL( *m_pOfficeBrandDir );
352 
353                 *m_pOfficeBaseDir = *m_pOfficeBrandDir;
354                 //     xExpander->expandMacros(
355                 //         rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
356                 //             "${$OOO_BASE_DIR/program/" SAL_CONFIGFILE( "bootstrap" ) ":BaseInstallation}" ) ) );
357 
358                 // OSL_ENSURE( m_pOfficeBaseDir->getLength() > 0,
359                 //             "Unable to obtain office base installation directory!" );
360 
361                 makeCanonicalFileURL( *m_pOfficeBaseDir );
362 
363                 *m_pUserDir =
364                     xExpander->expandMacros(
365                         rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
366                             "${$OOO_BASE_DIR/program/" SAL_CONFIGFILE( "bootstrap" ) ":UserInstallation}" ) ) );
367 
368                 OSL_ENSURE( !m_pUserDir->isEmpty(),
369                             "Unable to obtain office user data directory!" );
370 
371                 makeCanonicalFileURL( *m_pUserDir );
372             }
373         }
374     }
375 }
376 
createRegistryInfo_OfficeInstallationDirectories()377 void createRegistryInfo_OfficeInstallationDirectories()
378 {
379     static ::comphelper::module::OSingletonRegistration< OfficeInstallationDirectories > aAutoRegistration;
380 }
381