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(), "can't 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 "can't 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