1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <rtl/ustrbuf.hxx>
22 #include <osl/diagnose.h>
25 #include <osl/file.hxx>
26 #include <unotools/configmgr.hxx>
27 #include <com/sun/star/configuration/theDefaultProvider.hpp>
28 #include <com/sun/star/ucb/SimpleFileAccess.hpp>
29 #include <com/sun/star/frame/XConfigManager.hpp>
30 #include <com/sun/star/beans/PropertyValue.hpp>
32 #include <comphelper/processfactory.hxx>
33 #include "com/sun/star/deployment/thePackageManagerFactory.hpp"
34 #include <com/sun/star/util/theMacroExpander.hpp>
35 #include <com/sun/star/uri/UriReferenceFactory.hpp>
36 #include <com/sun/star/uri/XVndSunStarExpandUrl.hpp>
37 #include <i18nlangtag/languagetag.hxx>
38 #include <comphelper/string.hxx>
45 friend class TVChildTarget
;
50 TVDom( TVDom
* arent
= 0 )
59 for( unsigned i
= 0; i
< children
.size(); ++i
)
66 children
.push_back( new TVDom( this ) );
67 return children
.back();
70 TVDom
* newChild(TVDom
* p
)
72 children
.push_back( p
);
74 return children
.back();
78 TVDom
* getParent() const
83 return const_cast<TVDom
*>(this); // I am my own parent, if I am the root
93 bool isLeaf() const { return kind
== TVDom::tree_leaf
; }
94 void setKind( Kind ind
) { kind
= ind
; }
95 Kind
getKind( ) const { return kind
; }
98 void setApplication( const char* appl
)
100 application
= OUString( (sal_Char
*)(appl
),
102 RTL_TEXTENCODING_UTF8
);
105 void setTitle( const char* itle
)
107 title
+= OUString( (sal_Char
*)(itle
),
109 RTL_TEXTENCODING_UTF8
);
112 void setTitle( const XML_Char
* itle
,int len
)
114 title
+= OUString( (sal_Char
*)(itle
),
116 RTL_TEXTENCODING_UTF8
);
119 void setId( const char* d
)
121 id
= OUString( (sal_Char
*)(d
),
123 RTL_TEXTENCODING_UTF8
);
126 void setAnchor( const char* nchor
)
128 anchor
= OUString( (sal_Char
*)(nchor
),
130 RTL_TEXTENCODING_UTF8
);
133 OUString
getTargetURL()
135 if( targetURL
.isEmpty() )
138 for ( const TVDom
* p
= this;; p
= p
->parent
)
140 len
= p
->application
.getLength();
145 OUStringBuffer
strBuff( 22 + len
+ id
.getLength() );
147 "vnd.sun.star.help://"
150 targetURL
= strBuff
.makeStringAndClear();
159 OUString application
;
166 std::vector
< TVDom
* > children
;
173 using namespace treeview
;
174 using namespace com::sun::star
;
175 using namespace com::sun::star::uno
;
176 using namespace com::sun::star::beans
;
177 using namespace com::sun::star::configuration
;
178 using namespace com::sun::star::lang
;
179 using namespace com::sun::star::util
;
180 using namespace com::sun::star::frame
;
181 using namespace com::sun::star::container
;
182 using namespace com::sun::star::deployment
;
185 ConfigData::ConfigData()
186 : prodName("%PRODUCTNAME"),
187 prodVersion("%PRODUCTVERSION"),
188 vendName("%VENDORNAME"),
189 vendVersion("%VENDORVERSION"),
190 vendShort("%VENDORSHORT")
194 void SAL_CALL
ConfigData::replaceName( OUString
& oustring
) const
196 sal_Int32 idx
= -1,k
= 0,off
;
198 OUStringBuffer
aStrBuf( 0 );
200 while( ( idx
= oustring
.indexOf( sal_Unicode('%'),++idx
) ) != -1 )
202 if( oustring
.indexOf( prodName
,idx
) == idx
)
204 else if( oustring
.indexOf( prodVersion
,idx
) == idx
)
205 off
= PRODUCTVERSION
;
206 else if( oustring
.indexOf( vendName
,idx
) == idx
)
208 else if( oustring
.indexOf( vendVersion
,idx
) == idx
)
210 else if( oustring
.indexOf( vendShort
,idx
) == idx
)
220 aStrBuf
.ensureCapacity( 256 );
223 aStrBuf
.append( &oustring
.getStr()[k
],idx
- k
);
224 aStrBuf
.append( m_vReplacement
[off
] );
225 k
= idx
+ m_vAdd
[off
];
231 if( k
< oustring
.getLength() )
232 aStrBuf
.append( &oustring
.getStr()[k
],oustring
.getLength()-k
);
233 oustring
= aStrBuf
.makeStringAndClear();
240 //////////////////////////////////////////////////////////////////////////
242 //////////////////////////////////////////////////////////////////////////
250 OWeakObject::acquire();
259 OWeakObject::release();
264 TVBase::queryInterface(
266 throw( RuntimeException
)
268 Any aRet
= cppu::queryInterface( rType
,
269 (static_cast< XTypeProvider
* >(this)),
270 (static_cast< XNameAccess
* >(this)),
271 (static_cast< XHierarchicalNameAccess
* >(this)),
272 (static_cast< XChangesNotifier
* >(this)),
273 (static_cast< XComponent
* >(this)) );
275 return aRet
.hasValue() ? aRet
: OWeakObject::queryInterface( rType
);
279 ////////////////////////////////////////////////////////////////////////////////
281 // XTypeProvider methods.
283 XTYPEPROVIDER_IMPL_5( TVBase
,
286 XHierarchicalNameAccess
,
298 TVRead::TVRead( const ConfigData
& configData
,TVDom
* tvDom
)
303 Title
= tvDom
->title
;
304 configData
.replaceName( Title
);
305 if( tvDom
->isLeaf() )
307 TargetURL
= ( tvDom
->getTargetURL() + configData
.appendix
);
308 if( !tvDom
->anchor
.isEmpty() )
309 TargetURL
+= ( OUString( "#" ) +
313 Children
= new TVChildTarget( configData
,tvDom
);
330 TVRead::getByName( const OUString
& aName
)
331 throw( NoSuchElementException
,
332 WrappedTargetException
,
337 if( aName
.compareToAscii( "Title" ) == 0 )
339 else if( aName
.compareToAscii( "TargetURL" ) == 0 )
341 else if( aName
.compareToAscii( "Children" ) == 0 )
343 cppu::OWeakObject
* p
= Children
.get();
344 aAny
<<= Reference
< XInterface
>( p
);
352 throw NoSuchElementException();
358 Sequence
< OUString
> SAL_CALL
359 TVRead::getElementNames( )
360 throw( RuntimeException
)
362 Sequence
< OUString
> seq( 3 );
364 seq
[0] = OUString( "Title" );
365 seq
[1] = OUString( "TargetURL" );
366 seq
[2] = OUString( "Children" );
374 TVRead::hasByName( const OUString
& aName
)
375 throw( RuntimeException
)
377 if( aName
.compareToAscii( "Title" ) == 0 ||
378 aName
.compareToAscii( "TargetURL" ) == 0 ||
379 aName
.compareToAscii( "Children" ) == 0 )
386 // XHierarchicalNameAccess
389 TVRead::getByHierarchicalName( const OUString
& aName
)
390 throw( NoSuchElementException
,
394 OUString
name( aName
);
396 if( ( idx
= name
.indexOf( sal_Unicode( '/' ) ) ) != -1 &&
397 name
.copy( 0,idx
).compareToAscii( "Children" ) == 0 )
398 return Children
->getByHierarchicalName( name
.copy( 1 + idx
) );
400 return getByName( name
);
407 TVRead::hasByHierarchicalName( const OUString
& aName
)
408 throw( RuntimeException
)
411 OUString
name( aName
);
413 if( ( idx
= name
.indexOf( sal_Unicode( '/' ) ) ) != -1 &&
414 name
.copy( 0,idx
).compareToAscii( "Children" ) == 0 )
415 return Children
->hasByHierarchicalName( name
.copy( 1 + idx
) );
417 return hasByName( name
);
422 /**************************************************************************/
426 /**************************************************************************/
431 extern "C" void start_handler(void *userData
,
432 const XML_Char
*name
,
433 const XML_Char
**atts
)
437 if( strcmp( name
,"help_section" ) == 0 ||
438 strcmp( name
,"node" ) == 0 )
439 kind
= TVDom::tree_node
;
440 else if( strcmp( name
,"topic" ) == 0 )
441 kind
= TVDom::tree_leaf
;
445 TVDom
**tvDom
= static_cast< TVDom
** >( userData
);
449 *tvDom
= p
->newChild();
455 if( strcmp( *atts
,"application" ) == 0 )
456 p
->setApplication( *(atts
+1) );
457 else if( strcmp( *atts
,"title" ) == 0 )
458 p
->setTitle( *(atts
+1) );
459 else if( strcmp( *atts
,"id" ) == 0 )
460 p
->setId( *(atts
+1) );
461 else if( strcmp( *atts
,"anchor" ) == 0 )
462 p
->setAnchor( *(atts
+1) );
469 extern "C" void end_handler(void *userData
,
470 const XML_Char
*name
)
474 TVDom
**tvDom
= static_cast< TVDom
** >( userData
);
475 *tvDom
= (*tvDom
)->getParent();
479 extern "C" void data_handler( void *userData
,
483 TVDom
**tvDom
= static_cast< TVDom
** >( userData
);
484 if( (*tvDom
)->isLeaf() )
485 (*tvDom
)->setTitle( s
,len
);
488 TVChildTarget::TVChildTarget( const ConfigData
& configData
,TVDom
* tvDom
)
490 Elements
.resize( tvDom
->children
.size() );
491 for( unsigned i
= 0; i
< Elements
.size(); ++i
)
492 Elements
[i
] = new TVRead( configData
,tvDom
->children
[i
] );
495 TVChildTarget::TVChildTarget( const Reference
< XMultiServiceFactory
>& xMSF
)
497 ConfigData configData
= init( xMSF
);
499 if( configData
.locale
.isEmpty() || configData
.system
.isEmpty() )
502 sal_uInt64 ret
,len
= 0;
503 int j
= configData
.vFileURL
.size();
506 TVDom
* pTVDom
= &tvDom
;
510 len
= configData
.vFileLen
[--j
];
511 char* s
= new char[ int(len
) ]; // the buffer to hold the installed files
512 osl::File
aFile( configData
.vFileURL
[j
] );
513 aFile
.open( osl_File_OpenFlag_Read
);
514 aFile
.read( s
,len
,ret
);
517 XML_Parser parser
= XML_ParserCreate( 0 );
518 XML_SetElementHandler( parser
,
521 XML_SetCharacterDataHandler( parser
,
523 XML_SetUserData( parser
,&pTVDom
); // does not return this
525 XML_Status
const parsed
= XML_Parse(parser
, s
, int(len
), j
==0);
526 SAL_WARN_IF(XML_STATUS_ERROR
== parsed
, "xmlhelp",
527 "TVChildTarget::TVChildTarget(): Tree file parsing failed");
529 XML_ParserFree( parser
);
534 // now TVDom holds the relevant information
536 Elements
.resize( tvDom
.children
.size() );
537 for( unsigned i
= 0; i
< Elements
.size(); ++i
)
538 Elements
[i
] = new TVRead( configData
,tvDom
.children
[i
] );
542 TVChildTarget::~TVChildTarget()
546 void TVChildTarget::Check(TVDom
* tvDom
)
548 if (tvDom
->children
.empty())
556 while((i
<tvDom
->children
.size()-1) && (!h
))
558 if (((tvDom
->children
[i
])->application
== (tvDom
->children
[tvDom
->children
.size()-1])->application
) &&
559 ((tvDom
->children
[i
])->id
== (tvDom
->children
[tvDom
->children
.size()-1])->id
))
561 TVDom
* p
= tvDom
->children
[tvDom
->children
.size()-1];
563 for(unsigned k
=0; k
<p
->children
.size(); ++k
)
564 if (!SearchAndInsert(p
->children
[k
], tvDom
->children
[i
])) tvDom
->children
[i
]->newChild(p
->children
[k
]);
566 tvDom
->children
.pop_back();
573 bool TVChildTarget::SearchAndInsert(TVDom
* p
, TVDom
* tvDom
)
575 if (p
->isLeaf()) return false;
580 std::vector
< TVDom
* >::iterator max_It
, i
;
581 max_It
= tvDom
->children
.begin();
584 sal_Int32 p_int
= p
->id
.toInt32();
586 ////////////////////////////////check this level in the tree
587 for(i
= tvDom
->children
.begin(); i
!=tvDom
->children
.end(); ++i
)
588 if (!((*i
)->isLeaf()) &&
589 ((*i
)->id
.getLength() == p
->id
.getLength()) &&
590 (p
->id
.replaceAt((*i
)->parent
->id
.getLength(), p
->id
.getLength()-(*i
)->parent
->id
.getLength(), OUString("")) == (*i
)->parent
->id
)) //prefix check
593 c_int
= (*i
)->id
.toInt32();
597 (*(tvDom
->children
.insert(i
+1, p
)))->parent
= tvDom
;
600 else if(c_int
>max
&& c_int
< p_int
)
606 ////////////////////////////////recursive call if necessary
607 if (h
) (*(tvDom
->children
.insert(max_It
, p
)))->parent
= tvDom
;
610 i
= tvDom
->children
.begin();
611 while ((i
!=tvDom
->children
.end()) && (!h
))
613 h
= SearchAndInsert(p
, *i
);
621 TVChildTarget::getByName( const OUString
& aName
)
622 throw( NoSuchElementException
,
623 WrappedTargetException
,
626 OUString
num( aName
.getStr()+2,aName
.getLength()-4 );
627 sal_Int32 idx
= num
.toInt32() - 1;
628 if( idx
< 0 || Elements
.size() <= sal_uInt32( idx
) )
629 throw NoSuchElementException();
632 cppu::OWeakObject
* p
= Elements
[idx
].get();
633 aAny
<<= Reference
< XInterface
>( p
);
640 Sequence
< OUString
> SAL_CALL
641 TVChildTarget::getElementNames( )
642 throw( RuntimeException
)
644 Sequence
< OUString
> seq( Elements
.size() );
645 for( unsigned i
= 0; i
< Elements
.size(); ++i
)
646 seq
[i
] = OUString::valueOf( sal_Int32( 1+i
) );
654 TVChildTarget::hasByName( const OUString
& aName
)
655 throw( RuntimeException
)
657 OUString
num( aName
.getStr()+2,aName
.getLength()-4 );
658 sal_Int32 idx
= num
.toInt32() - 1;
659 if( idx
< 0 || Elements
.size() <= sal_uInt32( idx
) )
667 // XHierarchicalNameAccess
670 TVChildTarget::getByHierarchicalName( const OUString
& aName
)
671 throw( NoSuchElementException
,
675 OUString
name( aName
);
677 if( ( idx
= name
.indexOf( sal_Unicode( '/' ) ) ) != -1 )
679 OUString
num( name
.getStr()+2,idx
-4 );
680 sal_Int32 pref
= num
.toInt32() - 1;
682 if( pref
< 0 || Elements
.size() <= sal_uInt32( pref
) )
683 throw NoSuchElementException();
685 return Elements
[pref
]->getByHierarchicalName( name
.copy( 1 + idx
) );
688 return getByName( name
);
694 TVChildTarget::hasByHierarchicalName( const OUString
& aName
)
695 throw( RuntimeException
)
698 OUString
name( aName
);
700 if( ( idx
= name
.indexOf( sal_Unicode( '/' ) ) ) != -1 )
702 OUString
num( name
.getStr()+2,idx
-4 );
703 sal_Int32 pref
= num
.toInt32() - 1;
704 if( pref
< 0 || Elements
.size() <= sal_uInt32( pref
) )
707 return Elements
[pref
]->hasByHierarchicalName( name
.copy( 1 + idx
) );
710 return hasByName( name
);
718 ConfigData
TVChildTarget::init( const Reference
< XMultiServiceFactory
>& xSMgr
)
720 ConfigData configData
;
721 Reference
< XMultiServiceFactory
> sProvider( getConfiguration(comphelper::getComponentContext(xSMgr
)) );
723 /**********************************************************************/
724 /* reading Office.Common */
725 /**********************************************************************/
727 Reference
< XHierarchicalNameAccess
> xHierAccess( getHierAccess( sProvider
,
728 "org.openoffice.Office.Common" ) );
729 OUString
system( getKey( xHierAccess
,"Help/System" ) );
730 sal_Bool
showBasic( getBooleanKey(xHierAccess
,"Help/ShowBasic") );
731 OUString
instPath( getKey( xHierAccess
,"Path/Current/Help" ) );
732 if( instPath
.isEmpty() )
733 // try to determine path from default
734 instPath
= OUString( "$(instpath)/help" );
736 // replace anything like $(instpath);
737 subst( xSMgr
,instPath
);
739 /**********************************************************************/
741 /**********************************************************************/
743 xHierAccess
= getHierAccess( sProvider
,
744 "org.openoffice.Setup" );
746 OUString
setupversion( getKey( xHierAccess
,"Product/ooSetupVersion" ) );
747 OUString setupextension
;
751 Reference
< lang::XMultiServiceFactory
> xConfigProvider
= theDefaultProvider::get( comphelper::getComponentContext(xSMgr
) );
753 uno::Sequence
< uno::Any
> lParams(1);
754 beans::PropertyValue aParam
;
755 aParam
.Name
= OUString("nodepath");
756 aParam
.Value
<<= OUString("/org.openoffice.Setup/Product");
757 lParams
[0] = uno::makeAny(aParam
);
760 uno::Reference
< uno::XInterface
> xCFG( xConfigProvider
->createInstanceWithArguments(
761 OUString("com.sun.star.configuration.ConfigurationAccess"),
764 uno::Reference
< container::XNameAccess
> xDirectAccess(xCFG
, uno::UNO_QUERY
);
765 uno::Any aRet
= xDirectAccess
->getByName(OUString("ooSetupExtension"));
767 aRet
>>= setupextension
;
769 catch ( uno::Exception
& )
773 OUString
productVersion( setupversion
+
776 OUString
locale( getKey( xHierAccess
,"L10N/ooLocale" ) );
779 // Determine fileurl from url and locale
781 osl::FileBase::RC errFile
= osl::FileBase::getFileURLFromSystemPath( instPath
,url
);
782 if( errFile
!= osl::FileBase::E_None
) return configData
;
783 if( url
.lastIndexOf( sal_Unicode( '/' ) ) != url
.getLength() - 1 )
784 url
+= OUString( "/" );
787 osl::DirectoryItem aDirItem
;
788 if( osl::FileBase::E_None
== osl::DirectoryItem::get( url
+ locale
,aDirItem
) )
790 else if( ( ( idx
= locale
.indexOf( '-' ) ) != -1 ||
791 ( idx
= locale
.indexOf( '_' ) ) != -1 ) &&
792 osl::FileBase::E_None
== osl::DirectoryItem::get( url
+ locale
.copy( 0,idx
),
794 ret
= locale
.copy( 0,idx
);
797 locale
= OUString( "en-US" );
798 ret
= OUString("en");
802 // first of all, try do determine whether there are any *.tree files present
804 // Start with extensions to set them at the end of the list
805 TreeFileIterator
aTreeIt( locale
);
808 while( !(aTreeFile
= aTreeIt
.nextTreeFile( nFileSize
) ).isEmpty() )
810 configData
.vFileLen
.push_back( nFileSize
);
811 configData
.vFileURL
.push_back( aTreeFile
);
814 osl::Directory
aDirectory( url
);
815 osl::FileStatus
aFileStatus(
816 osl_FileStatus_Mask_FileName
| osl_FileStatus_Mask_FileURL
);
817 if( osl::Directory::E_None
== aDirectory
.open() )
820 OUString aFileUrl
, aFileName
;
821 while( aDirectory
.getNextItem( aDirItem
) == osl::FileBase::E_None
&&
822 aDirItem
.getFileStatus( aFileStatus
) == osl::FileBase::E_None
&&
823 aFileStatus
.isValid( osl_FileStatus_Mask_FileURL
) &&
824 aFileStatus
.isValid( osl_FileStatus_Mask_FileName
) )
826 aFileUrl
= aFileStatus
.getFileURL();
827 aFileName
= aFileStatus
.getFileName();
828 idx_
= aFileName
.lastIndexOf( sal_Unicode( '.' ) );
832 const sal_Unicode
* str
= aFileName
.getStr();
834 if( aFileName
.getLength() == idx_
+ 5 &&
835 ( str
[idx_
+ 1] == 't' || str
[idx_
+ 1] == 'T' ) &&
836 ( str
[idx_
+ 2] == 'r' || str
[idx_
+ 2] == 'R' ) &&
837 ( str
[idx_
+ 3] == 'e' || str
[idx_
+ 3] == 'E' ) &&
838 ( str
[idx_
+ 4] == 'e' || str
[idx_
+ 4] == 'E' ) )
840 OUString baseName
= aFileName
.copy(0,idx_
).toAsciiLowerCase();
841 if(! showBasic
&& baseName
.compareToAscii("sbasic") == 0 )
843 osl::File
aFile( aFileUrl
);
844 if( osl::FileBase::E_None
== aFile
.open( osl_File_OpenFlag_Read
) )
846 // use the file size, not aFileStatus size, in case the
847 // tree file is a symlink
849 aFile
.getSize( nSize
);
850 configData
.vFileLen
.push_back( nSize
);
851 configData
.vFileURL
.push_back( aFileUrl
);
859 configData
.m_vAdd
[0] = 12;
860 configData
.m_vAdd
[1] = 15;
861 configData
.m_vAdd
[2] = 11;
862 configData
.m_vAdd
[3] = 14;
863 configData
.m_vAdd
[4] = 12;
864 configData
.m_vReplacement
[0] = utl::ConfigManager::getProductName();
865 configData
.m_vReplacement
[1] = productVersion
;
866 // m_vReplacement[2...4] (vendorName/-Version/-Short) are empty strings
868 configData
.system
= system
;
869 configData
.locale
= locale
;
870 configData
.appendix
=
871 OUString( "?Language=" ) +
873 OUString( "&System=" ) +
875 OUString( "&UseDB=no" ) ;
888 Reference
< XMultiServiceFactory
>
889 TVChildTarget::getConfiguration(const Reference
< XComponentContext
>& rxContext
) const
891 Reference
< XMultiServiceFactory
> xProvider
;
896 xProvider
= theDefaultProvider::get( rxContext
);
898 catch( const com::sun::star::uno::Exception
& )
900 OSL_ENSURE( xProvider
.is(),"cant instantiate configuration" );
909 Reference
< XHierarchicalNameAccess
>
910 TVChildTarget::getHierAccess( const Reference
< XMultiServiceFactory
>& sProvider
,
911 const char* file
) const
913 Reference
< XHierarchicalNameAccess
> xHierAccess
;
917 Sequence
< Any
> seq(1);
918 OUString sReaderService
=
919 OUString( "com.sun.star.configuration.ConfigurationAccess" );
921 seq
[0] <<= OUString::createFromAscii( file
);
926 Reference
< XHierarchicalNameAccess
>
927 ( sProvider
->createInstanceWithArguments( sReaderService
,seq
),
930 catch( const com::sun::star::uno::Exception
& )
941 TVChildTarget::getKey( const Reference
< XHierarchicalNameAccess
>& xHierAccess
,
942 const char* key
) const
945 if( xHierAccess
.is() )
951 xHierAccess
->getByHierarchicalName( OUString::createFromAscii( key
) );
953 catch( const com::sun::star::container::NoSuchElementException
& )
963 TVChildTarget::getBooleanKey(const Reference
<
964 XHierarchicalNameAccess
>& xHierAccess
,
965 const char* key
) const
967 sal_Bool ret
= sal_False
;
968 if( xHierAccess
.is() )
974 xHierAccess
->getByHierarchicalName(
975 OUString::createFromAscii(key
));
977 catch( const com::sun::star::container::NoSuchElementException
& )
986 void TVChildTarget::subst( const Reference
< XMultiServiceFactory
>& m_xSMgr
,
987 OUString
& instpath
) const
989 Reference
< XConfigManager
> xCfgMgr
;
995 Reference
< XConfigManager
>(
996 m_xSMgr
->createInstance( OUString( "com.sun.star.config.SpecialConfigManager" ) ),
999 catch( const com::sun::star::uno::Exception
& )
1001 OSL_ENSURE( xCfgMgr
.is()," cant instantiate the special config manager " );
1005 OSL_ENSURE( xCfgMgr
.is(), "specialconfigmanager not found\n" );
1008 instpath
= xCfgMgr
->substituteVariables( instpath
);
1012 //===================================================================
1013 // class ExtensionIteratorBase
1015 static OUString
aSlash("/");
1016 static OUString
aHelpFilesBaseName("help");
1017 static OUString
aHelpMediaType("application/vnd.sun.star.help");
1019 ExtensionIteratorBase::ExtensionIteratorBase( const OUString
& aLanguage
)
1020 : m_eState( USER_EXTENSIONS
)
1021 , m_aLanguage( aLanguage
)
1026 void ExtensionIteratorBase::init()
1028 m_xContext
= ::comphelper::getProcessComponentContext();
1029 if( !m_xContext
.is() )
1031 throw RuntimeException(
1032 OUString( "ExtensionIteratorBase::init(), no XComponentContext" ),
1033 Reference
< XInterface
>() );
1036 m_xSFA
= ucb::SimpleFileAccess::create(m_xContext
);
1038 m_bUserPackagesLoaded
= false;
1039 m_bSharedPackagesLoaded
= false;
1040 m_bBundledPackagesLoaded
= false;
1042 m_iSharedPackage
= 0;
1043 m_iBundledPackage
= 0;
1046 Reference
< deployment::XPackage
> ExtensionIteratorBase::implGetHelpPackageFromPackage
1047 ( Reference
< deployment::XPackage
> xPackage
, Reference
< deployment::XPackage
>& o_xParentPackageBundle
)
1049 o_xParentPackageBundle
.clear();
1051 Reference
< deployment::XPackage
> xHelpPackage
;
1052 if( !xPackage
.is() )
1053 return xHelpPackage
;
1055 // Check if parent package is registered
1056 beans::Optional
< beans::Ambiguous
<sal_Bool
> > option( xPackage
->isRegistered
1057 ( Reference
<task::XAbortChannel
>(), Reference
<ucb::XCommandEnvironment
>() ) );
1058 bool bRegistered
= false;
1059 if( option
.IsPresent
)
1061 beans::Ambiguous
<sal_Bool
> const & reg
= option
.Value
;
1062 if( !reg
.IsAmbiguous
&& reg
.Value
)
1066 return xHelpPackage
;
1068 if( xPackage
->isBundle() )
1070 Sequence
< Reference
< deployment::XPackage
> > aPkgSeq
= xPackage
->getBundle
1071 ( Reference
<task::XAbortChannel
>(), Reference
<ucb::XCommandEnvironment
>() );
1072 sal_Int32 nPkgCount
= aPkgSeq
.getLength();
1073 const Reference
< deployment::XPackage
>* pSeq
= aPkgSeq
.getConstArray();
1074 for( sal_Int32 iPkg
= 0 ; iPkg
< nPkgCount
; ++iPkg
)
1076 const Reference
< deployment::XPackage
> xSubPkg
= pSeq
[ iPkg
];
1077 const Reference
< deployment::XPackageTypeInfo
> xPackageTypeInfo
= xSubPkg
->getPackageType();
1078 OUString aMediaType
= xPackageTypeInfo
->getMediaType();
1079 if( aMediaType
.equals( aHelpMediaType
) )
1081 xHelpPackage
= xSubPkg
;
1082 o_xParentPackageBundle
= xPackage
;
1089 const Reference
< deployment::XPackageTypeInfo
> xPackageTypeInfo
= xPackage
->getPackageType();
1090 OUString aMediaType
= xPackageTypeInfo
->getMediaType();
1091 if( aMediaType
.equals( aHelpMediaType
) )
1092 xHelpPackage
= xPackage
;
1095 return xHelpPackage
;
1098 Reference
< deployment::XPackage
> ExtensionIteratorBase::implGetNextUserHelpPackage
1099 ( Reference
< deployment::XPackage
>& o_xParentPackageBundle
)
1101 Reference
< deployment::XPackage
> xHelpPackage
;
1103 if( !m_bUserPackagesLoaded
)
1105 Reference
< XPackageManager
> xUserManager
=
1106 thePackageManagerFactory::get( m_xContext
)->getPackageManager( OUString("user") );
1107 m_aUserPackagesSeq
= xUserManager
->getDeployedPackages
1108 ( Reference
< task::XAbortChannel
>(), Reference
< ucb::XCommandEnvironment
>() );
1110 m_bUserPackagesLoaded
= true;
1113 if( m_iUserPackage
== m_aUserPackagesSeq
.getLength() )
1115 m_eState
= SHARED_EXTENSIONS
; // Later: SHARED_MODULE
1119 const Reference
< deployment::XPackage
>* pUserPackages
= m_aUserPackagesSeq
.getConstArray();
1120 Reference
< deployment::XPackage
> xPackage
= pUserPackages
[ m_iUserPackage
++ ];
1121 OSL_ENSURE( xPackage
.is(), "ExtensionIteratorBase::implGetNextUserHelpPackage(): Invalid package" );
1122 xHelpPackage
= implGetHelpPackageFromPackage( xPackage
, o_xParentPackageBundle
);
1125 return xHelpPackage
;
1128 Reference
< deployment::XPackage
> ExtensionIteratorBase::implGetNextSharedHelpPackage
1129 ( Reference
< deployment::XPackage
>& o_xParentPackageBundle
)
1131 Reference
< deployment::XPackage
> xHelpPackage
;
1133 if( !m_bSharedPackagesLoaded
)
1135 Reference
< XPackageManager
> xSharedManager
=
1136 thePackageManagerFactory::get( m_xContext
)->getPackageManager( OUString("shared") );
1137 m_aSharedPackagesSeq
= xSharedManager
->getDeployedPackages
1138 ( Reference
< task::XAbortChannel
>(), Reference
< ucb::XCommandEnvironment
>() );
1140 m_bSharedPackagesLoaded
= true;
1143 if( m_iSharedPackage
== m_aSharedPackagesSeq
.getLength() )
1145 m_eState
= BUNDLED_EXTENSIONS
;
1149 const Reference
< deployment::XPackage
>* pSharedPackages
= m_aSharedPackagesSeq
.getConstArray();
1150 Reference
< deployment::XPackage
> xPackage
= pSharedPackages
[ m_iSharedPackage
++ ];
1151 OSL_ENSURE( xPackage
.is(), "ExtensionIteratorBase::implGetNextSharedHelpPackage(): Invalid package" );
1152 xHelpPackage
= implGetHelpPackageFromPackage( xPackage
, o_xParentPackageBundle
);
1155 return xHelpPackage
;
1158 Reference
< deployment::XPackage
> ExtensionIteratorBase::implGetNextBundledHelpPackage
1159 ( Reference
< deployment::XPackage
>& o_xParentPackageBundle
)
1161 Reference
< deployment::XPackage
> xHelpPackage
;
1163 if( !m_bBundledPackagesLoaded
)
1165 Reference
< XPackageManager
> xBundledManager
=
1166 thePackageManagerFactory::get( m_xContext
)->getPackageManager( OUString("bundled") );
1167 m_aBundledPackagesSeq
= xBundledManager
->getDeployedPackages
1168 ( Reference
< task::XAbortChannel
>(), Reference
< ucb::XCommandEnvironment
>() );
1170 m_bBundledPackagesLoaded
= true;
1173 if( m_iBundledPackage
== m_aBundledPackagesSeq
.getLength() )
1175 m_eState
= END_REACHED
;
1179 const Reference
< deployment::XPackage
>* pBundledPackages
= m_aBundledPackagesSeq
.getConstArray();
1180 Reference
< deployment::XPackage
> xPackage
= pBundledPackages
[ m_iBundledPackage
++ ];
1181 OSL_ENSURE( xPackage
.is(), "ExtensionIteratorBase::implGetNextBundledHelpPackage(): Invalid package" );
1182 xHelpPackage
= implGetHelpPackageFromPackage( xPackage
, o_xParentPackageBundle
);
1185 return xHelpPackage
;
1188 inline bool isLetter( sal_Unicode c
)
1190 return comphelper::string::isalphaAscii(c
);
1193 void ExtensionIteratorBase::implGetLanguageVectorFromPackage( ::std::vector
< OUString
> &rv
,
1194 com::sun::star::uno::Reference
< com::sun::star::deployment::XPackage
> xPackage
)
1197 OUString aExtensionPath
= xPackage
->getURL();
1198 Sequence
< OUString
> aEntrySeq
= m_xSFA
->getFolderContents( aExtensionPath
, true );
1200 const OUString
* pSeq
= aEntrySeq
.getConstArray();
1201 sal_Int32 nCount
= aEntrySeq
.getLength();
1202 for( sal_Int32 i
= 0 ; i
< nCount
; ++i
)
1204 OUString aEntry
= pSeq
[i
];
1205 if( m_xSFA
->isFolder( aEntry
) )
1207 sal_Int32 nLastSlash
= aEntry
.lastIndexOf( '/' );
1208 if( nLastSlash
!= -1 )
1210 OUString aPureEntry
= aEntry
.copy( nLastSlash
+ 1 );
1212 // Check language sceme
1213 int nLen
= aPureEntry
.getLength();
1214 const sal_Unicode
* pc
= aPureEntry
.getStr();
1215 bool bStartCanBeLanguage
= ( nLen
>= 2 && isLetter( pc
[0] ) && isLetter( pc
[1] ) );
1216 bool bIsLanguage
= bStartCanBeLanguage
&&
1217 ( nLen
== 2 || (nLen
== 5 && pc
[2] == '-' && isLetter( pc
[3] ) && isLetter( pc
[4] )) );
1219 rv
.push_back( aPureEntry
);
1226 //===================================================================
1227 // class TreeFileIterator
1229 OUString
TreeFileIterator::nextTreeFile( sal_Int32
& rnFileSize
)
1233 while( aRetFile
.isEmpty() && m_eState
!= END_REACHED
)
1237 case USER_EXTENSIONS
:
1239 Reference
< deployment::XPackage
> xParentPackageBundle
;
1240 Reference
< deployment::XPackage
> xHelpPackage
= implGetNextUserHelpPackage( xParentPackageBundle
);
1241 if( !xHelpPackage
.is() )
1244 aRetFile
= implGetTreeFileFromPackage( rnFileSize
, xHelpPackage
);
1248 case SHARED_EXTENSIONS
:
1250 Reference
< deployment::XPackage
> xParentPackageBundle
;
1251 Reference
< deployment::XPackage
> xHelpPackage
= implGetNextSharedHelpPackage( xParentPackageBundle
);
1252 if( !xHelpPackage
.is() )
1255 aRetFile
= implGetTreeFileFromPackage( rnFileSize
, xHelpPackage
);
1258 case BUNDLED_EXTENSIONS
:
1260 Reference
< deployment::XPackage
> xParentPackageBundle
;
1261 Reference
< deployment::XPackage
> xHelpPackage
= implGetNextBundledHelpPackage( xParentPackageBundle
);
1262 if( !xHelpPackage
.is() )
1265 aRetFile
= implGetTreeFileFromPackage( rnFileSize
, xHelpPackage
);
1270 OSL_FAIL( "DataBaseIterator::nextTreeFile(): Invalid case END_REACHED" );
1278 OUString
TreeFileIterator::expandURL( const OUString
& aURL
)
1280 static Reference
< util::XMacroExpander
> xMacroExpander
;
1281 static Reference
< uri::XUriReferenceFactory
> xFac
;
1283 osl::MutexGuard
aGuard( m_aMutex
);
1285 if( !xMacroExpander
.is() || !xFac
.is() )
1287 xFac
= uri::UriReferenceFactory::create( m_xContext
);
1289 xMacroExpander
= util::theMacroExpander::get(m_xContext
);
1292 OUString aRetURL
= aURL
;
1293 Reference
< uri::XUriReference
> uriRef
;
1296 uriRef
= Reference
< uri::XUriReference
>( xFac
->parse( aRetURL
), UNO_QUERY
);
1299 Reference
< uri::XVndSunStarExpandUrl
> sxUri( uriRef
, UNO_QUERY
);
1303 aRetURL
= sxUri
->expand( xMacroExpander
);
1309 OUString
TreeFileIterator::implGetTreeFileFromPackage
1310 ( sal_Int32
& rnFileSize
, Reference
< deployment::XPackage
> xPackage
)
1313 OUString aLanguage
= m_aLanguage
;
1314 for( sal_Int32 iPass
= 0 ; iPass
< 2 ; ++iPass
)
1316 OUStringBuffer aStrBuf
;
1317 aStrBuf
.append( xPackage
->getURL() );
1318 aStrBuf
.append( aSlash
);
1319 aStrBuf
.append( aLanguage
);
1320 aStrBuf
.append( aSlash
);
1321 aStrBuf
.append( aHelpFilesBaseName
);
1322 aStrBuf
.appendAscii( ".tree" );
1324 aRetFile
= expandURL( aStrBuf
.makeStringAndClear() );
1327 if( m_xSFA
->exists( aRetFile
) )
1330 ::std::vector
< OUString
> av
;
1331 implGetLanguageVectorFromPackage( av
, xPackage
);
1332 ::std::vector
< OUString
>::const_iterator pFound
= LanguageTag::getFallback( av
, m_aLanguage
);
1333 if( pFound
!= av
.end() )
1334 aLanguage
= *pFound
;
1339 if( m_xSFA
->exists( aRetFile
) )
1340 rnFileSize
= m_xSFA
->getSize( aRetFile
);
1342 aRetFile
= OUString();
1349 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */