diff options
Diffstat (limited to 'xmlhelp/source/treeview/tvread.cxx')
-rw-r--r-- | xmlhelp/source/treeview/tvread.cxx | 1320 |
1 files changed, 1320 insertions, 0 deletions
diff --git a/xmlhelp/source/treeview/tvread.cxx b/xmlhelp/source/treeview/tvread.cxx new file mode 100644 index 000000000000..73c413394763 --- /dev/null +++ b/xmlhelp/source/treeview/tvread.cxx @@ -0,0 +1,1320 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_xmlhelp.hxx" + +#include <string.h> +#include <rtl/ustrbuf.hxx> +#ifndef _VOS_DIAGNOSE_HXX_ +#include <vos/diagnose.hxx> +#endif +#include "tvread.hxx" +#include <expat.h> +#include <osl/file.hxx> +#include <com/sun/star/frame/XConfigManager.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> + +#include <comphelper/processfactory.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> +#include "com/sun/star/deployment/thePackageManagerFactory.hpp" +#include <com/sun/star/util/XMacroExpander.hpp> +#include <com/sun/star/uri/XUriReferenceFactory.hpp> +#include <com/sun/star/uri/XVndSunStarExpandUrl.hpp> +#include <comphelper/locale.hxx> + +namespace treeview { + + + class TVDom + { + friend class TVChildTarget; + friend class TVRead; + + public: + + TVDom( TVDom* arent = 0 ) + : kind( other ), + parent( arent ), + childs( 0 ) + { + } + + ~TVDom() + { + for( unsigned i = 0; i < childs.size(); ++i ) + delete childs[i]; + } + + + TVDom* newChild() + { + childs.push_back( new TVDom( this ) ); + return childs.back(); + } + + + TVDom* getParent() const + { + if( parent ) + return parent; + else + return const_cast<TVDom*>(this); // I am my own parent, if I am the root + } + + enum Kind { + tree_view, + tree_node, + tree_leaf, + other + }; + + bool isLeaf() const { return kind == TVDom::tree_leaf; } + void setKind( Kind ind ) { kind = ind; } + Kind getKind( ) const { return kind; } + + + void setApplication( const char* appl ) + { + application = rtl::OUString( (sal_Char*)(appl), + strlen( appl ), + RTL_TEXTENCODING_UTF8 ); + } + + void setTitle( const char* itle ) + { + title += rtl::OUString( (sal_Char*)(itle), + strlen( itle ), + RTL_TEXTENCODING_UTF8 ); + } + + void setTitle( const XML_Char* itle,int len ) + { + title += rtl::OUString( (sal_Char*)(itle), + len, + RTL_TEXTENCODING_UTF8 ); + } + + void setId( const char* d ) + { + id = rtl::OUString( (sal_Char*)(d), + strlen( d ), + RTL_TEXTENCODING_UTF8 ); + } + + void setAnchor( const char* nchor ) + { + anchor = rtl::OUString( (sal_Char*)(nchor), + strlen( nchor ), + RTL_TEXTENCODING_UTF8 ); + } + + rtl::OUString getTargetURL() + { + if( ! targetURL.getLength() ) + { + sal_Int32 len; + for ( const TVDom* p = this;; p = p->parent ) + { + len = p->application.getLength(); + if ( len != 0 ) + break; + } + + rtl::OUStringBuffer strBuff( 22 + len + id.getLength() ); + strBuff.appendAscii( + "vnd.sun.star.help://" + ).append(id); + + targetURL = strBuff.makeStringAndClear(); + } + + return targetURL; + } + + private: + + Kind kind; + rtl::OUString application; + rtl::OUString title; + rtl::OUString id; + rtl::OUString anchor; + rtl::OUString targetURL; + + TVDom *parent; + std::vector< TVDom* > childs; + }; + +} + + + +using namespace treeview; +using namespace com::sun::star; +using namespace com::sun::star::uno; +using namespace com::sun::star::beans; +using namespace com::sun::star::lang; +using namespace com::sun::star::util; +using namespace com::sun::star::frame; +using namespace com::sun::star::container; +using namespace com::sun::star::deployment; + + +ConfigData::ConfigData() + : prodName( rtl::OUString::createFromAscii( "%PRODUCTNAME" ) ), + prodVersion( rtl::OUString::createFromAscii( "%PRODUCTVERSION" ) ), + vendName( rtl::OUString::createFromAscii( "%VENDORNAME" ) ), + vendVersion( rtl::OUString::createFromAscii( "%VENDORVERSION" ) ), + vendShort( rtl::OUString::createFromAscii( "%VENDORSHORT" ) ) +{ +} + +void SAL_CALL ConfigData::replaceName( rtl::OUString& oustring ) const +{ + sal_Int32 idx = -1,k = 0,off; + bool cap = false; + rtl::OUStringBuffer aStrBuf( 0 ); + + while( ( idx = oustring.indexOf( sal_Unicode('%'),++idx ) ) != -1 ) + { + if( oustring.indexOf( prodName,idx ) == idx ) + off = PRODUCTNAME; + else if( oustring.indexOf( prodVersion,idx ) == idx ) + off = PRODUCTVERSION; + else if( oustring.indexOf( vendName,idx ) == idx ) + off = VENDORNAME; + else if( oustring.indexOf( vendVersion,idx ) == idx ) + off = VENDORVERSION; + else if( oustring.indexOf( vendShort,idx ) == idx ) + off = VENDORSHORT; + else + off = -1; + + if( off != -1 ) + { + if( ! cap ) + { + cap = true; + aStrBuf.ensureCapacity( 256 ); + } + + aStrBuf.append( &oustring.getStr()[k],idx - k ); + aStrBuf.append( m_vReplacement[off] ); + k = idx + m_vAdd[off]; + } + } + + if( cap ) + { + if( k < oustring.getLength() ) + aStrBuf.append( &oustring.getStr()[k],oustring.getLength()-k ); + oustring = aStrBuf.makeStringAndClear(); + } +} + + + + +////////////////////////////////////////////////////////////////////////// +// XInterface +////////////////////////////////////////////////////////////////////////// + + +void SAL_CALL +TVBase::acquire( + void ) + throw() +{ + OWeakObject::acquire(); +} + + +void SAL_CALL +TVBase::release( + void ) + throw() +{ + OWeakObject::release(); +} + + +Any SAL_CALL +TVBase::queryInterface( + const Type& rType ) + throw( RuntimeException ) +{ + Any aRet = cppu::queryInterface( rType, + SAL_STATIC_CAST( XTypeProvider*, this ), + SAL_STATIC_CAST( XNameAccess*, this ), + SAL_STATIC_CAST( XHierarchicalNameAccess*, this ), + SAL_STATIC_CAST( XChangesNotifier*, this ), + SAL_STATIC_CAST( XComponent*, this ) ); + + return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ); +} + + +//////////////////////////////////////////////////////////////////////////////// +// +// XTypeProvider methods. + +XTYPEPROVIDER_IMPL_5( TVBase, + XTypeProvider, + XNameAccess, + XHierarchicalNameAccess, + XChangesNotifier, + XComponent ); + + + + + + +// TVRead + + +TVRead::TVRead( const ConfigData& configData,TVDom* tvDom ) +{ + if( ! tvDom ) + return; + + Title = tvDom->title; + configData.replaceName( Title ); + if( tvDom->isLeaf() ) + { + TargetURL = ( tvDom->getTargetURL() + configData.appendix ); + if( tvDom->anchor.getLength() ) + TargetURL += ( rtl::OUString::createFromAscii( "#" ) + + tvDom->anchor ); + } + else + Children = new TVChildTarget( configData,tvDom ); +} + + + +TVRead::~TVRead() +{ +} + + + + + + +// XNameAccess + +Any SAL_CALL +TVRead::getByName( const rtl::OUString& aName ) + throw( NoSuchElementException, + WrappedTargetException, + RuntimeException ) +{ + bool found( true ); + Any aAny; + if( aName.compareToAscii( "Title" ) == 0 ) + aAny <<= Title; + else if( aName.compareToAscii( "TargetURL" ) == 0 ) + aAny <<= TargetURL; + else if( aName.compareToAscii( "Children" ) == 0 ) + { + cppu::OWeakObject* p = Children.get(); + aAny <<= Reference< XInterface >( p ); + } + else + found = false; + + if( found ) + return aAny; + + throw NoSuchElementException(); +} + + + + +Sequence< rtl::OUString > SAL_CALL +TVRead::getElementNames( ) + throw( RuntimeException ) +{ + Sequence< rtl::OUString > seq( 3 ); + + seq[0] = rtl::OUString::createFromAscii( "Title" ); + seq[1] = rtl::OUString::createFromAscii( "TargetURL" ); + seq[2] = rtl::OUString::createFromAscii( "Children" ); + + return seq; +} + + + +sal_Bool SAL_CALL +TVRead::hasByName( const rtl::OUString& aName ) + throw( RuntimeException ) +{ + if( aName.compareToAscii( "Title" ) == 0 || + aName.compareToAscii( "TargetURL" ) == 0 || + aName.compareToAscii( "Children" ) == 0 ) + return true; + + return false; +} + + +// XHierarchicalNameAccess + +Any SAL_CALL +TVRead::getByHierarchicalName( const rtl::OUString& aName ) + throw( NoSuchElementException, + RuntimeException ) +{ + sal_Int32 idx; + rtl::OUString name( aName ); + + if( ( idx = name.indexOf( sal_Unicode( '/' ) ) ) != -1 && + name.copy( 0,idx ).compareToAscii( "Children" ) == 0 ) + return Children->getByHierarchicalName( name.copy( 1 + idx ) ); + + return getByName( name ); +} + + + + +sal_Bool SAL_CALL +TVRead::hasByHierarchicalName( const rtl::OUString& aName ) + throw( RuntimeException ) +{ + sal_Int32 idx; + rtl::OUString name( aName ); + + if( ( idx = name.indexOf( sal_Unicode( '/' ) ) ) != -1 && + name.copy( 0,idx ).compareToAscii( "Children" ) == 0 ) + return Children->hasByHierarchicalName( name.copy( 1 + idx ) ); + + return hasByName( name ); +} + + + +/**************************************************************************/ +/* */ +/* TVChildTarget */ +/* */ +/**************************************************************************/ + + + + +extern "C" void start_handler(void *userData, + const XML_Char *name, + const XML_Char **atts) +{ + TVDom::Kind kind; + + if( strcmp( name,"help_section" ) == 0 || + strcmp( name,"node" ) == 0 ) + kind = TVDom::tree_node; + else if( strcmp( name,"topic" ) == 0 ) + kind = TVDom::tree_leaf; + else + return; + + TVDom **tvDom = static_cast< TVDom** >( userData ); + TVDom *p; + p = *tvDom; + + *tvDom = p->newChild(); + p = *tvDom; + + p->setKind( kind ); + while( *atts ) + { + if( strcmp( *atts,"application" ) == 0 ) + p->setApplication( *(atts+1) ); + else if( strcmp( *atts,"title" ) == 0 ) + p->setTitle( *(atts+1) ); + else if( strcmp( *atts,"id" ) == 0 ) + p->setId( *(atts+1) ); + else if( strcmp( *atts,"anchor" ) == 0 ) + p->setAnchor( *(atts+1) ); + + atts+=2; + } +} + + +extern "C" void end_handler(void *userData, + const XML_Char *name ) +{ + (void)name; + + TVDom **tvDom = static_cast< TVDom** >( userData ); + *tvDom = (*tvDom)->getParent(); +} + + +extern "C" void data_handler( void *userData, + const XML_Char *s, + int len) +{ + TVDom **tvDom = static_cast< TVDom** >( userData ); + if( (*tvDom)->isLeaf() ) + (*tvDom)->setTitle( s,len ); +} + + + +TVChildTarget::TVChildTarget( const ConfigData& configData,TVDom* tvDom ) +{ + Elements.resize( tvDom->childs.size() ); + for( unsigned i = 0; i < Elements.size(); ++i ) + Elements[i] = new TVRead( configData,tvDom->childs[i] ); +} + + + + + +TVChildTarget::TVChildTarget( const Reference< XMultiServiceFactory >& xMSF ) +{ + ConfigData configData = init( xMSF ); + + if( ! configData.locale.getLength() || + ! configData.system.getLength() ) + return; + + sal_uInt64 ret,len = 0; + int j = configData.vFileURL.size(); + + TVDom tvDom; + TVDom* pTVDom = &tvDom; + + while( j ) + { + len = configData.vFileLen[--j]; + char* s = new char[ int(len) ]; // the buffer to hold the installed files + osl::File aFile( configData.vFileURL[j] ); + aFile.open( OpenFlag_Read ); + aFile.read( s,len,ret ); + aFile.close(); + + XML_Parser parser = XML_ParserCreate( 0 ); + XML_SetElementHandler( parser, + start_handler, + end_handler ); + XML_SetCharacterDataHandler( parser, + data_handler); + XML_SetUserData( parser,&pTVDom ); // does not return this + + int parsed = XML_Parse( parser,s,int( len ),j==0 ); + (void)parsed; + OSL_ENSURE( parsed, "TVChildTarget::TVChildTarget(): Tree file parsing failed" ); + + XML_ParserFree( parser ); + delete[] s; + } + + // now TVDom holds the relevant information + + Elements.resize( tvDom.childs.size() ); + for( unsigned i = 0; i < Elements.size(); ++i ) + Elements[i] = new TVRead( configData,tvDom.childs[i] ); +} + + +TVChildTarget::~TVChildTarget() +{ +} + + + +Any SAL_CALL +TVChildTarget::getByName( const rtl::OUString& aName ) + throw( NoSuchElementException, + WrappedTargetException, + RuntimeException ) +{ + rtl::OUString num( aName.getStr()+2,aName.getLength()-4 ); + sal_Int32 idx = num.toInt32() - 1; + if( idx < 0 || Elements.size() <= sal_uInt32( idx ) ) + throw NoSuchElementException(); + + Any aAny; + cppu::OWeakObject* p = Elements[idx].get(); + aAny <<= Reference< XInterface >( p ); + return aAny; +} + + + + +Sequence< rtl::OUString > SAL_CALL +TVChildTarget::getElementNames( ) + throw( RuntimeException ) +{ + Sequence< rtl::OUString > seq( Elements.size() ); + for( unsigned i = 0; i < Elements.size(); ++i ) + seq[i] = rtl::OUString::valueOf( sal_Int32( 1+i ) ); + + return seq; +} + + + +sal_Bool SAL_CALL +TVChildTarget::hasByName( const rtl::OUString& aName ) + throw( RuntimeException ) +{ + rtl::OUString num( aName.getStr()+2,aName.getLength()-4 ); + sal_Int32 idx = num.toInt32() - 1; + if( idx < 0 || Elements.size() <= sal_uInt32( idx ) ) + return false; + + return true; +} + + + +// XHierarchicalNameAccess + +Any SAL_CALL +TVChildTarget::getByHierarchicalName( const rtl::OUString& aName ) + throw( NoSuchElementException, + RuntimeException ) +{ + sal_Int32 idx; + rtl::OUString name( aName ); + + if( ( idx = name.indexOf( sal_Unicode( '/' ) ) ) != -1 ) + { + rtl::OUString num( name.getStr()+2,idx-4 ); + sal_Int32 pref = num.toInt32() - 1; + + if( pref < 0 || Elements.size() <= sal_uInt32( pref ) ) + throw NoSuchElementException(); + + return Elements[pref]->getByHierarchicalName( name.copy( 1 + idx ) ); + } + else + return getByName( name ); +} + + + +sal_Bool SAL_CALL +TVChildTarget::hasByHierarchicalName( const rtl::OUString& aName ) + throw( RuntimeException ) +{ + sal_Int32 idx; + rtl::OUString name( aName ); + + if( ( idx = name.indexOf( sal_Unicode( '/' ) ) ) != -1 ) + { + rtl::OUString num( name.getStr()+2,idx-4 ); + sal_Int32 pref = num.toInt32() - 1; + if( pref < 0 || Elements.size() <= sal_uInt32( pref ) ) + return false; + + return Elements[pref]->hasByHierarchicalName( name.copy( 1 + idx ) ); + } + else + return hasByName( name ); +} + + + + + + +ConfigData TVChildTarget::init( const Reference< XMultiServiceFactory >& xSMgr ) +{ + ConfigData configData; + Reference< XMultiServiceFactory > sProvider( getConfiguration(xSMgr) ); + + /**********************************************************************/ + /* reading Office.Common */ + /**********************************************************************/ + + Reference< XHierarchicalNameAccess > xHierAccess( getHierAccess( sProvider, + "org.openoffice.Office.Common" ) ); + rtl::OUString system( getKey( xHierAccess,"Help/System" ) ); + sal_Bool showBasic( getBooleanKey(xHierAccess,"Help/ShowBasic") ); + rtl::OUString instPath( getKey( xHierAccess,"Path/Current/Help" ) ); + if( ! instPath.getLength() ) + // try to determine path from default + instPath = rtl::OUString::createFromAscii( "$(instpath)/help" ); + + // replace anything like $(instpath); + subst( xSMgr,instPath ); + + /**********************************************************************/ + /* reading setup */ + /**********************************************************************/ + + xHierAccess = getHierAccess( sProvider, + "org.openoffice.Setup" ); + + rtl::OUString productName( getKey( xHierAccess,"Product/ooName" ) ); + rtl::OUString setupversion( getKey( xHierAccess,"Product/ooSetupVersion" ) ); + rtl::OUString setupextension; + + try + { + uno::Reference< lang::XMultiServiceFactory > xConfigProvider( + xSMgr ->createInstance(::rtl::OUString::createFromAscii("com.sun.star.configuration.ConfigurationProvider")), uno::UNO_QUERY_THROW); + + uno::Sequence < uno::Any > lParams(1); + beans::PropertyValue aParam ; + aParam.Name = ::rtl::OUString::createFromAscii("nodepath"); + aParam.Value <<= ::rtl::OUString::createFromAscii("/org.openoffice.Setup/Product"); + lParams[0] = uno::makeAny(aParam); + + // open it + uno::Reference< uno::XInterface > xCFG( xConfigProvider->createInstanceWithArguments( + ::rtl::OUString::createFromAscii("com.sun.star.configuration.ConfigurationAccess"), + lParams) ); + + uno::Reference< container::XNameAccess > xDirectAccess(xCFG, uno::UNO_QUERY); + uno::Any aRet = xDirectAccess->getByName(::rtl::OUString::createFromAscii("ooSetupExtension")); + + aRet >>= setupextension; + } + catch ( uno::Exception& ) + { + } + + rtl::OUString productVersion( setupversion + + rtl::OUString::createFromAscii( " " ) + + setupextension ); + rtl::OUString locale( getKey( xHierAccess,"L10N/ooLocale" ) ); + + + // Determine fileurl from url and locale + rtl::OUString url; + osl::FileBase::RC errFile = osl::FileBase::getFileURLFromSystemPath( instPath,url ); + if( errFile != osl::FileBase::E_None ) return configData; + if( url.lastIndexOf( sal_Unicode( '/' ) ) != url.getLength() - 1 ) + url += rtl::OUString::createFromAscii( "/" ); + rtl::OUString ret; + sal_Int32 idx; + osl::DirectoryItem aDirItem; + if( osl::FileBase::E_None == osl::DirectoryItem::get( url + locale,aDirItem ) ) + ret = locale; + else if( ( ( idx = locale.indexOf( '-' ) ) != -1 || + ( idx = locale.indexOf( '_' ) ) != -1 ) && + osl::FileBase::E_None == osl::DirectoryItem::get( url + locale.copy( 0,idx ), + aDirItem ) ) + ret = locale.copy( 0,idx ); + else + { + locale = rtl::OUString::createFromAscii( "en-US" ); + ret = rtl::OUString::createFromAscii("en"); + } + url = url + ret; + + // first of all, try do determine whether there are any *.tree files present + + // Start with extensions to set them at the end of the list + TreeFileIterator aTreeIt( locale ); + rtl::OUString aTreeFile; + sal_Int32 nFileSize; + while( (aTreeFile = aTreeIt.nextTreeFile( nFileSize ) ).getLength() > 0 ) + { + configData.vFileLen.push_back( nFileSize ); + configData.vFileURL.push_back( aTreeFile ); + } + + osl::Directory aDirectory( url ); + osl::FileStatus aFileStatus( FileStatusMask_FileName | FileStatusMask_FileSize | FileStatusMask_FileURL ); + if( osl::Directory::E_None == aDirectory.open() ) + { + int idx_ = 0; + rtl::OUString aFileUrl, aFileName; + while( aDirectory.getNextItem( aDirItem ) == osl::FileBase::E_None && + aDirItem.getFileStatus( aFileStatus ) == osl::FileBase::E_None && + aFileStatus.isValid( FileStatusMask_FileURL ) && + aFileStatus.isValid( FileStatusMask_FileName ) ) + { + aFileUrl = aFileStatus.getFileURL(); + aFileName = aFileStatus.getFileName(); + idx_ = aFileName.lastIndexOf( sal_Unicode( '.' ) ); + if( idx_ == -1 ) + continue; + + const sal_Unicode* str = aFileName.getStr(); + + if( aFileName.getLength() == idx_ + 5 && + ( str[idx_ + 1] == 't' || str[idx_ + 1] == 'T' ) && + ( str[idx_ + 2] == 'r' || str[idx_ + 2] == 'R' ) && + ( str[idx_ + 3] == 'e' || str[idx_ + 3] == 'E' ) && + ( str[idx_ + 4] == 'e' || str[idx_ + 4] == 'E' ) ) + { + OSL_ENSURE( aFileStatus.isValid( FileStatusMask_FileSize ), + "invalid file size" ); + + rtl::OUString baseName = aFileName.copy(0,idx_).toAsciiLowerCase(); + if(! showBasic && baseName.compareToAscii("sbasic") == 0 ) + continue; + + configData.vFileLen.push_back( aFileStatus.getFileSize() ); + configData.vFileURL.push_back( aFileUrl ); + } + } + aDirectory.close(); + } + + configData.m_vAdd[0] = 12; + configData.m_vAdd[1] = 15; + configData.m_vAdd[2] = 11; + configData.m_vAdd[3] = 14; + configData.m_vAdd[4] = 12; + configData.m_vReplacement[0] = productName; + configData.m_vReplacement[1] = productVersion; + // m_vReplacement[2...4] (vendorName/-Version/-Short) are empty strings + + configData.system = system; + configData.locale = locale; + configData.appendix = + rtl::OUString::createFromAscii( "?Language=" ) + + configData.locale + + rtl::OUString::createFromAscii( "&System=" ) + + configData.system + + rtl::OUString::createFromAscii( "&UseDB=no" ) ; + + return configData; +} + + + + + + + + + +Reference< XMultiServiceFactory > +TVChildTarget::getConfiguration(const Reference< XMultiServiceFactory >& m_xSMgr) const +{ + Reference< XMultiServiceFactory > sProvider; + if( m_xSMgr.is() ) + { + try + { + rtl::OUString sProviderService = + rtl::OUString::createFromAscii( "com.sun.star.configuration.ConfigurationProvider" ); + sProvider = + Reference< XMultiServiceFactory >( + m_xSMgr->createInstance( sProviderService ), + UNO_QUERY ); + } + catch( const com::sun::star::uno::Exception& ) + { + OSL_ENSURE( sProvider.is(),"cant instantiate configuration" ); + } + } + + return sProvider; +} + + + +Reference< XHierarchicalNameAccess > +TVChildTarget::getHierAccess( const Reference< XMultiServiceFactory >& sProvider, + const char* file ) const +{ + Reference< XHierarchicalNameAccess > xHierAccess; + + if( sProvider.is() ) + { + Sequence< Any > seq(1); + rtl::OUString sReaderService = + rtl::OUString::createFromAscii( "com.sun.star.configuration.ConfigurationAccess" ); + + seq[0] <<= rtl::OUString::createFromAscii( file ); + + try + { + xHierAccess = + Reference< XHierarchicalNameAccess > + ( sProvider->createInstanceWithArguments( sReaderService,seq ), + UNO_QUERY ); + } + catch( const com::sun::star::uno::Exception& ) + { + } + } + + return xHierAccess; +} + + + +rtl::OUString +TVChildTarget::getKey( const Reference< XHierarchicalNameAccess >& xHierAccess, + const char* key ) const +{ + rtl::OUString instPath; + if( xHierAccess.is() ) + { + Any aAny; + try + { + aAny = + xHierAccess->getByHierarchicalName( rtl::OUString::createFromAscii( key ) ); + } + catch( const com::sun::star::container::NoSuchElementException& ) + { + } + aAny >>= instPath; + } + return instPath; +} + + +sal_Bool +TVChildTarget::getBooleanKey(const Reference< + XHierarchicalNameAccess >& xHierAccess, + const char* key) const +{ + sal_Bool ret = sal_False; + if( xHierAccess.is() ) + { + Any aAny; + try + { + aAny = + xHierAccess->getByHierarchicalName( + rtl::OUString::createFromAscii(key)); + } + catch( const com::sun::star::container::NoSuchElementException& ) + { + } + aAny >>= ret; + } + return ret; +} + + +void TVChildTarget::subst( const Reference< XMultiServiceFactory >& m_xSMgr, + rtl::OUString& instpath ) const +{ + Reference< XConfigManager > xCfgMgr; + if( m_xSMgr.is() ) + { + try + { + xCfgMgr = + Reference< XConfigManager >( + m_xSMgr->createInstance( rtl::OUString::createFromAscii( "com.sun.star.config.SpecialConfigManager" ) ), + UNO_QUERY ); + } + catch( const com::sun::star::uno::Exception& ) + { + OSL_ENSURE( xCfgMgr.is()," cant instantiate the special config manager " ); + } + } + + OSL_ENSURE( xCfgMgr.is(), "specialconfigmanager not found\n" ); + + if( xCfgMgr.is() ) + instpath = xCfgMgr->substituteVariables( instpath ); +} + + +//=================================================================== +// class ExtensionIteratorBase + +static rtl::OUString aSlash( rtl::OUString::createFromAscii( "/" ) ); +static rtl::OUString aHelpFilesBaseName( rtl::OUString::createFromAscii( "help" ) ); +static rtl::OUString aHelpMediaType( rtl::OUString::createFromAscii( "application/vnd.sun.star.help" ) ); + +ExtensionIteratorBase::ExtensionIteratorBase( const rtl::OUString& aLanguage ) + : m_eState( USER_EXTENSIONS ) + , m_aLanguage( aLanguage ) +{ + init(); +} + +void ExtensionIteratorBase::init() +{ + Reference< XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory(); + Reference< XPropertySet > xProps( xFactory, UNO_QUERY ); + OSL_ASSERT( xProps.is() ); + if (xProps.is()) + { + xProps->getPropertyValue( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ) ) >>= m_xContext; + OSL_ASSERT( m_xContext.is() ); + } + if( !m_xContext.is() ) + { + throw RuntimeException( + ::rtl::OUString::createFromAscii( "ExtensionIteratorBase::init(), no XComponentContext" ), + Reference< XInterface >() ); + } + + Reference< XMultiComponentFactory > xSMgr( m_xContext->getServiceManager(), UNO_QUERY ); + m_xSFA = Reference< ucb::XSimpleFileAccess >( + xSMgr->createInstanceWithContext( rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ), + m_xContext ), UNO_QUERY_THROW ); + + m_bUserPackagesLoaded = false; + m_bSharedPackagesLoaded = false; + m_bBundledPackagesLoaded = false; + m_iUserPackage = 0; + m_iSharedPackage = 0; + m_iBundledPackage = 0; +} + +Reference< deployment::XPackage > ExtensionIteratorBase::implGetHelpPackageFromPackage + ( Reference< deployment::XPackage > xPackage, Reference< deployment::XPackage >& o_xParentPackageBundle ) +{ + o_xParentPackageBundle.clear(); + + Reference< deployment::XPackage > xHelpPackage; + if( !xPackage.is() ) + return xHelpPackage; + + // Check if parent package is registered + beans::Optional< beans::Ambiguous<sal_Bool> > option( xPackage->isRegistered + ( Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>() ) ); + bool bRegistered = false; + if( option.IsPresent ) + { + beans::Ambiguous<sal_Bool> const & reg = option.Value; + if( !reg.IsAmbiguous && reg.Value ) + bRegistered = true; + } + if( !bRegistered ) + return xHelpPackage; + + if( xPackage->isBundle() ) + { + Sequence< Reference< deployment::XPackage > > aPkgSeq = xPackage->getBundle + ( Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>() ); + sal_Int32 nPkgCount = aPkgSeq.getLength(); + const Reference< deployment::XPackage >* pSeq = aPkgSeq.getConstArray(); + for( sal_Int32 iPkg = 0 ; iPkg < nPkgCount ; ++iPkg ) + { + const Reference< deployment::XPackage > xSubPkg = pSeq[ iPkg ]; + const Reference< deployment::XPackageTypeInfo > xPackageTypeInfo = xSubPkg->getPackageType(); + rtl::OUString aMediaType = xPackageTypeInfo->getMediaType(); + if( aMediaType.equals( aHelpMediaType ) ) + { + xHelpPackage = xSubPkg; + o_xParentPackageBundle = xPackage; + break; + } + } + } + else + { + const Reference< deployment::XPackageTypeInfo > xPackageTypeInfo = xPackage->getPackageType(); + rtl::OUString aMediaType = xPackageTypeInfo->getMediaType(); + if( aMediaType.equals( aHelpMediaType ) ) + xHelpPackage = xPackage; + } + + return xHelpPackage; +} + +Reference< deployment::XPackage > ExtensionIteratorBase::implGetNextUserHelpPackage + ( Reference< deployment::XPackage >& o_xParentPackageBundle ) +{ + Reference< deployment::XPackage > xHelpPackage; + + if( !m_bUserPackagesLoaded ) + { + Reference< XPackageManager > xUserManager = + thePackageManagerFactory::get( m_xContext )->getPackageManager( rtl::OUString::createFromAscii("user") ); + m_aUserPackagesSeq = xUserManager->getDeployedPackages + ( Reference< task::XAbortChannel >(), Reference< ucb::XCommandEnvironment >() ); + + m_bUserPackagesLoaded = true; + } + + if( m_iUserPackage == m_aUserPackagesSeq.getLength() ) + { + m_eState = SHARED_EXTENSIONS; // Later: SHARED_MODULE + } + else + { + const Reference< deployment::XPackage >* pUserPackages = m_aUserPackagesSeq.getConstArray(); + Reference< deployment::XPackage > xPackage = pUserPackages[ m_iUserPackage++ ]; + VOS_ENSURE( xPackage.is(), "ExtensionIteratorBase::implGetNextUserHelpPackage(): Invalid package" ); + xHelpPackage = implGetHelpPackageFromPackage( xPackage, o_xParentPackageBundle ); + } + + return xHelpPackage; +} + +Reference< deployment::XPackage > ExtensionIteratorBase::implGetNextSharedHelpPackage + ( Reference< deployment::XPackage >& o_xParentPackageBundle ) +{ + Reference< deployment::XPackage > xHelpPackage; + + if( !m_bSharedPackagesLoaded ) + { + Reference< XPackageManager > xSharedManager = + thePackageManagerFactory::get( m_xContext )->getPackageManager( rtl::OUString::createFromAscii("shared") ); + m_aSharedPackagesSeq = xSharedManager->getDeployedPackages + ( Reference< task::XAbortChannel >(), Reference< ucb::XCommandEnvironment >() ); + + m_bSharedPackagesLoaded = true; + } + + if( m_iSharedPackage == m_aSharedPackagesSeq.getLength() ) + { + m_eState = BUNDLED_EXTENSIONS; + } + else + { + const Reference< deployment::XPackage >* pSharedPackages = m_aSharedPackagesSeq.getConstArray(); + Reference< deployment::XPackage > xPackage = pSharedPackages[ m_iSharedPackage++ ]; + VOS_ENSURE( xPackage.is(), "ExtensionIteratorBase::implGetNextSharedHelpPackage(): Invalid package" ); + xHelpPackage = implGetHelpPackageFromPackage( xPackage, o_xParentPackageBundle ); + } + + return xHelpPackage; +} + +Reference< deployment::XPackage > ExtensionIteratorBase::implGetNextBundledHelpPackage + ( Reference< deployment::XPackage >& o_xParentPackageBundle ) +{ + Reference< deployment::XPackage > xHelpPackage; + + if( !m_bBundledPackagesLoaded ) + { + Reference< XPackageManager > xBundledManager = + thePackageManagerFactory::get( m_xContext )->getPackageManager( rtl::OUString::createFromAscii("bundled") ); + m_aBundledPackagesSeq = xBundledManager->getDeployedPackages + ( Reference< task::XAbortChannel >(), Reference< ucb::XCommandEnvironment >() ); + + m_bBundledPackagesLoaded = true; + } + + if( m_iBundledPackage == m_aBundledPackagesSeq.getLength() ) + { + m_eState = END_REACHED; + } + else + { + const Reference< deployment::XPackage >* pBundledPackages = m_aBundledPackagesSeq.getConstArray(); + Reference< deployment::XPackage > xPackage = pBundledPackages[ m_iBundledPackage++ ]; + VOS_ENSURE( xPackage.is(), "ExtensionIteratorBase::implGetNextBundledHelpPackage(): Invalid package" ); + xHelpPackage = implGetHelpPackageFromPackage( xPackage, o_xParentPackageBundle ); + } + + return xHelpPackage; +} + +inline bool isLetter( sal_Unicode c ) +{ + bool bLetter = ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')); + return bLetter; +} + +void ExtensionIteratorBase::implGetLanguageVectorFromPackage( ::std::vector< ::rtl::OUString > &rv, + com::sun::star::uno::Reference< com::sun::star::deployment::XPackage > xPackage ) +{ + rv.clear(); + rtl::OUString aExtensionPath = xPackage->getURL(); + Sequence< rtl::OUString > aEntrySeq = m_xSFA->getFolderContents( aExtensionPath, true ); + + const rtl::OUString* pSeq = aEntrySeq.getConstArray(); + sal_Int32 nCount = aEntrySeq.getLength(); + for( sal_Int32 i = 0 ; i < nCount ; ++i ) + { + rtl::OUString aEntry = pSeq[i]; + if( m_xSFA->isFolder( aEntry ) ) + { + sal_Int32 nLastSlash = aEntry.lastIndexOf( '/' ); + if( nLastSlash != -1 ) + { + rtl::OUString aPureEntry = aEntry.copy( nLastSlash + 1 ); + + // Check language sceme + int nLen = aPureEntry.getLength(); + const sal_Unicode* pc = aPureEntry.getStr(); + bool bStartCanBeLanguage = ( nLen >= 2 && isLetter( pc[0] ) && isLetter( pc[1] ) ); + bool bIsLanguage = bStartCanBeLanguage && + ( nLen == 2 || (nLen == 5 && pc[2] == '-' && isLetter( pc[3] ) && isLetter( pc[4] )) ); + if( bIsLanguage ) + rv.push_back( aPureEntry ); + } + } + } +} + + +//=================================================================== +// class TreeFileIterator + +rtl::OUString TreeFileIterator::nextTreeFile( sal_Int32& rnFileSize ) +{ + rtl::OUString aRetFile; + + while( !aRetFile.getLength() && m_eState != END_REACHED ) + { + switch( m_eState ) + { + case USER_EXTENSIONS: + { + Reference< deployment::XPackage > xParentPackageBundle; + Reference< deployment::XPackage > xHelpPackage = implGetNextUserHelpPackage( xParentPackageBundle ); + if( !xHelpPackage.is() ) + break; + + aRetFile = implGetTreeFileFromPackage( rnFileSize, xHelpPackage ); + break; + } + + case SHARED_EXTENSIONS: + { + Reference< deployment::XPackage > xParentPackageBundle; + Reference< deployment::XPackage > xHelpPackage = implGetNextSharedHelpPackage( xParentPackageBundle ); + if( !xHelpPackage.is() ) + break; + + aRetFile = implGetTreeFileFromPackage( rnFileSize, xHelpPackage ); + break; + } + case BUNDLED_EXTENSIONS: + { + Reference< deployment::XPackage > xParentPackageBundle; + Reference< deployment::XPackage > xHelpPackage = implGetNextBundledHelpPackage( xParentPackageBundle ); + if( !xHelpPackage.is() ) + break; + + aRetFile = implGetTreeFileFromPackage( rnFileSize, xHelpPackage ); + break; + } + + case END_REACHED: + VOS_ENSURE( false, "DataBaseIterator::nextTreeFile(): Invalid case END_REACHED" ); + break; + } + } + + return aRetFile; +} + +rtl::OUString TreeFileIterator::expandURL( const rtl::OUString& aURL ) +{ + static Reference< util::XMacroExpander > xMacroExpander; + static Reference< uri::XUriReferenceFactory > xFac; + + osl::MutexGuard aGuard( m_aMutex ); + + if( !xMacroExpander.is() || !xFac.is() ) + { + Reference< XMultiComponentFactory > xSMgr( m_xContext->getServiceManager(), UNO_QUERY ); + + xFac = Reference< uri::XUriReferenceFactory >( + xSMgr->createInstanceWithContext( rtl::OUString::createFromAscii( + "com.sun.star.uri.UriReferenceFactory"), m_xContext ) , UNO_QUERY ); + if( !xFac.is() ) + { + throw RuntimeException( + ::rtl::OUString::createFromAscii( "Databases::expand(), could not instatiate UriReferenceFactory." ), + Reference< XInterface >() ); + } + + xMacroExpander = Reference< util::XMacroExpander >( + m_xContext->getValueByName( + ::rtl::OUString::createFromAscii( "/singletons/com.sun.star.util.theMacroExpander" ) ), + UNO_QUERY_THROW ); + } + + rtl::OUString aRetURL = aURL; + if( xMacroExpander.is() ) + { + Reference< uri::XUriReference > uriRef; + for (;;) + { + uriRef = Reference< uri::XUriReference >( xFac->parse( aRetURL ), UNO_QUERY ); + if ( uriRef.is() ) + { + Reference < uri::XVndSunStarExpandUrl > sxUri( uriRef, UNO_QUERY ); + if( !sxUri.is() ) + break; + + aRetURL = sxUri->expand( xMacroExpander ); + } + } + } + return aRetURL; +} + +rtl::OUString TreeFileIterator::implGetTreeFileFromPackage + ( sal_Int32& rnFileSize, Reference< deployment::XPackage > xPackage ) +{ + rtl::OUString aRetFile; + rtl::OUString aLanguage = m_aLanguage; + for( sal_Int32 iPass = 0 ; iPass < 2 ; ++iPass ) + { + rtl::OUStringBuffer aStrBuf; + aStrBuf.append( xPackage->getURL() ); + aStrBuf.append( aSlash ); + aStrBuf.append( aLanguage ); + aStrBuf.append( aSlash ); + aStrBuf.append( aHelpFilesBaseName ); + aStrBuf.appendAscii( ".tree" ); + + aRetFile = expandURL( aStrBuf.makeStringAndClear() ); + if( iPass == 0 ) + { + if( m_xSFA->exists( aRetFile ) ) + break; + + ::std::vector< ::rtl::OUString > av; + implGetLanguageVectorFromPackage( av, xPackage ); + ::std::vector< ::rtl::OUString >::const_iterator pFound = av.end(); + try + { + pFound = ::comphelper::Locale::getFallback( av, m_aLanguage ); + } + catch( ::comphelper::Locale::MalFormedLocaleException& ) + {} + if( pFound != av.end() ) + aLanguage = *pFound; + } + } + + rnFileSize = 0; + if( m_xSFA->exists( aRetFile ) ) + rnFileSize = m_xSFA->getSize( aRetFile ); + else + aRetFile = rtl::OUString(); + + return aRetFile; +} + + + |