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 {
118 return getImplementationName_Static();
119 }
120
getImplementationName_Static()121 rtl::OUString ContentProvider::getImplementationName_Static()
122 {
123 return rtl::OUString::createFromAscii("CHelpContentProvider" );
124 }
125
126 sal_Bool SAL_CALL
supportsService(const rtl::OUString & ServiceName)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
getSupportedServiceNames()141 ContentProvider::getSupportedServiceNames()
142 {
143 return getSupportedServiceNames_Static();
144 }
145
146 static uno::Reference< uno::XInterface > SAL_CALL
ContentProvider_CreateInstance(const uno::Reference<lang::XMultiServiceFactory> & rSMgr)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 >
getSupportedServiceNames_Static()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
queryContent(const uno::Reference<ucb::XContentIdentifier> & xCanonicId)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
dispose()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
elementReplaced(const container::ContainerEvent & Event)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
init()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 >
getConfiguration() const371 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 >
getHierAccess(const uno::Reference<lang::XMultiServiceFactory> & sProvider,const char * file) const396 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
getKey(const uno::Reference<container::XHierarchicalNameAccess> & xHierAccess,const char * key) const429 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
getBooleanKey(const uno::Reference<container::XHierarchicalNameAccess> & xHierAccess,const char * key) const452 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
subst(rtl::OUString & instpath) const474 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