update dev300-m58
[ooovba.git] / xmlhelp / source / treeview / tvread.cxx
blob7af3a7d57202cbe3882cfd4eab10db706d29318a
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: tvread.cxx,v $
10 * $Revision: 1.26 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
32 // MARKER(update_precomp.py): autogen include statement, do not remove
33 #include "precompiled_xmlhelp.hxx"
35 #include <string.h>
36 #include <rtl/ustrbuf.hxx>
37 #ifndef _VOS_DIAGNOSE_HXX_
38 #include <vos/diagnose.hxx>
39 #endif
40 #include "tvread.hxx"
41 #ifdef SYSTEM_EXPAT
42 #include <expat.h>
43 #else
44 #include <expat/xmlparse.h>
45 #endif
46 #include <osl/file.hxx>
47 #include <unotools/configmgr.hxx>
48 #include <com/sun/star/frame/XConfigManager.hpp>
49 #include <com/sun/star/beans/PropertyValue.hpp>
50 #include <com/sun/star/beans/PropertyState.hpp>
52 #include <comphelper/processfactory.hxx>
53 #include <com/sun/star/beans/XPropertySet.hpp>
54 #include "com/sun/star/deployment/thePackageManagerFactory.hpp"
55 #include <com/sun/star/util/XMacroExpander.hpp>
56 #include <com/sun/star/uri/XUriReferenceFactory.hpp>
57 #include <com/sun/star/uri/XVndSunStarExpandUrl.hpp>
58 #include <comphelper/locale.hxx>
60 namespace treeview {
63 class TVDom
65 friend class TVChildTarget;
66 friend class TVRead;
68 public:
70 TVDom( TVDom* arent = 0 )
71 : kind( other ),
72 parent( arent ),
73 childs( 0 )
77 ~TVDom()
79 for( unsigned i = 0; i < childs.size(); ++i )
80 delete childs[i];
84 TVDom* newChild()
86 childs.push_back( new TVDom( this ) );
87 return childs.back();
91 TVDom* getParent() const
93 if( parent )
94 return parent;
95 else
96 return const_cast<TVDom*>(this); // I am my own parent, if I am the root
99 enum Kind {
100 tree_view,
101 tree_node,
102 tree_leaf,
103 other
106 bool isLeaf() const { return kind == TVDom::tree_leaf; }
107 void setKind( Kind ind ) { kind = ind; }
108 Kind getKind( ) const { return kind; }
111 void setApplication( const char* appl )
113 application = rtl::OUString( (sal_Char*)(appl),
114 strlen( appl ),
115 RTL_TEXTENCODING_UTF8 );
118 void setTitle( const char* itle )
120 title += rtl::OUString( (sal_Char*)(itle),
121 strlen( itle ),
122 RTL_TEXTENCODING_UTF8 );
125 void setTitle( const XML_Char* itle,int len )
127 title += rtl::OUString( (sal_Char*)(itle),
128 len,
129 RTL_TEXTENCODING_UTF8 );
132 void setId( const char* d )
134 id = rtl::OUString( (sal_Char*)(d),
135 strlen( d ),
136 RTL_TEXTENCODING_UTF8 );
139 void setAnchor( const char* nchor )
141 anchor = rtl::OUString( (sal_Char*)(nchor),
142 strlen( nchor ),
143 RTL_TEXTENCODING_UTF8 );
146 rtl::OUString getTargetURL()
148 if( ! targetURL.getLength() )
150 sal_Int32 len;
151 for ( const TVDom* p = this;; p = p->parent )
153 len = p->application.getLength();
154 if ( len != 0 )
155 break;
158 rtl::OUStringBuffer strBuff( 22 + len + id.getLength() );
159 strBuff.appendAscii(
160 "vnd.sun.star.help://"
161 ).append(id);
163 targetURL = strBuff.makeStringAndClear();
166 return targetURL;
169 private:
171 Kind kind;
172 rtl::OUString application;
173 rtl::OUString title;
174 rtl::OUString id;
175 rtl::OUString anchor;
176 rtl::OUString targetURL;
178 TVDom *parent;
179 std::vector< TVDom* > childs;
186 using namespace treeview;
187 using namespace com::sun::star;
188 using namespace com::sun::star::uno;
189 using namespace com::sun::star::beans;
190 using namespace com::sun::star::lang;
191 using namespace com::sun::star::util;
192 using namespace com::sun::star::frame;
193 using namespace com::sun::star::container;
194 using namespace com::sun::star::deployment;
197 ConfigData::ConfigData()
198 : prodName( rtl::OUString::createFromAscii( "%PRODUCTNAME" ) ),
199 prodVersion( rtl::OUString::createFromAscii( "%PRODUCTVERSION" ) ),
200 vendName( rtl::OUString::createFromAscii( "%VENDORNAME" ) ),
201 vendVersion( rtl::OUString::createFromAscii( "%VENDORVERSION" ) ),
202 vendShort( rtl::OUString::createFromAscii( "%VENDORSHORT" ) )
206 void SAL_CALL ConfigData::replaceName( rtl::OUString& oustring ) const
208 sal_Int32 idx = -1,k = 0,off;
209 bool cap = false;
210 rtl::OUStringBuffer aStrBuf( 0 );
212 while( ( idx = oustring.indexOf( sal_Unicode('%'),++idx ) ) != -1 )
214 if( oustring.indexOf( prodName,idx ) == idx )
215 off = PRODUCTNAME;
216 else if( oustring.indexOf( prodVersion,idx ) == idx )
217 off = PRODUCTVERSION;
218 else if( oustring.indexOf( vendName,idx ) == idx )
219 off = VENDORNAME;
220 else if( oustring.indexOf( vendVersion,idx ) == idx )
221 off = VENDORVERSION;
222 else if( oustring.indexOf( vendShort,idx ) == idx )
223 off = VENDORSHORT;
224 else
225 off = -1;
227 if( off != -1 )
229 if( ! cap )
231 cap = true;
232 aStrBuf.ensureCapacity( 256 );
235 aStrBuf.append( &oustring.getStr()[k],idx - k );
236 aStrBuf.append( m_vReplacement[off] );
237 k = idx + m_vAdd[off];
241 if( cap )
243 if( k < oustring.getLength() )
244 aStrBuf.append( &oustring.getStr()[k],oustring.getLength()-k );
245 oustring = aStrBuf.makeStringAndClear();
252 //////////////////////////////////////////////////////////////////////////
253 // XInterface
254 //////////////////////////////////////////////////////////////////////////
257 void SAL_CALL
258 TVBase::acquire(
259 void )
260 throw()
262 OWeakObject::acquire();
266 void SAL_CALL
267 TVBase::release(
268 void )
269 throw()
271 OWeakObject::release();
275 Any SAL_CALL
276 TVBase::queryInterface(
277 const Type& rType )
278 throw( RuntimeException )
280 Any aRet = cppu::queryInterface( rType,
281 SAL_STATIC_CAST( XTypeProvider*, this ),
282 SAL_STATIC_CAST( XNameAccess*, this ),
283 SAL_STATIC_CAST( XHierarchicalNameAccess*, this ),
284 SAL_STATIC_CAST( XChangesNotifier*, this ),
285 SAL_STATIC_CAST( XComponent*, this ) );
287 return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
291 ////////////////////////////////////////////////////////////////////////////////
293 // XTypeProvider methods.
295 XTYPEPROVIDER_IMPL_5( TVBase,
296 XTypeProvider,
297 XNameAccess,
298 XHierarchicalNameAccess,
299 XChangesNotifier,
300 XComponent );
307 // TVRead
310 TVRead::TVRead( const ConfigData& configData,TVDom* tvDom )
312 if( ! tvDom )
313 return;
315 Title = tvDom->title;
316 configData.replaceName( Title );
317 if( tvDom->isLeaf() )
319 TargetURL = ( tvDom->getTargetURL() + configData.appendix );
320 if( tvDom->anchor.getLength() )
321 TargetURL += ( rtl::OUString::createFromAscii( "#" ) +
322 tvDom->anchor );
324 else
325 Children = new TVChildTarget( configData,tvDom );
330 TVRead::~TVRead()
339 // XNameAccess
341 Any SAL_CALL
342 TVRead::getByName( const rtl::OUString& aName )
343 throw( NoSuchElementException,
344 WrappedTargetException,
345 RuntimeException )
347 bool found( true );
348 Any aAny;
349 if( aName.compareToAscii( "Title" ) == 0 )
350 aAny <<= Title;
351 else if( aName.compareToAscii( "TargetURL" ) == 0 )
352 aAny <<= TargetURL;
353 else if( aName.compareToAscii( "Children" ) == 0 )
355 cppu::OWeakObject* p = Children.get();
356 aAny <<= Reference< XInterface >( p );
358 else
359 found = false;
361 if( found )
362 return aAny;
364 throw NoSuchElementException();
370 Sequence< rtl::OUString > SAL_CALL
371 TVRead::getElementNames( )
372 throw( RuntimeException )
374 Sequence< rtl::OUString > seq( 3 );
376 seq[0] = rtl::OUString::createFromAscii( "Title" );
377 seq[1] = rtl::OUString::createFromAscii( "TargetURL" );
378 seq[2] = rtl::OUString::createFromAscii( "Children" );
380 return seq;
385 sal_Bool SAL_CALL
386 TVRead::hasByName( const rtl::OUString& aName )
387 throw( RuntimeException )
389 if( aName.compareToAscii( "Title" ) == 0 ||
390 aName.compareToAscii( "TargetURL" ) == 0 ||
391 aName.compareToAscii( "Children" ) == 0 )
392 return true;
394 return false;
398 // XHierarchicalNameAccess
400 Any SAL_CALL
401 TVRead::getByHierarchicalName( const rtl::OUString& aName )
402 throw( NoSuchElementException,
403 RuntimeException )
405 sal_Int32 idx;
406 rtl::OUString name( aName );
408 if( ( idx = name.indexOf( sal_Unicode( '/' ) ) ) != -1 &&
409 name.copy( 0,idx ).compareToAscii( "Children" ) == 0 )
410 return Children->getByHierarchicalName( name.copy( 1 + idx ) );
412 return getByName( name );
418 sal_Bool SAL_CALL
419 TVRead::hasByHierarchicalName( const rtl::OUString& aName )
420 throw( RuntimeException )
422 sal_Int32 idx;
423 rtl::OUString name( aName );
425 if( ( idx = name.indexOf( sal_Unicode( '/' ) ) ) != -1 &&
426 name.copy( 0,idx ).compareToAscii( "Children" ) == 0 )
427 return Children->hasByHierarchicalName( name.copy( 1 + idx ) );
429 return hasByName( name );
434 /**************************************************************************/
435 /* */
436 /* TVChildTarget */
437 /* */
438 /**************************************************************************/
443 extern "C" void start_handler(void *userData,
444 const XML_Char *name,
445 const XML_Char **atts)
447 TVDom::Kind kind;
449 if( strcmp( name,"help_section" ) == 0 ||
450 strcmp( name,"node" ) == 0 )
451 kind = TVDom::tree_node;
452 else if( strcmp( name,"topic" ) == 0 )
453 kind = TVDom::tree_leaf;
454 else
455 return;
457 TVDom **tvDom = static_cast< TVDom** >( userData );
458 TVDom *p;
459 p = *tvDom;
461 *tvDom = p->newChild();
462 p = *tvDom;
464 p->setKind( kind );
465 while( *atts )
467 if( strcmp( *atts,"application" ) == 0 )
468 p->setApplication( *(atts+1) );
469 else if( strcmp( *atts,"title" ) == 0 )
470 p->setTitle( *(atts+1) );
471 else if( strcmp( *atts,"id" ) == 0 )
472 p->setId( *(atts+1) );
473 else if( strcmp( *atts,"anchor" ) == 0 )
474 p->setAnchor( *(atts+1) );
476 atts+=2;
481 extern "C" void end_handler(void *userData,
482 const XML_Char *name )
484 (void)name;
486 TVDom **tvDom = static_cast< TVDom** >( userData );
487 *tvDom = (*tvDom)->getParent();
491 extern "C" void data_handler( void *userData,
492 const XML_Char *s,
493 int len)
495 TVDom **tvDom = static_cast< TVDom** >( userData );
496 if( (*tvDom)->isLeaf() )
497 (*tvDom)->setTitle( s,len );
502 TVChildTarget::TVChildTarget( const ConfigData& configData,TVDom* tvDom )
504 Elements.resize( tvDom->childs.size() );
505 for( unsigned i = 0; i < Elements.size(); ++i )
506 Elements[i] = new TVRead( configData,tvDom->childs[i] );
513 TVChildTarget::TVChildTarget( const Reference< XMultiServiceFactory >& xMSF )
515 ConfigData configData = init( xMSF );
517 if( ! configData.locale.getLength() ||
518 ! configData.system.getLength() )
519 return;
521 sal_uInt64 ret,len = 0;
522 int j = configData.vFileURL.size();
524 TVDom tvDom;
525 TVDom* pTVDom = &tvDom;
527 while( j )
529 len = configData.vFileLen[--j];
530 char* s = new char[ int(len) ]; // the buffer to hold the installed files
531 osl::File aFile( configData.vFileURL[j] );
532 aFile.open( OpenFlag_Read );
533 aFile.read( s,len,ret );
534 aFile.close();
536 XML_Parser parser = XML_ParserCreate( 0 );
537 XML_SetElementHandler( parser,
538 start_handler,
539 end_handler );
540 XML_SetCharacterDataHandler( parser,
541 data_handler);
542 XML_SetUserData( parser,&pTVDom ); // does not return this
544 int parsed = XML_Parse( parser,s,int( len ),j==0 );
545 (void)parsed;
546 OSL_ENSURE( parsed, "TVChildTarget::TVChildTarget(): Tree file parsing failed" );
548 XML_ParserFree( parser );
549 delete[] s;
552 // now TVDom holds the relevant information
554 Elements.resize( tvDom.childs.size() );
555 for( unsigned i = 0; i < Elements.size(); ++i )
556 Elements[i] = new TVRead( configData,tvDom.childs[i] );
560 TVChildTarget::~TVChildTarget()
566 Any SAL_CALL
567 TVChildTarget::getByName( const rtl::OUString& aName )
568 throw( NoSuchElementException,
569 WrappedTargetException,
570 RuntimeException )
572 rtl::OUString num( aName.getStr()+2,aName.getLength()-4 );
573 sal_Int32 idx = num.toInt32() - 1;
574 if( idx < 0 || Elements.size() <= sal_uInt32( idx ) )
575 throw NoSuchElementException();
577 Any aAny;
578 cppu::OWeakObject* p = Elements[idx].get();
579 aAny <<= Reference< XInterface >( p );
580 return aAny;
586 Sequence< rtl::OUString > SAL_CALL
587 TVChildTarget::getElementNames( )
588 throw( RuntimeException )
590 Sequence< rtl::OUString > seq( Elements.size() );
591 for( unsigned i = 0; i < Elements.size(); ++i )
592 seq[i] = rtl::OUString::valueOf( sal_Int32( 1+i ) );
594 return seq;
599 sal_Bool SAL_CALL
600 TVChildTarget::hasByName( const rtl::OUString& aName )
601 throw( RuntimeException )
603 rtl::OUString num( aName.getStr()+2,aName.getLength()-4 );
604 sal_Int32 idx = num.toInt32() - 1;
605 if( idx < 0 || Elements.size() <= sal_uInt32( idx ) )
606 return false;
608 return true;
613 // XHierarchicalNameAccess
615 Any SAL_CALL
616 TVChildTarget::getByHierarchicalName( const rtl::OUString& aName )
617 throw( NoSuchElementException,
618 RuntimeException )
620 sal_Int32 idx;
621 rtl::OUString name( aName );
623 if( ( idx = name.indexOf( sal_Unicode( '/' ) ) ) != -1 )
625 rtl::OUString num( name.getStr()+2,idx-4 );
626 sal_Int32 pref = num.toInt32() - 1;
628 if( pref < 0 || Elements.size() <= sal_uInt32( pref ) )
629 throw NoSuchElementException();
631 return Elements[pref]->getByHierarchicalName( name.copy( 1 + idx ) );
633 else
634 return getByName( name );
639 sal_Bool SAL_CALL
640 TVChildTarget::hasByHierarchicalName( const rtl::OUString& aName )
641 throw( RuntimeException )
643 sal_Int32 idx;
644 rtl::OUString name( aName );
646 if( ( idx = name.indexOf( sal_Unicode( '/' ) ) ) != -1 )
648 rtl::OUString num( name.getStr()+2,idx-4 );
649 sal_Int32 pref = num.toInt32() - 1;
650 if( pref < 0 || Elements.size() <= sal_uInt32( pref ) )
651 return false;
653 return Elements[pref]->hasByHierarchicalName( name.copy( 1 + idx ) );
655 else
656 return hasByName( name );
664 ConfigData TVChildTarget::init( const Reference< XMultiServiceFactory >& xSMgr )
666 ConfigData configData;
667 Reference< XMultiServiceFactory > sProvider( getConfiguration(xSMgr) );
669 /**********************************************************************/
670 /* reading Office.Common */
671 /**********************************************************************/
673 Reference< XHierarchicalNameAccess > xHierAccess( getHierAccess( sProvider,
674 "org.openoffice.Office.Common" ) );
675 rtl::OUString system( getKey( xHierAccess,"Help/System" ) );
676 sal_Bool showBasic( getBooleanKey(xHierAccess,"Help/ShowBasic") );
677 rtl::OUString instPath( getKey( xHierAccess,"Path/Current/Help" ) );
678 if( ! instPath.getLength() )
679 // try to determine path from default
680 instPath = rtl::OUString::createFromAscii( "$(instpath)/help" );
682 // replace anything like $(instpath);
683 subst( xSMgr,instPath );
686 /**********************************************************************/
687 /* reading Webtop.Common */
688 /**********************************************************************/
690 xHierAccess = getHierAccess( sProvider,
691 "org.openoffice.Webtop.Common" );
692 rtl::OUString vendorName( getKey( xHierAccess,"Product/ooName" ) );
694 rtl::OUString setupversion( getKey( xHierAccess,"Product/ooSetupVersion" ) );
695 rtl::OUString setupextension( getKey( xHierAccess,"Product/ooSetupExtension") );
696 rtl::OUString vendorVersion( setupversion +
697 rtl::OUString::createFromAscii( " " ) +
698 setupextension );
699 rtl::OUString vendorShort = vendorName;
701 /**********************************************************************/
702 /* reading setup */
703 /**********************************************************************/
705 xHierAccess = getHierAccess( sProvider,
706 "org.openoffice.Setup" );
708 rtl::OUString productName( getKey( xHierAccess,"Product/ooName" ) );
709 setupversion = getKey( xHierAccess,"Product/ooSetupVersion" );
710 setupextension = rtl::OUString();
711 utl::ConfigManager * mgr = utl::ConfigManager::GetConfigManager();
712 if (mgr != NULL) {
713 mgr->GetDirectConfigProperty(utl::ConfigManager::PRODUCTEXTENSION) >>=
714 setupextension;
716 rtl::OUString productVersion( setupversion +
717 rtl::OUString::createFromAscii( " " ) +
718 setupextension );
719 rtl::OUString locale( getKey( xHierAccess,"L10N/ooLocale" ) );
722 // Determine fileurl from url and locale
723 rtl::OUString url;
724 osl::FileBase::RC errFile = osl::FileBase::getFileURLFromSystemPath( instPath,url );
725 if( errFile != osl::FileBase::E_None ) return configData;
726 if( url.lastIndexOf( sal_Unicode( '/' ) ) != url.getLength() - 1 )
727 url += rtl::OUString::createFromAscii( "/" );
728 rtl::OUString ret;
729 sal_Int32 idx;
730 osl::DirectoryItem aDirItem;
731 if( osl::FileBase::E_None == osl::DirectoryItem::get( url + locale,aDirItem ) )
732 ret = locale;
733 else if( ( ( idx = locale.indexOf( '-' ) ) != -1 ||
734 ( idx = locale.indexOf( '_' ) ) != -1 ) &&
735 osl::FileBase::E_None == osl::DirectoryItem::get( url + locale.copy( 0,idx ),
736 aDirItem ) )
737 ret = locale.copy( 0,idx );
738 else
740 locale = rtl::OUString::createFromAscii( "en-US" );
741 ret = rtl::OUString::createFromAscii("en");
743 url = url + ret;
745 // first of all, try do determine whether there are any *.tree files present
747 // Start with extensions to set them at the end of the list
748 TreeFileIterator aTreeIt( locale );
749 rtl::OUString aTreeFile;
750 sal_Int32 nFileSize;
751 while( (aTreeFile = aTreeIt.nextTreeFile( nFileSize ) ).getLength() > 0 )
753 configData.vFileLen.push_back( nFileSize );
754 configData.vFileURL.push_back( aTreeFile );
757 osl::Directory aDirectory( url );
758 osl::FileStatus aFileStatus( FileStatusMask_FileName | FileStatusMask_FileSize | FileStatusMask_FileURL );
759 if( osl::Directory::E_None == aDirectory.open() )
761 int idx_ = 0;
762 rtl::OUString aFileUrl, aFileName;
763 while( aDirectory.getNextItem( aDirItem ) == osl::FileBase::E_None &&
764 aDirItem.getFileStatus( aFileStatus ) == osl::FileBase::E_None &&
765 aFileStatus.isValid( FileStatusMask_FileURL ) &&
766 aFileStatus.isValid( FileStatusMask_FileName ) )
768 aFileUrl = aFileStatus.getFileURL();
769 aFileName = aFileStatus.getFileName();
770 idx_ = aFileName.lastIndexOf( sal_Unicode( '.' ) );
771 if( idx_ == -1 )
772 continue;
774 const sal_Unicode* str = aFileName.getStr();
776 if( aFileName.getLength() == idx_ + 5 &&
777 ( str[idx_ + 1] == 't' || str[idx_ + 1] == 'T' ) &&
778 ( str[idx_ + 2] == 'r' || str[idx_ + 2] == 'R' ) &&
779 ( str[idx_ + 3] == 'e' || str[idx_ + 3] == 'E' ) &&
780 ( str[idx_ + 4] == 'e' || str[idx_ + 4] == 'E' ) )
782 OSL_ENSURE( aFileStatus.isValid( FileStatusMask_FileSize ),
783 "invalid file size" );
785 rtl::OUString baseName = aFileName.copy(0,idx_).toAsciiLowerCase();
786 if(! showBasic && baseName.compareToAscii("sbasic") == 0 )
787 continue;
788 osl::File aFile( aFileUrl );
789 if( osl::FileBase::E_None == aFile.open( OpenFlag_Read ) )
791 sal_uInt64 nSize;
792 aFile.getSize( nSize );
793 configData.vFileLen.push_back( aFileStatus.getFileSize() );
794 configData.vFileURL.push_back( aFileUrl );
795 aFile.close();
799 aDirectory.close();
802 configData.m_vAdd[0] = 12;
803 configData.m_vAdd[1] = 15;
804 configData.m_vAdd[2] = 11;
805 configData.m_vAdd[3] = 14;
806 configData.m_vAdd[4] = 12;
807 configData.m_vReplacement[0] = productName;
808 configData.m_vReplacement[1] = productVersion;
809 configData.m_vReplacement[2] = vendorName;
810 configData.m_vReplacement[3] = vendorVersion;
811 configData.m_vReplacement[4] = vendorShort;
813 configData.system = system;
814 configData.locale = locale;
815 configData.appendix =
816 rtl::OUString::createFromAscii( "?Language=" ) +
817 configData.locale +
818 rtl::OUString::createFromAscii( "&System=" ) +
819 configData.system +
820 rtl::OUString::createFromAscii( "&UseDB=no" ) ;
822 return configData;
833 Reference< XMultiServiceFactory >
834 TVChildTarget::getConfiguration(const Reference< XMultiServiceFactory >& m_xSMgr) const
836 Reference< XMultiServiceFactory > sProvider;
837 if( m_xSMgr.is() )
839 Any aAny;
840 aAny <<= rtl::OUString::createFromAscii( "plugin" );
841 PropertyValue aProp( rtl::OUString::createFromAscii( "servertype" ),
843 aAny,
844 PropertyState_DIRECT_VALUE );
846 Sequence< Any > seq(1);
847 seq[0] <<= aProp;
851 rtl::OUString sProviderService =
852 rtl::OUString::createFromAscii( "com.sun.star.configuration.ConfigurationProvider" );
853 sProvider =
854 Reference< XMultiServiceFactory >(
855 m_xSMgr->createInstanceWithArguments( sProviderService,seq ),
856 UNO_QUERY );
858 catch( const com::sun::star::uno::Exception& )
860 OSL_ENSURE( sProvider.is(),"cant instantiate configuration" );
864 return sProvider;
869 Reference< XHierarchicalNameAccess >
870 TVChildTarget::getHierAccess( const Reference< XMultiServiceFactory >& sProvider,
871 const char* file ) const
873 Reference< XHierarchicalNameAccess > xHierAccess;
875 if( sProvider.is() )
877 Sequence< Any > seq(1);
878 rtl::OUString sReaderService =
879 rtl::OUString::createFromAscii( "com.sun.star.configuration.ConfigurationAccess" );
881 seq[0] <<= rtl::OUString::createFromAscii( file );
885 xHierAccess =
886 Reference< XHierarchicalNameAccess >
887 ( sProvider->createInstanceWithArguments( sReaderService,seq ),
888 UNO_QUERY );
890 catch( const com::sun::star::uno::Exception& )
895 return xHierAccess;
900 rtl::OUString
901 TVChildTarget::getKey( const Reference< XHierarchicalNameAccess >& xHierAccess,
902 const char* key ) const
904 rtl::OUString instPath;
905 if( xHierAccess.is() )
907 Any aAny;
910 aAny =
911 xHierAccess->getByHierarchicalName( rtl::OUString::createFromAscii( key ) );
913 catch( const com::sun::star::container::NoSuchElementException& )
916 aAny >>= instPath;
918 return instPath;
922 sal_Bool
923 TVChildTarget::getBooleanKey(const Reference<
924 XHierarchicalNameAccess >& xHierAccess,
925 const char* key) const
927 sal_Bool ret = sal_False;
928 if( xHierAccess.is() )
930 Any aAny;
933 aAny =
934 xHierAccess->getByHierarchicalName(
935 rtl::OUString::createFromAscii(key));
937 catch( const com::sun::star::container::NoSuchElementException& )
940 aAny >>= ret;
942 return ret;
946 void TVChildTarget::subst( const Reference< XMultiServiceFactory >& m_xSMgr,
947 rtl::OUString& instpath ) const
949 Reference< XConfigManager > xCfgMgr;
950 if( m_xSMgr.is() )
954 xCfgMgr =
955 Reference< XConfigManager >(
956 m_xSMgr->createInstance( rtl::OUString::createFromAscii( "com.sun.star.config.SpecialConfigManager" ) ),
957 UNO_QUERY );
959 catch( const com::sun::star::uno::Exception& )
961 OSL_ENSURE( xCfgMgr.is()," cant instantiate the special config manager " );
965 OSL_ENSURE( xCfgMgr.is(), "specialconfigmanager not found\n" );
967 if( xCfgMgr.is() )
968 instpath = xCfgMgr->substituteVariables( instpath );
972 //===================================================================
973 // class ExtensionIteratorBase
975 static rtl::OUString aSlash( rtl::OUString::createFromAscii( "/" ) );
976 static rtl::OUString aHelpFilesBaseName( rtl::OUString::createFromAscii( "help" ) );
977 static rtl::OUString aHelpMediaType( rtl::OUString::createFromAscii( "application/vnd.sun.star.help" ) );
979 ExtensionIteratorBase::ExtensionIteratorBase( const rtl::OUString& aLanguage )
980 : m_eState( USER_EXTENSIONS )
981 , m_aLanguage( aLanguage )
983 init();
986 void ExtensionIteratorBase::init()
988 Reference< XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory();
989 Reference< XPropertySet > xProps( xFactory, UNO_QUERY );
990 OSL_ASSERT( xProps.is() );
991 if (xProps.is())
993 xProps->getPropertyValue(
994 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ) ) >>= m_xContext;
995 OSL_ASSERT( m_xContext.is() );
997 if( !m_xContext.is() )
999 throw RuntimeException(
1000 ::rtl::OUString::createFromAscii( "ExtensionIteratorBase::init(), no XComponentContext" ),
1001 Reference< XInterface >() );
1004 Reference< XMultiComponentFactory > xSMgr( m_xContext->getServiceManager(), UNO_QUERY );
1005 m_xSFA = Reference< ucb::XSimpleFileAccess >(
1006 xSMgr->createInstanceWithContext( rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ),
1007 m_xContext ), UNO_QUERY_THROW );
1009 m_bUserPackagesLoaded = false;
1010 m_bSharedPackagesLoaded = false;
1011 m_iUserPackage = 0;
1012 m_iSharedPackage = 0;
1015 Reference< deployment::XPackage > ExtensionIteratorBase::implGetHelpPackageFromPackage
1016 ( Reference< deployment::XPackage > xPackage, Reference< deployment::XPackage >& o_xParentPackageBundle )
1018 o_xParentPackageBundle.clear();
1020 Reference< deployment::XPackage > xHelpPackage;
1021 if( !xPackage.is() )
1022 return xHelpPackage;
1024 // Check if parent package is registered
1025 beans::Optional< beans::Ambiguous<sal_Bool> > option( xPackage->isRegistered
1026 ( Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>() ) );
1027 bool bRegistered = false;
1028 if( option.IsPresent )
1030 beans::Ambiguous<sal_Bool> const & reg = option.Value;
1031 if( !reg.IsAmbiguous && reg.Value )
1032 bRegistered = true;
1034 if( !bRegistered )
1035 return xHelpPackage;
1037 if( xPackage->isBundle() )
1039 Sequence< Reference< deployment::XPackage > > aPkgSeq = xPackage->getBundle
1040 ( Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>() );
1041 sal_Int32 nPkgCount = aPkgSeq.getLength();
1042 const Reference< deployment::XPackage >* pSeq = aPkgSeq.getConstArray();
1043 for( sal_Int32 iPkg = 0 ; iPkg < nPkgCount ; ++iPkg )
1045 const Reference< deployment::XPackage > xSubPkg = pSeq[ iPkg ];
1046 const Reference< deployment::XPackageTypeInfo > xPackageTypeInfo = xSubPkg->getPackageType();
1047 rtl::OUString aMediaType = xPackageTypeInfo->getMediaType();
1048 if( aMediaType.equals( aHelpMediaType ) )
1050 xHelpPackage = xSubPkg;
1051 o_xParentPackageBundle = xPackage;
1052 break;
1056 else
1058 const Reference< deployment::XPackageTypeInfo > xPackageTypeInfo = xPackage->getPackageType();
1059 rtl::OUString aMediaType = xPackageTypeInfo->getMediaType();
1060 if( aMediaType.equals( aHelpMediaType ) )
1061 xHelpPackage = xPackage;
1064 return xHelpPackage;
1067 Reference< deployment::XPackage > ExtensionIteratorBase::implGetNextUserHelpPackage
1068 ( Reference< deployment::XPackage >& o_xParentPackageBundle )
1070 Reference< deployment::XPackage > xHelpPackage;
1072 if( !m_bUserPackagesLoaded )
1074 Reference< XPackageManager > xUserManager =
1075 thePackageManagerFactory::get( m_xContext )->getPackageManager( rtl::OUString::createFromAscii("user") );
1076 m_aUserPackagesSeq = xUserManager->getDeployedPackages
1077 ( Reference< task::XAbortChannel >(), Reference< ucb::XCommandEnvironment >() );
1079 m_bUserPackagesLoaded = true;
1082 if( m_iUserPackage == m_aUserPackagesSeq.getLength() )
1084 m_eState = SHARED_EXTENSIONS; // Later: SHARED_MODULE
1086 else
1088 const Reference< deployment::XPackage >* pUserPackages = m_aUserPackagesSeq.getConstArray();
1089 Reference< deployment::XPackage > xPackage = pUserPackages[ m_iUserPackage++ ];
1090 VOS_ENSURE( xPackage.is(), "ExtensionIteratorBase::implGetNextUserHelpPackage(): Invalid package" );
1091 xHelpPackage = implGetHelpPackageFromPackage( xPackage, o_xParentPackageBundle );
1094 return xHelpPackage;
1097 Reference< deployment::XPackage > ExtensionIteratorBase::implGetNextSharedHelpPackage
1098 ( Reference< deployment::XPackage >& o_xParentPackageBundle )
1100 Reference< deployment::XPackage > xHelpPackage;
1102 if( !m_bSharedPackagesLoaded )
1104 Reference< XPackageManager > xSharedManager =
1105 thePackageManagerFactory::get( m_xContext )->getPackageManager( rtl::OUString::createFromAscii("shared") );
1106 m_aSharedPackagesSeq = xSharedManager->getDeployedPackages
1107 ( Reference< task::XAbortChannel >(), Reference< ucb::XCommandEnvironment >() );
1109 m_bSharedPackagesLoaded = true;
1112 if( m_iSharedPackage == m_aSharedPackagesSeq.getLength() )
1114 m_eState = END_REACHED;
1116 else
1118 const Reference< deployment::XPackage >* pSharedPackages = m_aSharedPackagesSeq.getConstArray();
1119 Reference< deployment::XPackage > xPackage = pSharedPackages[ m_iSharedPackage++ ];
1120 VOS_ENSURE( xPackage.is(), "ExtensionIteratorBase::implGetNextSharedHelpPackage(): Invalid package" );
1121 xHelpPackage = implGetHelpPackageFromPackage( xPackage, o_xParentPackageBundle );
1124 return xHelpPackage;
1127 inline bool isLetter( sal_Unicode c )
1129 bool bLetter = ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'));
1130 return bLetter;
1133 void ExtensionIteratorBase::implGetLanguageVectorFromPackage( ::std::vector< ::rtl::OUString > &rv,
1134 com::sun::star::uno::Reference< com::sun::star::deployment::XPackage > xPackage )
1136 rv.clear();
1137 rtl::OUString aExtensionPath = xPackage->getURL();
1138 Sequence< rtl::OUString > aEntrySeq = m_xSFA->getFolderContents( aExtensionPath, true );
1140 const rtl::OUString* pSeq = aEntrySeq.getConstArray();
1141 sal_Int32 nCount = aEntrySeq.getLength();
1142 for( sal_Int32 i = 0 ; i < nCount ; ++i )
1144 rtl::OUString aEntry = pSeq[i];
1145 if( m_xSFA->isFolder( aEntry ) )
1147 sal_Int32 nLastSlash = aEntry.lastIndexOf( '/' );
1148 if( nLastSlash != -1 )
1150 rtl::OUString aPureEntry = aEntry.copy( nLastSlash + 1 );
1152 // Check language sceme
1153 int nLen = aPureEntry.getLength();
1154 const sal_Unicode* pc = aPureEntry.getStr();
1155 bool bStartCanBeLanguage = ( nLen >= 2 && isLetter( pc[0] ) && isLetter( pc[1] ) );
1156 bool bIsLanguage = bStartCanBeLanguage &&
1157 ( nLen == 2 || (nLen == 5 && pc[2] == '-' && isLetter( pc[3] ) && isLetter( pc[4] )) );
1158 if( bIsLanguage )
1159 rv.push_back( aPureEntry );
1166 //===================================================================
1167 // class TreeFileIterator
1169 rtl::OUString TreeFileIterator::nextTreeFile( sal_Int32& rnFileSize )
1171 rtl::OUString aRetFile;
1173 while( !aRetFile.getLength() && m_eState != END_REACHED )
1175 switch( m_eState )
1177 case USER_EXTENSIONS:
1179 Reference< deployment::XPackage > xParentPackageBundle;
1180 Reference< deployment::XPackage > xHelpPackage = implGetNextUserHelpPackage( xParentPackageBundle );
1181 if( !xHelpPackage.is() )
1182 break;
1184 aRetFile = implGetTreeFileFromPackage( rnFileSize, xHelpPackage );
1185 break;
1188 case SHARED_EXTENSIONS:
1190 Reference< deployment::XPackage > xParentPackageBundle;
1191 Reference< deployment::XPackage > xHelpPackage = implGetNextSharedHelpPackage( xParentPackageBundle );
1192 if( !xHelpPackage.is() )
1193 break;
1195 aRetFile = implGetTreeFileFromPackage( rnFileSize, xHelpPackage );
1196 break;
1198 case END_REACHED:
1199 VOS_ENSURE( false, "DataBaseIterator::nextTreeFile(): Invalid case END_REACHED" );
1200 break;
1204 return aRetFile;
1207 rtl::OUString TreeFileIterator::expandURL( const rtl::OUString& aURL )
1209 static Reference< util::XMacroExpander > xMacroExpander;
1210 static Reference< uri::XUriReferenceFactory > xFac;
1212 osl::MutexGuard aGuard( m_aMutex );
1214 if( !xMacroExpander.is() || !xFac.is() )
1216 Reference< XMultiComponentFactory > xSMgr( m_xContext->getServiceManager(), UNO_QUERY );
1218 xFac = Reference< uri::XUriReferenceFactory >(
1219 xSMgr->createInstanceWithContext( rtl::OUString::createFromAscii(
1220 "com.sun.star.uri.UriReferenceFactory"), m_xContext ) , UNO_QUERY );
1221 if( !xFac.is() )
1223 throw RuntimeException(
1224 ::rtl::OUString::createFromAscii( "Databases::expand(), could not instatiate UriReferenceFactory." ),
1225 Reference< XInterface >() );
1228 xMacroExpander = Reference< util::XMacroExpander >(
1229 m_xContext->getValueByName(
1230 ::rtl::OUString::createFromAscii( "/singletons/com.sun.star.util.theMacroExpander" ) ),
1231 UNO_QUERY_THROW );
1234 rtl::OUString aRetURL = aURL;
1235 if( xMacroExpander.is() )
1237 Reference< uri::XUriReference > uriRef;
1238 for (;;)
1240 uriRef = Reference< uri::XUriReference >( xFac->parse( aRetURL ), UNO_QUERY );
1241 if ( uriRef.is() )
1243 Reference < uri::XVndSunStarExpandUrl > sxUri( uriRef, UNO_QUERY );
1244 if( !sxUri.is() )
1245 break;
1247 aRetURL = sxUri->expand( xMacroExpander );
1251 return aRetURL;
1254 rtl::OUString TreeFileIterator::implGetTreeFileFromPackage
1255 ( sal_Int32& rnFileSize, Reference< deployment::XPackage > xPackage )
1257 rtl::OUString aRetFile;
1258 rtl::OUString aLanguage = m_aLanguage;
1259 for( sal_Int32 iPass = 0 ; iPass < 2 ; ++iPass )
1261 rtl::OUStringBuffer aStrBuf;
1262 aStrBuf.append( xPackage->getURL() );
1263 aStrBuf.append( aSlash );
1264 aStrBuf.append( aLanguage );
1265 aStrBuf.append( aSlash );
1266 aStrBuf.append( aHelpFilesBaseName );
1267 aStrBuf.appendAscii( ".tree" );
1269 aRetFile = expandURL( aStrBuf.makeStringAndClear() );
1270 if( iPass == 0 )
1272 if( m_xSFA->exists( aRetFile ) )
1273 break;
1275 ::std::vector< ::rtl::OUString > av;
1276 implGetLanguageVectorFromPackage( av, xPackage );
1277 ::std::vector< ::rtl::OUString >::const_iterator pFound = av.end();
1280 pFound = ::comphelper::Locale::getFallback( av, m_aLanguage );
1282 catch( ::comphelper::Locale::MalFormedLocaleException& )
1284 if( pFound != av.end() )
1285 aLanguage = *pFound;
1289 rnFileSize = 0;
1290 if( m_xSFA->exists( aRetFile ) )
1291 rnFileSize = m_xSFA->getSize( aRetFile );
1292 else
1293 aRetFile = rtl::OUString();
1295 return aRetFile;