xref: /trunk/main/xmlhelp/source/cxxhelp/provider/provider.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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_xmlhelp.hxx"
30 
31 /**************************************************************************
32                                 TODO
33  **************************************************************************
34 
35  *************************************************************************/
36 
37 #include <stdio.h>
38 #include <osl/file.hxx>
39 #ifndef _VOS_DIAGNOSE_HXX_
40 #include <vos/diagnose.hxx>
41 #endif
42 #include <ucbhelper/contentidentifier.hxx>
43 #include <com/sun/star/frame/XConfigManager.hpp>
44 #ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBBUTE_HPP_
45 #include <com/sun/star/beans/PropertyAttribute.hpp>
46 #endif
47 #include <com/sun/star/beans/PropertyValue.hpp>
48 #include <com/sun/star/container/XContainer.hpp>
49 #include <com/sun/star/container/XNameAccess.hpp>
50 #include <com/sun/star/container/XNameReplace.hpp>
51 #include <com/sun/star/uno/XComponentContext.hpp>
52 #include <com/sun/star/beans/XPropertySet.hpp>
53 #include <rtl/bootstrap.hxx>
54 
55 #include "databases.hxx"
56 #include "provider.hxx"
57 #include "content.hxx"
58 #include "databases.hxx"
59 
60 using namespace com::sun::star;
61 using namespace chelp;
62 
63 //=========================================================================
64 //=========================================================================
65 //
66 // ContentProvider Implementation.
67 //
68 //=========================================================================
69 //=========================================================================
70 
71 ContentProvider::ContentProvider(
72     const uno::Reference< lang::XMultiServiceFactory >& rSMgr )
73     : ::ucbhelper::ContentProviderImplHelper( rSMgr ),
74         isInitialized( false ),
75         m_aScheme( rtl::OUString::createFromAscii( MYUCP_URL_SCHEME ) ),
76         m_pDatabases( 0 )
77 {
78 }
79 
80 //=========================================================================
81 // virtual
82 ContentProvider::~ContentProvider()
83 {
84     delete m_pDatabases;
85 }
86 
87 //=========================================================================
88 //
89 // XInterface methods.
90 //
91 //=========================================================================
92 
93 XINTERFACE_IMPL_6( ContentProvider,
94                    lang::XTypeProvider,
95                    lang::XServiceInfo,
96                    ucb::XContentProvider,
97                    lang::XComponent,
98                    lang::XEventListener, /* base of XContainerListener */
99                    container::XContainerListener);
100 
101 //=========================================================================
102 //
103 // XTypeProvider methods.
104 //
105 //=========================================================================
106 
107 XTYPEPROVIDER_IMPL_5( ContentProvider,
108                       lang::XTypeProvider,
109                       lang::XServiceInfo,
110                       ucb::XContentProvider,
111                       lang::XComponent,
112                       container::XContainerListener);
113 
114 //=========================================================================
115 //
116 // XServiceInfo methods.
117 //
118 //=========================================================================
119 
120 rtl::OUString SAL_CALL ContentProvider::getImplementationName()
121     throw( uno::RuntimeException )
122 {
123     return getImplementationName_Static();
124 }
125 
126 rtl::OUString ContentProvider::getImplementationName_Static()
127 {
128     return rtl::OUString::createFromAscii("CHelpContentProvider" );
129 }
130 
131 sal_Bool SAL_CALL
132 ContentProvider::supportsService(const rtl::OUString& ServiceName )
133     throw( uno::RuntimeException )
134 {
135     uno::Sequence< rtl::OUString > aSNL = getSupportedServiceNames();
136     const rtl::OUString* pArray = aSNL.getArray();
137     for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
138     {
139         if( pArray[ i ] == ServiceName )
140             return sal_True;
141     }
142 
143     return sal_False;
144 }
145 
146 uno::Sequence< rtl::OUString > SAL_CALL
147 ContentProvider::getSupportedServiceNames()
148     throw( uno::RuntimeException )
149 {
150     return getSupportedServiceNames_Static();
151 }
152 
153 static uno::Reference< uno::XInterface > SAL_CALL
154 ContentProvider_CreateInstance(
155         const uno::Reference< lang::XMultiServiceFactory> & rSMgr )
156     throw( uno::Exception )
157 {
158     lang::XServiceInfo * pX = static_cast< lang::XServiceInfo * >(
159         new ContentProvider( rSMgr ) );
160     return uno::Reference< uno::XInterface >::query( pX );
161 }
162 
163 uno::Sequence< rtl::OUString >
164 ContentProvider::getSupportedServiceNames_Static()
165 {
166     uno::Sequence< rtl::OUString > aSNS( 2 );
167     aSNS.getArray()[ 0 ] =
168         rtl::OUString::createFromAscii(
169             MYUCP_CONTENT_PROVIDER_SERVICE_NAME1 );
170     aSNS.getArray()[ 1 ] =
171         rtl::OUString::createFromAscii(
172             MYUCP_CONTENT_PROVIDER_SERVICE_NAME2 );
173 
174     return aSNS;
175 }
176 
177 //=========================================================================
178 //
179 // Service factory implementation.
180 //
181 //=========================================================================
182 
183 ONE_INSTANCE_SERVICE_FACTORY_IMPL( ContentProvider );
184 
185 //=========================================================================
186 //
187 // XContentProvider methods.
188 //
189 //=========================================================================
190 
191 // virtual
192 uno::Reference< ucb::XContent > SAL_CALL
193 ContentProvider::queryContent(
194         const uno::Reference< ucb::XContentIdentifier >& xCanonicId )
195     throw( ucb::IllegalIdentifierException, uno::RuntimeException )
196 {
197     if ( !xCanonicId->getContentProviderScheme()
198              .equalsIgnoreAsciiCase( m_aScheme ) )
199     {   // Wrong URL-scheme
200         throw ucb::IllegalIdentifierException();
201     }
202 
203     {
204         osl::MutexGuard aGuard( m_aMutex );
205         if( !isInitialized )
206             init();
207     }
208 
209     if( !m_pDatabases )
210         throw uno::RuntimeException();
211 
212     rtl::OUString aOUString( m_pDatabases->getInstallPathAsURL() );
213     rtl::OString aOString( aOUString.getStr(),
214                            aOUString.getLength(),
215                            RTL_TEXTENCODING_UTF8 );
216 
217     // Check, if a content with given id already exists...
218     uno::Reference< ucb::XContent > xContent
219         = queryExistingContent( xCanonicId ).get();
220     if ( xContent.is() )
221         return xContent;
222 
223     xContent = new Content( m_xSMgr, this, xCanonicId, m_pDatabases );
224 
225     // register new content
226     registerNewContent( xContent );
227 
228     // Further checks
229 
230     if ( !xContent->getIdentifier().is() )
231         throw ucb::IllegalIdentifierException();
232 
233     return xContent;
234 }
235 
236 void SAL_CALL
237 ContentProvider::dispose()
238     throw ( uno::RuntimeException)
239 {
240     if(m_xContainer.is())
241     {
242         m_xContainer->removeContainerListener(this);
243         m_xContainer.clear();
244     }
245 }
246 
247 void SAL_CALL
248 ContentProvider::elementReplaced(const container::ContainerEvent& Event)
249     throw (uno::RuntimeException)
250 {
251     if(!m_pDatabases)
252         return;
253 
254     rtl::OUString accessor;
255     Event.Accessor >>= accessor;
256     if(accessor.compareToAscii("HelpStyleSheet"))
257         return;
258 
259     rtl::OUString replacedElement,element;
260     Event.ReplacedElement >>= replacedElement;
261     Event.Element >>= element;
262 
263     if(replacedElement == element)
264         return;
265 
266     m_pDatabases->changeCSS(element);
267 }
268 
269 void ContentProvider::init()
270 {
271     osl::MutexGuard aGuard( m_aMutex );
272 
273     isInitialized = true;
274     uno::Reference< lang::XMultiServiceFactory > sProvider(
275         getConfiguration() );
276     uno::Reference< container::XHierarchicalNameAccess > xHierAccess(
277         getHierAccess( sProvider,
278                        "org.openoffice.Office.Common" ) );
279 
280     rtl::OUString instPath( getKey( xHierAccess,"Path/Current/Help" ) );
281     if( ! instPath.getLength() )
282         // try to determine path from default
283         instPath = rtl::OUString::createFromAscii( "$(instpath)/help" );
284     // replace anything like $(instpath);
285     subst( instPath );
286 
287     rtl::OUString stylesheet( getKey( xHierAccess,"Help/HelpStyleSheet" ) );
288     try
289     {
290         // now adding as configuration change listener for the stylesheet
291         uno::Reference< container::XNameAccess> xAccess(
292             xHierAccess, uno::UNO_QUERY );
293         if( xAccess.is() )
294         {
295             uno::Any aAny =
296                 xAccess->getByName( rtl::OUString::createFromAscii( "Help" ) );
297             aAny >>= m_xContainer;
298             if( m_xContainer.is() )
299                 m_xContainer->addContainerListener( this );
300         }
301     }
302     catch( uno::Exception const & )
303     {
304     }
305 
306     /**
307      *  now determing
308      *  productname,
309      *  productversion,
310      */
311 
312     xHierAccess = getHierAccess( sProvider, "org.openoffice.Setup" );
313     rtl::OUString productname(
314         getKey( xHierAccess,"Product/ooName" ) );
315 
316     rtl::OUString setupversion(
317         getKey( xHierAccess,"Product/ooSetupVersion" ) );
318     rtl::OUString setupextension;
319 
320     try
321     {
322         uno::Reference< lang::XMultiServiceFactory > xConfigProvider(
323               m_xSMgr ->createInstance(::rtl::OUString::createFromAscii("com.sun.star.configuration.ConfigurationProvider")), uno::UNO_QUERY_THROW);
324 
325         uno::Sequence < uno::Any > lParams(1);
326         beans::PropertyValue                       aParam ;
327         aParam.Name    = ::rtl::OUString::createFromAscii("nodepath");
328         aParam.Value <<= ::rtl::OUString::createFromAscii("/org.openoffice.Setup/Product");
329         lParams[0] = uno::makeAny(aParam);
330 
331         // open it
332         uno::Reference< uno::XInterface > xCFG( xConfigProvider->createInstanceWithArguments(
333                     ::rtl::OUString::createFromAscii("com.sun.star.configuration.ConfigurationAccess"),
334                     lParams) );
335 
336         uno::Reference< container::XNameAccess > xDirectAccess(xCFG, uno::UNO_QUERY);
337         uno::Any aRet = xDirectAccess->getByName(::rtl::OUString::createFromAscii("ooSetupExtension"));
338 
339         aRet >>= setupextension;
340     }
341     catch ( uno::Exception& )
342     {
343     }
344 
345     rtl::OUString productversion(
346         setupversion +
347         rtl::OUString::createFromAscii( " " ) +
348         setupextension );
349 
350     uno::Sequence< rtl::OUString > aImagesZipPaths( 2 );
351     xHierAccess = getHierAccess( sProvider,  "org.openoffice.Office.Common" );
352 
353     rtl::OUString aPath( getKey( xHierAccess, "Path/Current/UserConfig" ) );
354     subst( aPath );
355     aImagesZipPaths[ 0 ] = aPath;
356 
357     aPath = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("$OOO_BASE_DIR/share/config"));
358     rtl::Bootstrap::expandMacros(aPath);
359     aImagesZipPaths[ 1 ] = aPath;
360 
361     uno::Reference< uno::XComponentContext > xContext;
362     uno::Reference< beans::XPropertySet > xProps( m_xSMgr, uno::UNO_QUERY );
363     OSL_ASSERT( xProps.is() );
364     if (xProps.is())
365     {
366         xProps->getPropertyValue(
367             ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ) ) >>= xContext;
368         OSL_ASSERT( xContext.is() );
369     }
370 
371     sal_Bool showBasic = getBooleanKey(xHierAccess,"Help/ShowBasic");
372     m_pDatabases = new Databases( showBasic,
373                                   instPath,
374                                   aImagesZipPaths,
375                                   productname,
376                                   productversion,
377                                   stylesheet,
378                                   xContext );
379 }
380 
381 uno::Reference< lang::XMultiServiceFactory >
382 ContentProvider::getConfiguration() const
383 {
384     uno::Reference< lang::XMultiServiceFactory > sProvider;
385     if( m_xSMgr.is() )
386     {
387         try
388         {
389             rtl::OUString sProviderService =
390                 rtl::OUString::createFromAscii(
391                     "com.sun.star.configuration.ConfigurationProvider" );
392             sProvider =
393                 uno::Reference< lang::XMultiServiceFactory >(
394                     m_xSMgr->createInstance( sProviderService ),
395                     uno::UNO_QUERY );
396         }
397         catch( const uno::Exception& )
398         {
399             OSL_ENSURE( sProvider.is(), "cant instantiate configuration" );
400         }
401     }
402 
403     return sProvider;
404 }
405 
406 uno::Reference< container::XHierarchicalNameAccess >
407 ContentProvider::getHierAccess(
408     const uno::Reference< lang::XMultiServiceFactory >& sProvider,
409     const char* file ) const
410 {
411     uno::Reference< container::XHierarchicalNameAccess > xHierAccess;
412 
413     if( sProvider.is() )
414     {
415         uno::Sequence< uno::Any > seq( 1 );
416         rtl::OUString sReaderService(
417             rtl::OUString::createFromAscii(
418                 "com.sun.star.configuration.ConfigurationAccess" ) );
419 
420         seq[ 0 ] <<= rtl::OUString::createFromAscii( file );
421 
422         try
423         {
424             xHierAccess =
425                 uno::Reference< container::XHierarchicalNameAccess >(
426                     sProvider->createInstanceWithArguments(
427                         sReaderService, seq ),
428                     uno::UNO_QUERY );
429         }
430         catch( const uno::Exception& )
431         {
432         }
433     }
434     return xHierAccess;
435 }
436 
437 
438 
439 rtl::OUString
440 ContentProvider::getKey(
441     const uno::Reference< container::XHierarchicalNameAccess >& xHierAccess,
442     const char* key ) const
443 {
444     rtl::OUString instPath;
445     if( xHierAccess.is() )
446     {
447         uno::Any aAny;
448         try
449         {
450             aAny =
451                 xHierAccess->getByHierarchicalName(
452                     rtl::OUString::createFromAscii( key ) );
453         }
454         catch( const container::NoSuchElementException& )
455         {
456         }
457         aAny >>= instPath;
458     }
459     return instPath;
460 }
461 
462 sal_Bool
463 ContentProvider::getBooleanKey(
464     const uno::Reference< container::XHierarchicalNameAccess >& xHierAccess,
465     const char* key ) const
466 {
467   sal_Bool ret = sal_False;
468   if( xHierAccess.is() )
469   {
470       uno::Any aAny;
471       try
472       {
473           aAny =
474             xHierAccess->getByHierarchicalName(
475                 rtl::OUString::createFromAscii( key ) );
476       }
477       catch( const container::NoSuchElementException& )
478       {
479       }
480       aAny >>= ret;
481   }
482   return ret;
483 }
484 
485 void ContentProvider::subst( rtl::OUString& instpath ) const
486 {
487     uno::Reference< frame::XConfigManager > xCfgMgr;
488     if( m_xSMgr.is() )
489     {
490         try
491         {
492             xCfgMgr =
493                 uno::Reference< frame::XConfigManager >(
494                     m_xSMgr->createInstance(
495                         rtl::OUString::createFromAscii(
496                             "com.sun.star.config.SpecialConfigManager" ) ),
497                     uno::UNO_QUERY );
498         }
499         catch( const uno::Exception&)
500         {
501             OSL_ENSURE( xCfgMgr.is(),
502                         "cant instantiate the special config manager " );
503         }
504     }
505 
506     OSL_ENSURE( xCfgMgr.is(), "specialconfigmanager not found\n" );
507 
508     if( xCfgMgr.is() )
509         instpath = xCfgMgr->substituteVariables( instpath );
510 }
511