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