diff options
author | Jens-Heiner Rechtien <hr@openoffice.org> | 2004-04-13 11:08:32 +0000 |
---|---|---|
committer | Jens-Heiner Rechtien <hr@openoffice.org> | 2004-04-13 11:08:32 +0000 |
commit | 54f14164e743241c690e4b56e67457459fbfc72f (patch) | |
tree | 1c1055e30afa43389f86b678f108546fd8c6ec48 /desktop/source | |
parent | a0550001dd453d873770100c553f4e21580fec0c (diff) |
INTEGRATION: CWS unopkg1 (1.1.2); FILE ADDED
2004/03/26 14:16:06 dbo 1.1.2.10: #115884# minor fixes
Issue number:
Submitted by:
Reviewed by:
2004/03/23 11:11:37 dbo 1.1.2.9: #115884#
Issue number:
Submitted by:
Reviewed by:
2004/03/22 16:20:28 dbo 1.1.2.8: #115884# fixing %%
Issue number:
Submitted by:
Reviewed by:
2004/03/19 16:12:56 dbo 1.1.2.7: #115884# fixes
Issue number:
Submitted by:
Reviewed by:
2004/03/16 10:17:38 dbo 1.1.2.6: #115884# misc bugs
Issue number:
Submitted by:
Reviewed by:
2004/03/12 18:02:47 dbo 1.1.2.5: #115884# misc fixes
Issue number:
Submitted by:
Reviewed by:
2004/03/09 15:46:34 dbo 1.1.2.4: #i20304# snapshot
Issue number:
Submitted by:
Reviewed by:
2004/03/05 20:18:44 dbo 1.1.2.3: #i20303# source save
Issue number:
Submitted by:
Reviewed by:
2004/03/02 09:36:33 dbo 1.1.2.2: #i20304#
Issue number:
Submitted by:
Reviewed by:
2004/02/27 16:00:48 dbo 1.1.2.1: #i20304# new/revised
Issue number:
Submitted by:
Reviewed by:
Diffstat (limited to 'desktop/source')
-rw-r--r-- | desktop/source/deployment/registry/component/dp_component.cxx | 1147 |
1 files changed, 1147 insertions, 0 deletions
diff --git a/desktop/source/deployment/registry/component/dp_component.cxx b/desktop/source/deployment/registry/component/dp_component.cxx new file mode 100644 index 000000000000..0f6dee7fa9bc --- /dev/null +++ b/desktop/source/deployment/registry/component/dp_component.cxx @@ -0,0 +1,1147 @@ +/************************************************************************* + * + * $RCSfile: dp_component.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: hr $ $Date: 2004-04-13 12:08:32 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#include "dp_backend.h" +#include "dp_ucb.h" +#include "dp_platform.h" +#include "dp_persmap.h" +#include "rtl/string.hxx" +#include "rtl/strbuf.hxx" +#include "rtl/ustrbuf.hxx" +#include "rtl/uri.hxx" +#include "osl/file.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "ucbhelper/content.hxx" +#include "comphelper/anytostring.hxx" +#include "xmlscript/xml_helper.hxx" +#include "com/sun/star/lang/WrappedTargetRuntimeException.hpp" +#include "com/sun/star/container/XHierarchicalNameAccess.hpp" +#include "com/sun/star/registry/XSimpleRegistry.hpp" +#include "com/sun/star/registry/XImplementationRegistration.hpp" +#include "com/sun/star/loader/XImplementationLoader.hpp" +#include "com/sun/star/io/XInputStream.hpp" +#include "com/sun/star/sdbc/XResultSet.hpp" +#include "com/sun/star/sdbc/XRow.hpp" +#include "com/sun/star/ucb/NameClash.hpp" +#include "com/sun/star/container/XSet.hpp" +#include <hash_set> +#include <vector> +#include <memory> +#include <algorithm> + + +using namespace ::dp_misc; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ucb; +using ::rtl::OUString; +using ::osl::File; + +namespace dp_registry +{ +namespace backend +{ +namespace component +{ + +typedef ::std::hash_set< + ::rtl::OUString, ::rtl::OUStringHash > t_stringset; + +//============================================================================== +class BackendImpl : public ::dp_registry::backend::PackageRegistryBackend +{ + t_stringset m_jar_typelibs; + t_stringset m_rdb_typelibs; + bool m_unorc_inited; + bool m_unorc_modified; + + OUString m_inflated_dir, m_inflated_reg_dir; + ::std::auto_ptr< PersistentMap > m_urlToTemp; + +protected: + // PackageRegistryBackend + virtual Reference< deployment::XPackage > createPackage( + OUString const & url, + OUString const & mediaType, OUString const & subType, + INetContentTypeParameterList const & params, + Reference< XCommandEnvironment > const & xCmdEnv ); + + virtual void SAL_CALL disposing(); + +public: + Reference< registry::XImplementationRegistration > m_xImplReg; + Reference< registry::XSimpleRegistry > m_xServicesRDB; + + t_stringset & getTypelibs( bool jar ) + { return jar ? m_jar_typelibs : m_rdb_typelibs; } + void unorc_verify_init( Reference< XCommandEnvironment > const & xCmdEnv ); + void unorc_flush( Reference< XCommandEnvironment > const & xCmdEnv ); + + OUString getInflatedCopy( + OUString const & url, + Reference< XCommandEnvironment > const & xCmdEnv ); + void removeInflatedCopy( + OUString const & url, + Reference< XCommandEnvironment > const & xCmdEnv ); + + bool addToUnoRc( + bool jarFile, OUString const & url, + Reference< XCommandEnvironment > const & xCmdEnv ); + bool removeFromUnoRc( + bool jarFile, OUString const & url, + Reference< XCommandEnvironment > const & xCmdEnv ); + + Sequence< Reference< lang::XServiceInfo > > loadFactories( + OUString const & url, OUString const & loader ); + + inline BackendImpl( + Reference< XComponentContext > const & xComponentContext, + OUString const & implName, + Sequence< OUString > const & supported_media_types ) + : PackageRegistryBackend( + xComponentContext, implName, supported_media_types ), + m_unorc_inited( false ), + m_unorc_modified( false ), + m_xImplReg( + xComponentContext->getServiceManager() + ->createInstanceWithContext( + OUSTR("com.sun.star.registry.ImplementationRegistration"), + xComponentContext ), UNO_QUERY_THROW ) + {} + + // XInitialization + virtual void SAL_CALL initialize( Sequence< Any > const & args ) + throw (RuntimeException); + + // XPackageRegistry + virtual OUString SAL_CALL detectMediaType( OUString const & url ) + throw (RuntimeException); +}; + +//============================================================================== +class ComponentPackageImpl : public ::dp_registry::backend::Package +{ + OUString m_inflated_url; + OUString m_loader; + t_Registered m_registered; + + inline BackendImpl * getMyBackend() const + { return static_cast< BackendImpl * >(m_myBackend.get()); } + + // Package + virtual t_Registered getRegStatus( + ::osl::ResettableMutexGuard & guard, + Reference< XCommandEnvironment > const & xCmdEnv ); + virtual bool processPackage( + bool register_package, + ::osl::ResettableMutexGuard & guard, + Reference< XCommandEnvironment > const & xCmdEnv ); + +public: + inline ComponentPackageImpl( + ::rtl::Reference< PackageRegistryBackend > const & myBackend, + OUString const & url, OUString const & mediaType, + OUString const & name, OUString const & description, + OUString const & loader ) + : Package( myBackend, url, mediaType, name, name /* display-name */, + description ), + m_loader( loader ), + m_registered( REG_VOID ) + {} +}; + +//============================================================================== +class TypelibraryPackageImpl : public ::dp_registry::backend::Package +{ + OUString m_inflated_unorc_url; + bool m_jarFile; + t_Registered m_registered; + Reference< container::XHierarchicalNameAccess > m_xTDprov; + + inline BackendImpl * getMyBackend() const + { return static_cast< BackendImpl * >(m_myBackend.get()); } + + // Package + virtual t_Registered getRegStatus( + ::osl::ResettableMutexGuard & guard, + Reference< XCommandEnvironment > const & xCmdEnv ); + virtual bool processPackage( + bool register_package, + ::osl::ResettableMutexGuard & guard, + Reference< XCommandEnvironment > const & xCmdEnv ); + +public: + inline TypelibraryPackageImpl( + ::rtl::Reference< PackageRegistryBackend > const & myBackend, + OUString const & url, OUString const & mediaType, + OUString const & name, OUString const & description, bool jarFile ) + : Package( myBackend, url, mediaType, name, name /* display-name */, + description ), + m_jarFile( jarFile ), + m_registered( REG_VOID ) + {} +}; + +//______________________________________________________________________________ +void BackendImpl::disposing() +{ + try + { + m_xServicesRDB->close(); + m_xServicesRDB.clear(); + m_urlToTemp.reset(0); + unorc_flush( Reference< XCommandEnvironment >() ); + + PackageRegistryBackend::disposing(); + } + catch (RuntimeException &) + { + throw; + } + catch (Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw lang::WrappedTargetRuntimeException( + OUSTR("caught unexpected exception while disposing..."), + static_cast< OWeakObject * >(this), exc ); + } +} + +struct predicate_equalsIgnoreAsciiCase +{ + OUString m_str; + predicate_equalsIgnoreAsciiCase( OUString const & str ) : m_str( str ) {} + bool operator () ( t_string2string_map::value_type const & v ) const + { return v.second.equalsIgnoreAsciiCase( m_str ); } +}; + +//______________________________________________________________________________ +void BackendImpl::initialize( Sequence< Any > const & args ) + throw (RuntimeException) +{ + PackageRegistryBackend::initialize( args ); + + // services.rdb: + m_xServicesRDB.set( + getComponentContext()->getServiceManager() + ->createInstanceWithContext( + OUSTR("com.sun.star.registry.SimpleRegistry"), + getComponentContext() ), UNO_QUERY_THROW ); + + if (transientMode()) + { + // in-mem rdb: + m_xServicesRDB->open( OUString() /* in-mem */, + false /* ! read-only */, true /* create */ ); + // inflated in-mem DB: + m_urlToTemp.reset( new PersistentMap ); + } + else + { + m_xServicesRDB->open( + // xxx todo: switch to alternating rdbs: + expand_reg_url( make_url( getCachePath(), OUSTR("services.rdb") ), + getComponentContext() ), + false /* ! read-only */, true /* create */ ); + + // ensure "inflated" folder: + m_inflated_reg_dir = make_url( getCachePath(), OUSTR("inflated") ); + ::ucb::Content inflated_dir_content; + create_folder( &inflated_dir_content, m_inflated_reg_dir ); + m_inflated_dir = expand_reg_url( + m_inflated_reg_dir, getComponentContext() ); + + // scan for zombie temp dirs: + OUString inflated_db_url( + make_url( getCachePath(), OUSTR("inflated.db") ) ); + m_urlToTemp.reset( new PersistentMap( inflated_db_url, + getComponentContext() ) ); + t_string2string_map urlToTemp( m_urlToTemp->getEntries() ); + + OUString str_Title = OUSTR("Title"); + Reference< sdbc::XResultSet > xResultSet( + inflated_dir_content.createCursor( + Sequence< OUString >( &str_Title, 1 ), + ::ucb::INCLUDE_DOCUMENTS_ONLY ) ); + // get all inflated temp directories: + ::std::vector< OUString > tempEntries; + while (xResultSet->next()) + { + OUString title( Reference< sdbc::XRow >( + xResultSet, UNO_QUERY_THROW )->getString( + 1 /* Title */ ) ); + tempEntries.push_back( ::rtl::Uri::encode( + title, rtl_UriCharClassPchar, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ) ); + } + + for ( ::std::size_t pos = 0; pos < tempEntries.size(); ++pos ) + { + OUString const & tempEntry = tempEntries[ pos ]; + if (::std::find_if( urlToTemp.begin(), urlToTemp.end(), + predicate_equalsIgnoreAsciiCase( tempEntry ) ) + == urlToTemp.end()) + { + // temp entry not needed anymore: + OUString url( make_url( m_inflated_reg_dir, tempEntry ) ); + erase_path( url ); + erase_path( url + OUSTR(".inflated") ); + } + OSL_ASSERT( ! m_urlToTemp->has( tempEntry ) ); + } + } +} + +//============================================================================== +OUString SAL_CALL getImplementationName() +{ + return OUSTR( + "com.sun.star.comp.deployment.component.PackageRegistryBackend"); +} + +//============================================================================== +Reference< XInterface > SAL_CALL create( + Reference< XComponentContext > const & xComponentContext ) + SAL_THROW( (Exception) ) +{ + OUString const media_types [] = { + OUSTR("application/vnd.sun.star.uno-component"), + OUSTR("application/vnd.sun.star.uno-typelibrary") + }; + return static_cast< ::cppu::OWeakObject * >( + new BackendImpl( + xComponentContext, getImplementationName(), + Sequence< OUString >( media_types, ARLEN(media_types) ) ) ); +} + +// XPackageRegistry +//______________________________________________________________________________ +OUString BackendImpl::detectMediaType( OUString const & url ) + throw (RuntimeException) +{ + ::ucb::Content ucb_content; + if (::ucb::Content::create( url, Reference< XCommandEnvironment >(), + ucb_content )) + { + OUString title( extract_throw< OUString >( + ucb_content.getPropertyValue( OUSTR("Title") ) ) ); + if (title.endsWithIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM(SAL_DLLEXTENSION) )) + return OUSTR("application/vnd.sun.star.uno-component;type=native;" + "platform=" THIS_OS "_" THIS_CPU); + if (title.endsWithIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM(".jar") )) + { + // xxx todo: ait for MAV fix: +// // read .jar manifest file: +// ::rtl::OUStringBuffer buf; +// buf.appendAscii( +// RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.pkg://") ); +// buf.append( ::rtl::Uri::encode( url, +// rtl_UriCharClassRegName, +// rtl_UriEncodeIgnoreEscapes, +// RTL_TEXTENCODING_UTF8 ) ); +// buf.appendAscii( +// RTL_CONSTASCII_STRINGPARAM("/META-INF/MANIFEST.MF") ); +// ::ucb::Content manifest_content; +// if (create_ucb_content( &manifest_content, buf.makeStringAndClear(), +// Reference< XCommandEnvironment >(), +// false /* no throw */ )) +// { +// OUString line; +// if (readLine( &line, OUSTR("RegistrationClassName"), +// manifest_content, RTL_TEXTENCODING_ASCII_US )) + return OUSTR( + "application/vnd.sun.star.uno-component;type=Java"); +// } +// return OUSTR("application/vnd.sun.star.uno-typelibrary;type=Java"); + } + if (title.endsWithIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM(".py") )) + return OUSTR("application/vnd.sun.star.uno-component;type=Python"); + if (title.endsWithIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM(".rdb") )) + return OUSTR("application/vnd.sun.star.uno-typelibrary;type=RDB"); + } + return OUString(); +} + +// PackageRegistryBackend +//______________________________________________________________________________ +Reference< deployment::XPackage > BackendImpl::createPackage( + OUString const & url, + OUString const & mediaType, OUString const & subType, + INetContentTypeParameterList const & params, + Reference< XCommandEnvironment > const & xCmdEnv ) +{ + ::ucb::Content ucb_content( url, xCmdEnv ); + OUString name( extract_throw< OUString >( + ucb_content.getPropertyValue( OUSTR("Title") ) ) ); + + // xxx todo: probe and evaluate component xml description + + if (subType.matchIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.uno-component") )) + { + INetContentTypeParameter const * param = params.find( "type" ); + if (param != 0) + { + OUString value(param->m_sValue); + if (value.equalsIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM("native") )) + { + return new ComponentPackageImpl( + this, url, mediaType, name, + OUSTR("UNO Shared Library Component"), + OUSTR("com.sun.star.loader.SharedLibrary") ); + } + if (value.equalsIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM("Java") )) + { + return new ComponentPackageImpl( + this, url, mediaType, name, + OUSTR("UNO Java Component"), + OUSTR("com.sun.star.loader.Java2") ); + } + if (value.equalsIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM("Python") )) + { + return new ComponentPackageImpl( + this, url, mediaType, name, + OUSTR("UNO Python Component"), + OUSTR("com.sun.star.loader.Python") ); + } + else // fallback: guess loader xxx todo discuss + { + OUString loader( OUSTR("com.sun.star.loader.") + value ); + // check if loader service available: + if (getComponentContext()->getServiceManager() + ->createInstanceWithContext( + loader, getComponentContext() ).is()) + { + ::rtl::OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("UNO ") ); + buf.append( value ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" Component") ); + return new ComponentPackageImpl( + this, url, mediaType, name, + buf.makeStringAndClear(), loader ); + } + } + throw lang::IllegalArgumentException( + OUSTR("no support for UNO Components of type: ") + value, + static_cast< OWeakObject * >(this), + static_cast< sal_Int16 >(-1 /* not known */) ); + } + } + else if (subType.matchIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.uno-typelibrary") )) + { + INetContentTypeParameter const * param = params.find( "type" ); + if (param != 0) + { + OUString value(param->m_sValue); + if (value.equalsIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM("RDB") )) + { + return new TypelibraryPackageImpl( + this, url, mediaType, name, + OUSTR("Native Type-Library File"), false /* rdb */ ); + } + if (value.equalsIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM("Java") )) + { + return new TypelibraryPackageImpl( + this, url, mediaType, name, + OUSTR("Java Type-Library File"), true /* jar */ ); + } + throw lang::IllegalArgumentException( + OUSTR("no support for type-libraries of type: ") + value, + static_cast< OWeakObject * >(this), + static_cast< sal_Int16 >(-1 /* not known */) ); + } + } + throw lang::IllegalArgumentException( + OUSTR("invalid media-type given: ") + mediaType, + static_cast< OWeakObject * >(this), + static_cast< sal_Int16 >(-1 /* not known */) ); +} + +//############################################################################## + +//______________________________________________________________________________ +void BackendImpl::unorc_verify_init( + Reference< XCommandEnvironment > const & xCmdEnv ) +{ + if (transientMode()) + return; + ::osl::MutexGuard guard( getMutex() ); + if (! m_unorc_inited) + { + ::ucb::Content ucb_content; + if (create_ucb_content( + &ucb_content, + make_url( getCachePath(), OUSTR(SAL_CONFIGFILE("uno")) ), + xCmdEnv, false /* no throw */ )) + { + OUString line; + if (readLine( &line, OUSTR("UNO_JAVA_CLASSPATH="), ucb_content, + RTL_TEXTENCODING_UTF8 )) + { + sal_Int32 index = sizeof ("UNO_JAVA_CLASSPATH=") - 1; + do + { + OUString token( line.getToken( 0, ' ', index ).trim() ); + if (token.getLength() > 0) + m_jar_typelibs.insert( token ); + } + while (index >= 0); + } + if (readLine( &line, OUSTR("UNO_TYPES="), ucb_content, + RTL_TEXTENCODING_UTF8 )) + { + sal_Int32 index = sizeof ("UNO_TYPES=") - 1; + do + { + OUString token( line.getToken( 0, ' ', index ).trim() ); + if (token.getLength() > 0) + m_rdb_typelibs.insert( token ); + } + while (index >= 0); + } + m_unorc_modified = false; + m_unorc_inited = true; + } + else + { + // file has never been written before: write now + m_unorc_modified = true; + m_unorc_inited = true; + unorc_flush( xCmdEnv ); + } + } +} + +//______________________________________________________________________________ +void BackendImpl::unorc_flush( + Reference< XCommandEnvironment > const & xCmdEnv ) +{ + if (transientMode()) + return; + if (!m_unorc_inited || !m_unorc_modified) + return; + + ::rtl::OStringBuffer buf; + if (! m_jar_typelibs.empty()) + { + t_stringset::const_iterator iPos( m_jar_typelibs.begin() ); + t_stringset::const_iterator const iEnd( m_jar_typelibs.end() ); + buf.append( RTL_CONSTASCII_STRINGPARAM("UNO_JAVA_CLASSPATH=") ); + while (iPos != iEnd) + { + // encoded ASCII file-urls: + ::rtl::OString item( + ::rtl::OUStringToOString( *iPos, RTL_TEXTENCODING_ASCII_US ) ); + buf.append( item ); + ++iPos; + if (iPos != iEnd) + buf.append( ' ' ); + } + buf.append( '\n' ); + } + if (! m_jar_typelibs.empty()) + { + t_stringset::const_iterator iPos( m_rdb_typelibs.begin() ); + t_stringset::const_iterator const iEnd( m_rdb_typelibs.end() ); + buf.append( RTL_CONSTASCII_STRINGPARAM("UNO_TYPES=") ); + while (iPos != iEnd) + { + // encoded ASCII file-urls: + ::rtl::OString item( + ::rtl::OUStringToOString( *iPos, RTL_TEXTENCODING_ASCII_US ) ); + buf.append( item ); + ++iPos; + if (iPos != iEnd) + buf.append( ' ' ); + } + buf.append( '\n' ); + } + buf.append( + RTL_CONSTASCII_STRINGPARAM("UNO_SERVICES=$ORIGIN/services.rdb\n") ); + + Reference< io::XInputStream > xData( + ::xmlscript::createInputStream( + ::rtl::ByteSequence( + reinterpret_cast< sal_Int8 const * >(buf.getStr()), + buf.getLength() ) ) ); + ::ucb::Content ucb_content( + make_url( getCachePath(), OUSTR(SAL_CONFIGFILE("uno")) ), xCmdEnv ); + ucb_content.writeStream( xData, true /* replace existing */ ); + m_unorc_modified = false; +} + +//------------------------------------------------------------------------------ +static inline OUString encodeForRcFile( OUString const & str ) +{ + // escape $\{} (=> rtl bootstrap files) + ::rtl::OUStringBuffer buf; + sal_Int32 pos = 0; + sal_Int32 len = str.getLength(); + for ( ; pos < len; ++pos ) + { + sal_Unicode c = str[ pos ]; + switch (c) + { + case '$': + case '\\': + case '{': + case '}': + buf.append( static_cast< sal_Unicode >('\\') ); + break; + } + buf.append( c ); + } + return buf.makeStringAndClear(); +} + +//______________________________________________________________________________ +bool BackendImpl::addToUnoRc( + bool jarFile, OUString const & rcurl, + Reference< XCommandEnvironment > const & xCmdEnv ) +{ + ::osl::MutexGuard guard( getMutex() ); + unorc_verify_init( xCmdEnv ); + ::std::pair< t_stringset::iterator, bool > insertion( + getTypelibs(jarFile).insert( rcurl ) ); + m_unorc_modified |= insertion.second; + // write immediately: + unorc_flush( xCmdEnv ); + return insertion.second; +} + +//______________________________________________________________________________ +bool BackendImpl::removeFromUnoRc( + bool jarFile, OUString const & rcurl, + Reference< XCommandEnvironment > const & xCmdEnv ) +{ + ::osl::MutexGuard guard( getMutex() ); + unorc_verify_init( xCmdEnv ); + ::std::size_t erased = getTypelibs(jarFile).erase( rcurl ); + bool ret = (erased > 0); + m_unorc_modified |= ret; + OSL_ASSERT( ret ); + // write immediately: + unorc_flush( xCmdEnv ); + return ret; +} + +//------------------------------------------------------------------------------ +void copyDeep( OUString const & source_url, OUString const & dest_url, + Reference< XCommandEnvironment > const & xCmdEnv ) +{ + // prepare destination folder: + ::ucb::Content ucb_dest_folder; + create_folder( &ucb_dest_folder, + dest_url.copy( 0, dest_url.lastIndexOf( '/' ) ) ); + + ::rtl::OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("inflating ") ); + buf.append( source_url ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" to ") ); + buf.append( dest_url ); + ProgressLevel progress( xCmdEnv ); + progress.update( buf.makeStringAndClear() ); + + ::ucb::Content source_content( source_url, xCmdEnv ); + if (! ucb_dest_folder.transferContent( + source_content, ::ucb::InsertOperation_COPY, + OUString(), NameClash::OVERWRITE )) + throw RuntimeException( + OUSTR("::ucb::Content::transferContent() failed!"), 0 ); + + // copy dependent files: + if (// xxx todo: wait for MAV fix in package + dest_url.endsWithIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM(".jar") )) + { + // .jar manifest Class-Path dependencies: + ::rtl::OUStringBuffer buf; + buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.pkg://") ); + buf.append( ::rtl::Uri::encode( /* xxx todo */dest_url, + rtl_UriCharClassRegName, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ) ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("/META-INF/MANIFEST.MF") ); + ::ucb::Content manifest_content; + if (create_ucb_content( + &manifest_content, + buf.makeStringAndClear(), xCmdEnv, false /* no throw */ )) + { + OUString line; + if (readLine( &line, OUSTR("Class-Path"), + manifest_content, RTL_TEXTENCODING_ASCII_US )) + { + sal_Int32 index = line.indexOf( ':' ); + if (index >= 0) + { + OUString dest_dir( + dest_url.copy( 0, dest_url.lastIndexOf( '/' ) ) ); + ++index; + do + { + OUString rel_path( + line.getToken( 0, ' ', index ).trim() ); + if (rel_path.getLength() > 0) + { + OUString source( + make_url( + source_url.copy( + 0, source_url.lastIndexOf( '/' ) ), + rel_path ) ); + copyDeep( source, make_url( dest_dir, rel_path ), + xCmdEnv ); + } + } + while (index >= 0); + } + } + } + } +// else if (source_url.endsWithIgnoreAsciiCaseAsciiL( +// RTL_CONSTASCII_STRINGPARAM(SAL_DLLEXTENSION) )) +// { +// // xxx todo? +// // check .RPATH dependencies for .so files: +// } +} + +//______________________________________________________________________________ +OUString BackendImpl::getInflatedCopy( + OUString const & url, Reference< XCommandEnvironment > const & xCmdEnv ) +{ + ::osl::MutexGuard guard( getMutex() ); + OUString package( url.copy( url.lastIndexOf( '/' ) + 1 ) ); + OUString tempEntry; + if (m_urlToTemp->get( &tempEntry, url )) + { + OUString dir( make_url( m_inflated_reg_dir, tempEntry ) ); + dir += OUSTR(".inflated"); + return make_url( dir, package ); + } + + OUString dir; + // create new temp dir: + File::RC rc; + if (transientMode()) + { + rc = File::createTempFile( 0, 0, &dir ); + tempEntry = dir.copy( dir.lastIndexOf( '/' ) + 1 ); + } + else + { + rc = File::createTempFile( &m_inflated_dir, 0, &dir ); + OSL_ASSERT( dir.matchIgnoreAsciiCase( m_inflated_dir ) ); + tempEntry = dir.copy( dir.lastIndexOf( '/' ) + 1 ); + dir = make_url( m_inflated_reg_dir, tempEntry ); + } + if (rc != File::E_None) + throw RuntimeException( + OUSTR("::osl::File::createTempFile() failed!"), 0 ); + dir += OUSTR(".inflated"); + + OUString dest_url( make_url( dir, package ) ); + copyDeep( url, dest_url, xCmdEnv ); + + // add new entry to DB: + m_urlToTemp->put( url, tempEntry ); + return dest_url; +} + +//______________________________________________________________________________ +void BackendImpl::removeInflatedCopy( + OUString const & url, Reference< XCommandEnvironment > const & xCmdEnv ) +{ + ::osl::MutexGuard guard( getMutex() ); + bool erased = m_urlToTemp->erase( url ); + OSL_ENSURE( erased, "entry not in inflated DB!?" ); +} + +//______________________________________________________________________________ +Sequence< Reference< lang::XServiceInfo > > BackendImpl::loadFactories( + OUString const & url, OUString const & loader ) +{ + // HACK: highly dependent on stoc/source/servicemanager + // and stoc/source/implreg implementation which rely on the same + // services.rdb format! + Reference< XComponentContext > const & xContext = getComponentContext(); + Reference< registry::XSimpleRegistry > xMemReg( + xContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.registry.SimpleRegistry"), xContext ), + UNO_QUERY_THROW ); + xMemReg->open( OUString() /* in mem */, false, true ); + + Reference< loader::XImplementationLoader > xLoader( + xContext->getServiceManager()->createInstanceWithContext( + loader, xContext ), UNO_QUERY_THROW ); + try + { + xLoader->writeRegistryInfo( xMemReg->getRootKey(), OUString(), url ); + } + // ignore if factory cannot be registered: + catch (registry::CannotRegisterImplementationException &) + { + } + + Sequence< Reference< registry::XRegistryKey > > keys( + xMemReg->getRootKey()->openKeys() ); + ::std::vector< Reference< lang::XServiceInfo > > ret; + ret.reserve( keys.getLength() ); + Reference< registry::XRegistryKey > const * pkeys = keys.getConstArray(); + for ( sal_Int32 pos = 0; pos < keys.getLength(); ++pos ) + { + try + { + ret.push_back( + Reference< lang::XServiceInfo >( + xLoader->activate( pkeys[ pos ]->getKeyName().copy( + 1 /* loading slash */ ), + OUString(), + url, + pkeys[ pos ] ), UNO_QUERY_THROW ) ); + } + // ignore if factory cannot be activated: + catch (loader::CannotActivateFactoryException &) + { + } + } + return Sequence< Reference< lang::XServiceInfo > >( &ret[ 0 ], ret.size() ); +} + +// Package +//______________________________________________________________________________ +ComponentPackageImpl::t_Registered ComponentPackageImpl::getRegStatus( + ::osl::ResettableMutexGuard & guard, + Reference< XCommandEnvironment > const & xCmdEnv ) +{ + BackendImpl * that = getMyBackend(); + if (m_registered == REG_VOID) + { + m_registered = REG_NOT_REGISTERED; + // lookup rdb for location URL: + if (m_inflated_url.getLength() == 0) // get an inflated URL: + m_inflated_url = that->getInflatedCopy( m_url, xCmdEnv ); + + Reference< registry::XRegistryKey > xRootKey( + that->m_xServicesRDB->getRootKey() ); + Reference< registry::XRegistryKey > xImplKey( + xRootKey->openKey( OUSTR("IMPLEMENTATIONS") ) ); + Sequence< OUString > implNames; + if (xImplKey.is()) + implNames = xImplKey->getKeyNames(); + OUString const * pImplNames = implNames.getConstArray(); + for ( sal_Int32 pos = implNames.getLength(); pos--; ) + { + OUString key( pImplNames[ pos ] + OUSTR("/UNO/LOCATION") ); + Reference< registry::XRegistryKey > xKey( xRootKey->openKey(key) ); + if (xKey.is() && xKey->isValid()) + { + OUString location( xKey->getAsciiValue() ); + if (location.equalsIgnoreAsciiCase( m_inflated_url )) + { + m_registered = REG_REGISTERED; + break; + } + } + } + } + return m_registered; +} + +//______________________________________________________________________________ +bool ComponentPackageImpl::processPackage( + bool register_package, + ::osl::ResettableMutexGuard & guard, + Reference< XCommandEnvironment > const & xCmdEnv ) +{ + BackendImpl * that = getMyBackend(); + that->ensure_no_running_office(); + + if (m_inflated_url.getLength() == 0) // get an inflated URL: + m_inflated_url = that->getInflatedCopy( m_url, xCmdEnv ); + bool java = m_loader.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("com.sun.star.loader.Java2") ); + + bool success = true; + ProgressLevel progress( xCmdEnv ); + that->unorc_verify_init( xCmdEnv ); // ensure written unorc file + if (register_package) + { + // XXX todo: singletons live deployment + + // rdb part: + progress.update( + OUSTR("registering UNO component ") + m_inflated_url ); + OSL_ASSERT( that->m_xServicesRDB.is() ); + try + { + that->m_xImplReg->registerImplementation( + m_loader, m_inflated_url /* loaders will expand */, + that->m_xServicesRDB ); + } + catch (registry::CannotRegisterImplementationException &) + { + success = false; + // xxx todo: wait for MAV fix + if (java) // workaround typelibs + success &= that->addToUnoRc( + java, encodeForRcFile(m_inflated_url), xCmdEnv ); + else + throw; + } + m_registered = REG_VOID; + +// // live insertion: +// Sequence< Reference< lang::XServiceInfo > > factories( +// that->loadFactories( m_inflated_url, m_loader ) ); +// Reference< container::XSet > xSet( +// that->getComponentContext()->getServiceManager(), UNO_QUERY_THROW ); +// Reference< lang::XServiceInfo > const * pfactories = +// factories.getConstArray(); +// for ( sal_Int32 pos = 0; pos < factories.getLength(); ++pos ) +// { +// try +// { +// xSet->insert( makeAny(pfactories[ pos ]) ); +// } +// // ignore if factory has already benn inserted: +// catch (container::ElementExistException &) +// { +// OSL_ENSURE( 0, "### factory already registered?" ); +// } +// } + + if (java && success) // xxx todo: add to CLASSPATH until we have an + // own extendable classloader, the sandbox + // classloader is insufficient, because the bridge + // and class com.sun.star.uno.Type load classes + // using a different classloader, e.g. the + // system classloader. + success &= that->addToUnoRc( + java, encodeForRcFile(m_inflated_url), xCmdEnv ); + + if (success) + m_registered = REG_REGISTERED; + } + else // revokePackage() + { + m_registered = REG_VOID; + // rdb part: + that->m_xImplReg->revokeImplementation( + m_inflated_url /* loaders will expand */, that->m_xServicesRDB ); + +// // live removal: +// Sequence< Reference< lang::XServiceInfo > > factories( +// that->loadFactories( m_inflated_url, m_loader ) ); +// Reference< container::XSet > xSet( +// that->getComponentContext()->getServiceManager(), UNO_QUERY_THROW ); +// Reference< lang::XServiceInfo > const * pfactories = +// factories.getConstArray(); +// for ( sal_Int32 pos = 0; pos < factories.getLength(); ++pos ) +// { +// try +// { +// xSet->remove( +// makeAny( pfactories[ pos ]->getImplementationName() ) ); +// } +// // ignore if factory is not in: +// catch (container::NoSuchElementException &) +// { +// OSL_ENSURE( 0, "### registered factory not in?" ); +// } +// } + + if (java) // xxx todo: add to CLASSPATH until we have an + // own extendable classloader, the sandbox + // classloader is insufficient, because the bridge + // and class com.sun.star.uno.Type load classes + // using a different classloader, e.g. the + // system classloader. + success &= that->removeFromUnoRc( + java, encodeForRcFile(m_inflated_url), xCmdEnv ); + + that->removeInflatedCopy( m_url, xCmdEnv ); + + if (success) + m_registered = REG_NOT_REGISTERED; + } + + return success; +} + +//############################################################################## + +// Package +//______________________________________________________________________________ +TypelibraryPackageImpl::t_Registered TypelibraryPackageImpl::getRegStatus( + ::osl::ResettableMutexGuard & guard, + Reference< XCommandEnvironment > const & xCmdEnv ) +{ + BackendImpl * that = getMyBackend(); + if (m_inflated_unorc_url.getLength() == 0) // get an inflated URL: + m_inflated_unorc_url = encodeForRcFile( + that->getInflatedCopy( m_url, xCmdEnv ) ); + + t_stringset const & rSet = that->getTypelibs(m_jarFile); + return rSet.find(m_inflated_unorc_url) == rSet.end() + ? REG_NOT_REGISTERED : REG_REGISTERED; +} + +//______________________________________________________________________________ +bool TypelibraryPackageImpl::processPackage( + bool register_package, + ::osl::ResettableMutexGuard & guard, + Reference< XCommandEnvironment > const & xCmdEnv ) +{ + BackendImpl * that = getMyBackend(); + that->ensure_no_running_office(); + + if (m_inflated_unorc_url.getLength() == 0) // get an inflated URL: + m_inflated_unorc_url = encodeForRcFile( + that->getInflatedCopy( m_url, xCmdEnv ) ); + + bool success = true; + m_registered = REG_VOID; + if (register_package) + { + // xxx todo: check jar, rdb compatibility to existing types + + if (that->addToUnoRc( m_jarFile, m_inflated_unorc_url, xCmdEnv )) + { +// // live insertion: +// if (m_jarFile) +// { +// // xxx todo add to classpath at runtime: +// that->ensure_persistentMode(); +// } +// else // RDB: +// { +// Reference< XComponentContext > const & xContext = +// that->getComponentContext(); +// if (! m_xTDprov.is()) +// { +// m_xTDprov.set( +// xContext->getServiceManager() +// ->createInstanceWithArgumentsAndContext( +// OUSTR("com.sun.star.comp.stoc." +// "RegistryTypeDescriptionProvider"), +// Sequence< Any >( &arg, 1 ), xContext ), UNO_QUERY ); +// OSL_ASSERT( m_xTDprov.is() ); +// } +// if (m_xTDprov.is()) +// { +// Reference< container::XSet > xSet( +// xContext->getValueByName( +// OUSTR("/singletons/com.sun.star." +// "reflection.theTypeDescriptionManager") ), +// UNO_QUERY_THROW ); +// xSet->insert( makeAny(m_xTDprov) ); +// } +// } + } + m_registered = REG_REGISTERED; + } + else // revokePackage() + { + if (that->removeFromUnoRc( m_jarFile, m_inflated_unorc_url, xCmdEnv )) + { +// // revoke live: +// if (m_jarFile) +// { +// // xxx todo add to classpath at runtime: +// that->ensure_persistentMode(); +// } +// else +// { +// if (m_xTDprov.is()) +// { +// Reference< container::XSet > xSet( +// xContext->getValueByName( +// OUSTR("/singletons/com.sun.star." +// "reflection.theTypeDescriptionManager") ), +// UNO_QUERY_THROW ); +// xSet->remove( makeAny(m_xTDprov) ); +// } +// } + } + else + success = false; + m_registered = REG_NOT_REGISTERED; + that->removeInflatedCopy( m_url, xCmdEnv ); + } + return success; +} + +} // namespace component +} // namespace backend +} // namespace dp_registry + |