bump product version to 4.1.6.2
[LibreOffice.git] / xmlhelp / source / treeview / tvread.cxx
blob01ef477e9311489af49f05c89476b4f3a26936a5
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
20 #include <string.h>
21 #include <rtl/ustrbuf.hxx>
22 #include <osl/diagnose.h>
23 #include "tvread.hxx"
24 #include <expat.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>
40 namespace treeview {
43 class TVDom
45 friend class TVChildTarget;
46 friend class TVRead;
48 public:
50 TVDom( TVDom* arent = 0 )
51 : kind( other ),
52 parent( arent ),
53 children( 0 )
57 ~TVDom()
59 for( unsigned i = 0; i < children.size(); ++i )
60 delete children[i];
64 TVDom* newChild()
66 children.push_back( new TVDom( this ) );
67 return children.back();
70 TVDom* newChild(TVDom* p)
72 children.push_back( p );
73 p->parent = this;
74 return children.back();
78 TVDom* getParent() const
80 if( parent )
81 return parent;
82 else
83 return const_cast<TVDom*>(this); // I am my own parent, if I am the root
86 enum Kind {
87 tree_view,
88 tree_node,
89 tree_leaf,
90 other
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),
101 strlen( appl ),
102 RTL_TEXTENCODING_UTF8 );
105 void setTitle( const char* itle )
107 title += OUString( (sal_Char*)(itle),
108 strlen( itle ),
109 RTL_TEXTENCODING_UTF8 );
112 void setTitle( const XML_Char* itle,int len )
114 title += OUString( (sal_Char*)(itle),
115 len,
116 RTL_TEXTENCODING_UTF8 );
119 void setId( const char* d )
121 id = OUString( (sal_Char*)(d),
122 strlen( d ),
123 RTL_TEXTENCODING_UTF8 );
126 void setAnchor( const char* nchor )
128 anchor = OUString( (sal_Char*)(nchor),
129 strlen( nchor ),
130 RTL_TEXTENCODING_UTF8 );
133 OUString getTargetURL()
135 if( targetURL.isEmpty() )
137 sal_Int32 len;
138 for ( const TVDom* p = this;; p = p->parent )
140 len = p->application.getLength();
141 if ( len != 0 )
142 break;
145 OUStringBuffer strBuff( 22 + len + id.getLength() );
146 strBuff.appendAscii(
147 "vnd.sun.star.help://"
148 ).append(id);
150 targetURL = strBuff.makeStringAndClear();
153 return targetURL;
156 private:
158 Kind kind;
159 OUString application;
160 OUString title;
161 OUString id;
162 OUString anchor;
163 OUString targetURL;
165 TVDom *parent;
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;
197 bool cap = false;
198 OUStringBuffer aStrBuf( 0 );
200 while( ( idx = oustring.indexOf( sal_Unicode('%'),++idx ) ) != -1 )
202 if( oustring.indexOf( prodName,idx ) == idx )
203 off = PRODUCTNAME;
204 else if( oustring.indexOf( prodVersion,idx ) == idx )
205 off = PRODUCTVERSION;
206 else if( oustring.indexOf( vendName,idx ) == idx )
207 off = VENDORNAME;
208 else if( oustring.indexOf( vendVersion,idx ) == idx )
209 off = VENDORVERSION;
210 else if( oustring.indexOf( vendShort,idx ) == idx )
211 off = VENDORSHORT;
212 else
213 off = -1;
215 if( off != -1 )
217 if( ! cap )
219 cap = true;
220 aStrBuf.ensureCapacity( 256 );
223 aStrBuf.append( &oustring.getStr()[k],idx - k );
224 aStrBuf.append( m_vReplacement[off] );
225 k = idx + m_vAdd[off];
229 if( cap )
231 if( k < oustring.getLength() )
232 aStrBuf.append( &oustring.getStr()[k],oustring.getLength()-k );
233 oustring = aStrBuf.makeStringAndClear();
240 //////////////////////////////////////////////////////////////////////////
241 // XInterface
242 //////////////////////////////////////////////////////////////////////////
245 void SAL_CALL
246 TVBase::acquire(
247 void )
248 throw()
250 OWeakObject::acquire();
254 void SAL_CALL
255 TVBase::release(
256 void )
257 throw()
259 OWeakObject::release();
263 Any SAL_CALL
264 TVBase::queryInterface(
265 const Type& rType )
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,
284 XTypeProvider,
285 XNameAccess,
286 XHierarchicalNameAccess,
287 XChangesNotifier,
288 XComponent );
295 // TVRead
298 TVRead::TVRead( const ConfigData& configData,TVDom* tvDom )
300 if( ! tvDom )
301 return;
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( "#" ) +
310 tvDom->anchor );
312 else
313 Children = new TVChildTarget( configData,tvDom );
318 TVRead::~TVRead()
327 // XNameAccess
329 Any SAL_CALL
330 TVRead::getByName( const OUString& aName )
331 throw( NoSuchElementException,
332 WrappedTargetException,
333 RuntimeException )
335 bool found( true );
336 Any aAny;
337 if( aName.compareToAscii( "Title" ) == 0 )
338 aAny <<= Title;
339 else if( aName.compareToAscii( "TargetURL" ) == 0 )
340 aAny <<= TargetURL;
341 else if( aName.compareToAscii( "Children" ) == 0 )
343 cppu::OWeakObject* p = Children.get();
344 aAny <<= Reference< XInterface >( p );
346 else
347 found = false;
349 if( found )
350 return aAny;
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" );
368 return seq;
373 sal_Bool SAL_CALL
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 )
380 return true;
382 return false;
386 // XHierarchicalNameAccess
388 Any SAL_CALL
389 TVRead::getByHierarchicalName( const OUString& aName )
390 throw( NoSuchElementException,
391 RuntimeException )
393 sal_Int32 idx;
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 );
406 sal_Bool SAL_CALL
407 TVRead::hasByHierarchicalName( const OUString& aName )
408 throw( RuntimeException )
410 sal_Int32 idx;
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 /**************************************************************************/
423 /* */
424 /* TVChildTarget */
425 /* */
426 /**************************************************************************/
431 extern "C" void start_handler(void *userData,
432 const XML_Char *name,
433 const XML_Char **atts)
435 TVDom::Kind kind;
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;
442 else
443 return;
445 TVDom **tvDom = static_cast< TVDom** >( userData );
446 TVDom *p;
447 p = *tvDom;
449 *tvDom = p->newChild();
450 p = *tvDom;
452 p->setKind( kind );
453 while( *atts )
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) );
464 atts+=2;
469 extern "C" void end_handler(void *userData,
470 const XML_Char *name )
472 (void)name;
474 TVDom **tvDom = static_cast< TVDom** >( userData );
475 *tvDom = (*tvDom)->getParent();
479 extern "C" void data_handler( void *userData,
480 const XML_Char *s,
481 int len)
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() )
500 return;
502 sal_uInt64 ret,len = 0;
503 int j = configData.vFileURL.size();
505 TVDom tvDom;
506 TVDom* pTVDom = &tvDom;
508 while( j )
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 );
515 aFile.close();
517 XML_Parser parser = XML_ParserCreate( 0 );
518 XML_SetElementHandler( parser,
519 start_handler,
520 end_handler );
521 XML_SetCharacterDataHandler( parser,
522 data_handler);
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 );
530 delete[] s;
532 Check(pTVDom);
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())
550 return;
553 unsigned i = 0;
554 bool h = false;
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();
567 h = true;
569 ++i;
573 bool TVChildTarget::SearchAndInsert(TVDom* p, TVDom* tvDom)
575 if (p->isLeaf()) return false;
577 bool h = false;
578 sal_Int32 max = 0;
580 std::vector< TVDom* >::iterator max_It, i;
581 max_It = tvDom->children.begin();
583 sal_Int32 c_int;
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
592 h = true;
593 c_int = (*i)->id.toInt32();
595 if (p_int==c_int)
597 (*(tvDom->children.insert(i+1, p)))->parent = tvDom;
598 return true;
600 else if(c_int>max && c_int < p_int)
602 max = c_int;
603 max_It = i+1;
606 ////////////////////////////////recursive call if necessary
607 if (h) (*(tvDom->children.insert(max_It, p)))->parent = tvDom;
608 else
610 i = tvDom->children.begin();
611 while ((i!=tvDom->children.end()) && (!h))
613 h = SearchAndInsert(p, *i);
614 ++i;
617 return h;
620 Any SAL_CALL
621 TVChildTarget::getByName( const OUString& aName )
622 throw( NoSuchElementException,
623 WrappedTargetException,
624 RuntimeException )
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();
631 Any aAny;
632 cppu::OWeakObject* p = Elements[idx].get();
633 aAny <<= Reference< XInterface >( p );
634 return aAny;
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 ) );
648 return seq;
653 sal_Bool SAL_CALL
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 ) )
660 return false;
662 return true;
667 // XHierarchicalNameAccess
669 Any SAL_CALL
670 TVChildTarget::getByHierarchicalName( const OUString& aName )
671 throw( NoSuchElementException,
672 RuntimeException )
674 sal_Int32 idx;
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 ) );
687 else
688 return getByName( name );
693 sal_Bool SAL_CALL
694 TVChildTarget::hasByHierarchicalName( const OUString& aName )
695 throw( RuntimeException )
697 sal_Int32 idx;
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 ) )
705 return false;
707 return Elements[pref]->hasByHierarchicalName( name.copy( 1 + idx ) );
709 else
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 /**********************************************************************/
740 /* reading setup */
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);
759 // open it
760 uno::Reference< uno::XInterface > xCFG( xConfigProvider->createInstanceWithArguments(
761 OUString("com.sun.star.configuration.ConfigurationAccess"),
762 lParams) );
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 +
774 OUString( " " ) +
775 setupextension );
776 OUString locale( getKey( xHierAccess,"L10N/ooLocale" ) );
779 // Determine fileurl from url and locale
780 OUString url;
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( "/" );
785 OUString ret;
786 sal_Int32 idx;
787 osl::DirectoryItem aDirItem;
788 if( osl::FileBase::E_None == osl::DirectoryItem::get( url + locale,aDirItem ) )
789 ret = locale;
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 ),
793 aDirItem ) )
794 ret = locale.copy( 0,idx );
795 else
797 locale = OUString( "en-US" );
798 ret = OUString("en");
800 url = url + ret;
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 );
806 OUString aTreeFile;
807 sal_Int32 nFileSize;
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() )
819 int idx_ = 0;
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( '.' ) );
829 if( idx_ == -1 )
830 continue;
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 )
842 continue;
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
848 sal_uInt64 nSize;
849 aFile.getSize( nSize );
850 configData.vFileLen.push_back( nSize );
851 configData.vFileURL.push_back( aFileUrl );
852 aFile.close();
856 aDirectory.close();
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=" ) +
872 configData.locale +
873 OUString( "&System=" ) +
874 configData.system +
875 OUString( "&UseDB=no" ) ;
877 return configData;
888 Reference< XMultiServiceFactory >
889 TVChildTarget::getConfiguration(const Reference< XComponentContext >& rxContext) const
891 Reference< XMultiServiceFactory > xProvider;
892 if( rxContext.is() )
896 xProvider = theDefaultProvider::get( rxContext );
898 catch( const com::sun::star::uno::Exception& )
900 OSL_ENSURE( xProvider.is(),"cant instantiate configuration" );
904 return xProvider;
909 Reference< XHierarchicalNameAccess >
910 TVChildTarget::getHierAccess( const Reference< XMultiServiceFactory >& sProvider,
911 const char* file ) const
913 Reference< XHierarchicalNameAccess > xHierAccess;
915 if( sProvider.is() )
917 Sequence< Any > seq(1);
918 OUString sReaderService =
919 OUString( "com.sun.star.configuration.ConfigurationAccess" );
921 seq[0] <<= OUString::createFromAscii( file );
925 xHierAccess =
926 Reference< XHierarchicalNameAccess >
927 ( sProvider->createInstanceWithArguments( sReaderService,seq ),
928 UNO_QUERY );
930 catch( const com::sun::star::uno::Exception& )
935 return xHierAccess;
940 OUString
941 TVChildTarget::getKey( const Reference< XHierarchicalNameAccess >& xHierAccess,
942 const char* key ) const
944 OUString instPath;
945 if( xHierAccess.is() )
947 Any aAny;
950 aAny =
951 xHierAccess->getByHierarchicalName( OUString::createFromAscii( key ) );
953 catch( const com::sun::star::container::NoSuchElementException& )
956 aAny >>= instPath;
958 return instPath;
962 sal_Bool
963 TVChildTarget::getBooleanKey(const Reference<
964 XHierarchicalNameAccess >& xHierAccess,
965 const char* key) const
967 sal_Bool ret = sal_False;
968 if( xHierAccess.is() )
970 Any aAny;
973 aAny =
974 xHierAccess->getByHierarchicalName(
975 OUString::createFromAscii(key));
977 catch( const com::sun::star::container::NoSuchElementException& )
980 aAny >>= ret;
982 return ret;
986 void TVChildTarget::subst( const Reference< XMultiServiceFactory >& m_xSMgr,
987 OUString& instpath ) const
989 Reference< XConfigManager > xCfgMgr;
990 if( m_xSMgr.is() )
994 xCfgMgr =
995 Reference< XConfigManager >(
996 m_xSMgr->createInstance( OUString( "com.sun.star.config.SpecialConfigManager" ) ),
997 UNO_QUERY );
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" );
1007 if( xCfgMgr.is() )
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 )
1023 init();
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;
1041 m_iUserPackage = 0;
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 )
1063 bRegistered = true;
1065 if( !bRegistered )
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;
1083 break;
1087 else
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
1117 else
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;
1147 else
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;
1177 else
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 )
1196 rv.clear();
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] )) );
1218 if( bIsLanguage )
1219 rv.push_back( aPureEntry );
1226 //===================================================================
1227 // class TreeFileIterator
1229 OUString TreeFileIterator::nextTreeFile( sal_Int32& rnFileSize )
1231 OUString aRetFile;
1233 while( aRetFile.isEmpty() && m_eState != END_REACHED )
1235 switch( m_eState )
1237 case USER_EXTENSIONS:
1239 Reference< deployment::XPackage > xParentPackageBundle;
1240 Reference< deployment::XPackage > xHelpPackage = implGetNextUserHelpPackage( xParentPackageBundle );
1241 if( !xHelpPackage.is() )
1242 break;
1244 aRetFile = implGetTreeFileFromPackage( rnFileSize, xHelpPackage );
1245 break;
1248 case SHARED_EXTENSIONS:
1250 Reference< deployment::XPackage > xParentPackageBundle;
1251 Reference< deployment::XPackage > xHelpPackage = implGetNextSharedHelpPackage( xParentPackageBundle );
1252 if( !xHelpPackage.is() )
1253 break;
1255 aRetFile = implGetTreeFileFromPackage( rnFileSize, xHelpPackage );
1256 break;
1258 case BUNDLED_EXTENSIONS:
1260 Reference< deployment::XPackage > xParentPackageBundle;
1261 Reference< deployment::XPackage > xHelpPackage = implGetNextBundledHelpPackage( xParentPackageBundle );
1262 if( !xHelpPackage.is() )
1263 break;
1265 aRetFile = implGetTreeFileFromPackage( rnFileSize, xHelpPackage );
1266 break;
1269 case END_REACHED:
1270 OSL_FAIL( "DataBaseIterator::nextTreeFile(): Invalid case END_REACHED" );
1271 break;
1275 return aRetFile;
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;
1294 for (;;)
1296 uriRef = Reference< uri::XUriReference >( xFac->parse( aRetURL ), UNO_QUERY );
1297 if ( uriRef.is() )
1299 Reference < uri::XVndSunStarExpandUrl > sxUri( uriRef, UNO_QUERY );
1300 if( !sxUri.is() )
1301 break;
1303 aRetURL = sxUri->expand( xMacroExpander );
1306 return aRetURL;
1309 OUString TreeFileIterator::implGetTreeFileFromPackage
1310 ( sal_Int32& rnFileSize, Reference< deployment::XPackage > xPackage )
1312 OUString aRetFile;
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() );
1325 if( iPass == 0 )
1327 if( m_xSFA->exists( aRetFile ) )
1328 break;
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;
1338 rnFileSize = 0;
1339 if( m_xSFA->exists( aRetFile ) )
1340 rnFileSize = m_xSFA->getSize( aRetFile );
1341 else
1342 aRetFile = OUString();
1344 return aRetFile;
1349 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */