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