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