/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "lru_cache.h" #include "permissions.h" #include "bootstrapservices.hxx" #define SERVICE_NAME "com.sun.star.security.AccessController" #define IMPL_NAME "com.sun.star.security.comp.stoc.AccessController" #define USER_CREDS "access-control.user-credentials" using namespace ::std; using namespace ::osl; using namespace ::cppu; using namespace ::com::sun::star; using namespace ::com::sun::star::uno; namespace stoc_sec { // static stuff initialized when loading lib static OUString s_envType = CPPU_CURRENT_LANGUAGE_BINDING_NAME; const char s_acRestriction[] = "access-control.restriction"; //################################################################################################## /** ac context intersects permissions of two ac contexts */ class acc_Intersection : public WeakImplHelper1< security::XAccessControlContext > { Reference< security::XAccessControlContext > m_x1, m_x2; inline acc_Intersection( Reference< security::XAccessControlContext > const & x1, Reference< security::XAccessControlContext > const & x2 ) SAL_THROW(()); public: virtual ~acc_Intersection() SAL_THROW(()); static inline Reference< security::XAccessControlContext > create( Reference< security::XAccessControlContext > const & x1, Reference< security::XAccessControlContext > const & x2 ) SAL_THROW(()); // XAccessControlContext impl virtual void SAL_CALL checkPermission( Any const & perm ) throw (RuntimeException); }; //__________________________________________________________________________________________________ inline acc_Intersection::acc_Intersection( Reference< security::XAccessControlContext > const & x1, Reference< security::XAccessControlContext > const & x2 ) SAL_THROW(()) : m_x1( x1 ) , m_x2( x2 ) {} //__________________________________________________________________________________________________ acc_Intersection::~acc_Intersection() SAL_THROW(()) {} //-------------------------------------------------------------------------------------------------- inline Reference< security::XAccessControlContext > acc_Intersection::create( Reference< security::XAccessControlContext > const & x1, Reference< security::XAccessControlContext > const & x2 ) SAL_THROW(()) { if (! x1.is()) return x2; if (! x2.is()) return x1; return new acc_Intersection( x1, x2 ); } //__________________________________________________________________________________________________ void acc_Intersection::checkPermission( Any const & perm ) throw (RuntimeException) { m_x1->checkPermission( perm ); m_x2->checkPermission( perm ); } /** ac context unifies permissions of two ac contexts */ class acc_Union : public WeakImplHelper1< security::XAccessControlContext > { Reference< security::XAccessControlContext > m_x1, m_x2; inline acc_Union( Reference< security::XAccessControlContext > const & x1, Reference< security::XAccessControlContext > const & x2 ) SAL_THROW(()); public: virtual ~acc_Union() SAL_THROW(()); static inline Reference< security::XAccessControlContext > create( Reference< security::XAccessControlContext > const & x1, Reference< security::XAccessControlContext > const & x2 ) SAL_THROW(()); // XAccessControlContext impl virtual void SAL_CALL checkPermission( Any const & perm ) throw (RuntimeException); }; //__________________________________________________________________________________________________ inline acc_Union::acc_Union( Reference< security::XAccessControlContext > const & x1, Reference< security::XAccessControlContext > const & x2 ) SAL_THROW(()) : m_x1( x1 ) , m_x2( x2 ) {} //__________________________________________________________________________________________________ acc_Union::~acc_Union() SAL_THROW(()) {} //-------------------------------------------------------------------------------------------------- inline Reference< security::XAccessControlContext > acc_Union::create( Reference< security::XAccessControlContext > const & x1, Reference< security::XAccessControlContext > const & x2 ) SAL_THROW(()) { if (! x1.is()) return Reference< security::XAccessControlContext >(); // unrestricted if (! x2.is()) return Reference< security::XAccessControlContext >(); // unrestricted return new acc_Union( x1, x2 ); } //__________________________________________________________________________________________________ void acc_Union::checkPermission( Any const & perm ) throw (RuntimeException) { try { m_x1->checkPermission( perm ); } catch (security::AccessControlException &) { m_x2->checkPermission( perm ); } } /** ac context doing permission checks on static permissions */ class acc_Policy : public WeakImplHelper1< security::XAccessControlContext > { PermissionCollection m_permissions; public: inline acc_Policy( PermissionCollection const & permissions ) SAL_THROW(()); virtual ~acc_Policy() SAL_THROW(()); // XAccessControlContext impl virtual void SAL_CALL checkPermission( Any const & perm ) throw (RuntimeException); }; //__________________________________________________________________________________________________ inline acc_Policy::acc_Policy( PermissionCollection const & permissions ) SAL_THROW(()) : m_permissions( permissions ) {} //__________________________________________________________________________________________________ acc_Policy::~acc_Policy() SAL_THROW(()) {} //__________________________________________________________________________________________________ void acc_Policy::checkPermission( Any const & perm ) throw (RuntimeException) { m_permissions.checkPermission( perm ); } /** current context overriding dynamic ac restriction */ class acc_CurrentContext : public ImplHelper1< XCurrentContext > { oslInterlockedCount m_refcount; Reference< XCurrentContext > m_xDelegate; Any m_restriction; public: inline acc_CurrentContext( Reference< XCurrentContext > const & xDelegate, Reference< security::XAccessControlContext > const & xRestriction ) SAL_THROW(()); virtual ~acc_CurrentContext() SAL_THROW(()); // XInterface impl virtual void SAL_CALL acquire() throw (); virtual void SAL_CALL release() throw (); // XCurrentContext impl virtual Any SAL_CALL getValueByName( OUString const & name ) throw (RuntimeException); }; //__________________________________________________________________________________________________ inline acc_CurrentContext::acc_CurrentContext( Reference< XCurrentContext > const & xDelegate, Reference< security::XAccessControlContext > const & xRestriction ) SAL_THROW(()) : m_refcount( 0 ) , m_xDelegate( xDelegate ) { if (xRestriction.is()) { m_restriction = makeAny( xRestriction ); } // return empty any otherwise on getValueByName(), not null interface } //__________________________________________________________________________________________________ acc_CurrentContext::~acc_CurrentContext() SAL_THROW(()) {} //__________________________________________________________________________________________________ void acc_CurrentContext::acquire() throw () { osl_atomic_increment( &m_refcount ); } //__________________________________________________________________________________________________ void acc_CurrentContext::release() throw () { if (! osl_atomic_decrement( &m_refcount )) { delete this; } } //__________________________________________________________________________________________________ Any acc_CurrentContext::getValueByName( OUString const & name ) throw (RuntimeException) { if (name.startsWith(s_acRestriction)) { return m_restriction; } else if (m_xDelegate.is()) { return m_xDelegate->getValueByName( name ); } else { return Any(); } } //################################################################################################## static inline Reference< security::XAccessControlContext > getDynamicRestriction( Reference< XCurrentContext > const & xContext ) SAL_THROW( (RuntimeException) ) { if (xContext.is()) { Any acc(xContext->getValueByName(OUString(s_acRestriction))); if (typelib_TypeClass_INTERFACE == acc.pType->eTypeClass) { // avoid ref-counting OUString const & typeName = *reinterpret_cast< OUString const * >( &acc.pType->pTypeName ); if ( typeName == "com.sun.star.security.XAccessControlContext" ) { return Reference< security::XAccessControlContext >( *reinterpret_cast< security::XAccessControlContext ** const >( acc.pData ) ); } else // try to query { return Reference< security::XAccessControlContext >::query( *reinterpret_cast< XInterface ** const >( acc.pData ) ); } } } return Reference< security::XAccessControlContext >(); } //================================================================================================== class cc_reset { void * m_cc; public: inline cc_reset( void * cc ) SAL_THROW(()) : m_cc( cc ) {} inline ~cc_reset() SAL_THROW(()) { ::uno_setCurrentContext( m_cc, s_envType.pData, 0 ); } }; //################################################################################################## struct MutexHolder { Mutex m_mutex; }; typedef WeakComponentImplHelper3< security::XAccessController, lang::XServiceInfo, lang::XInitialization > t_helper; //================================================================================================== class AccessController : public MutexHolder , public t_helper { Reference< XComponentContext > m_xComponentContext; Reference< security::XPolicy > m_xPolicy; Reference< security::XPolicy > const & getPolicy() SAL_THROW( (RuntimeException) ); // mode enum Mode { OFF, ON, DYNAMIC_ONLY, SINGLE_USER, SINGLE_DEFAULT_USER } m_mode; PermissionCollection m_defaultPermissions; // for single-user mode PermissionCollection m_singleUserPermissions; OUString m_singleUserId; bool m_defaultPerm_init; bool m_singleUser_init; // for multi-user mode lru_cache< OUString, PermissionCollection, OUStringHash, equal_to< OUString > > m_user2permissions; ThreadData m_rec; typedef vector< pair< OUString, Any > > t_rec_vec; inline void clearPostPoned() SAL_THROW(()); void checkAndClearPostPoned() SAL_THROW( (RuntimeException) ); PermissionCollection getEffectivePermissions( Reference< XCurrentContext > const & xContext, Any const & demanded_perm ) SAL_THROW( (RuntimeException) ); protected: virtual void SAL_CALL disposing(); public: AccessController( Reference< XComponentContext > const & xComponentContext ) SAL_THROW( (RuntimeException) ); virtual ~AccessController() SAL_THROW(()); // XInitialization impl virtual void SAL_CALL initialize( Sequence< Any > const & arguments ) throw (Exception); // XAccessController impl virtual void SAL_CALL checkPermission( Any const & perm ) throw (RuntimeException); virtual Any SAL_CALL doRestricted( Reference< security::XAction > const & xAction, Reference< security::XAccessControlContext > const & xRestriction ) throw (Exception); virtual Any SAL_CALL doPrivileged( Reference< security::XAction > const & xAction, Reference< security::XAccessControlContext > const & xRestriction ) throw (Exception); virtual Reference< security::XAccessControlContext > SAL_CALL getContext() throw (RuntimeException); // XServiceInfo impl virtual OUString SAL_CALL getImplementationName() throw (RuntimeException); virtual sal_Bool SAL_CALL supportsService( OUString const & serviceName ) throw (RuntimeException); virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() throw (RuntimeException); }; //__________________________________________________________________________________________________ AccessController::AccessController( Reference< XComponentContext > const & xComponentContext ) SAL_THROW( (RuntimeException) ) : t_helper( m_mutex ) , m_xComponentContext( xComponentContext ) , m_mode( ON ) // default , m_defaultPerm_init( false ) , m_singleUser_init( false ) , m_rec( 0 ) { // The .../mode value had originally been set in // cppu::add_access_control_entries (cppuhelper/source/servicefactory.cxx) // to something other than "off" depending on various UNO_AC* bootstrap // variables that are no longer supported, so this is mostly dead code now: OUString mode; if (m_xComponentContext->getValueByName( "/services/" SERVICE_NAME "/mode" ) >>= mode) { if ( mode == "off" ) { m_mode = OFF; } else if ( mode == "on" ) { m_mode = ON; } else if ( mode == "dynamic-only" ) { m_mode = DYNAMIC_ONLY; } else if ( mode == "single-user" ) { m_xComponentContext->getValueByName( "/services/" SERVICE_NAME "/single-user-id" ) >>= m_singleUserId; if (m_singleUserId.isEmpty()) { throw RuntimeException( "expected a user id in component context entry " "\"/services/" SERVICE_NAME "/single-user-id\"!", (OWeakObject *)this ); } m_mode = SINGLE_USER; } else if ( mode == "single-default-user" ) { m_mode = SINGLE_DEFAULT_USER; } } // switch on caching for DYNAMIC_ONLY and ON (sharable multi-user process) if (ON == m_mode || DYNAMIC_ONLY == m_mode) { sal_Int32 cacheSize = 0; // multi-user cache size if (! (m_xComponentContext->getValueByName( "/services/" SERVICE_NAME "/user-cache-size" ) >>= cacheSize)) { cacheSize = 128; // reasonable default? } #ifdef __CACHE_DIAGNOSE cacheSize = 2; #endif m_user2permissions.setSize( cacheSize ); } } //__________________________________________________________________________________________________ AccessController::~AccessController() SAL_THROW(()) {} //__________________________________________________________________________________________________ void AccessController::disposing() { m_mode = OFF; // avoid checks from now on xxx todo review/ better DYNAMIC_ONLY? m_xPolicy.clear(); m_xComponentContext.clear(); } // XInitialization impl //__________________________________________________________________________________________________ void AccessController::initialize( Sequence< Any > const & arguments ) throw (Exception) { // xxx todo: review for forking // portal forking hack: re-initialize for another user-id if (SINGLE_USER != m_mode) // only if in single-user mode { throw RuntimeException( "invalid call: ac must be in \"single-user\" mode!", (OWeakObject *)this ); } OUString userId; arguments[ 0 ] >>= userId; if ( userId.isEmpty() ) { throw RuntimeException( "expected a user-id as first argument!", (OWeakObject *)this ); } // assured that no sync is necessary: no check happens at this forking time m_singleUserId = userId; m_singleUser_init = false; } //__________________________________________________________________________________________________ Reference< security::XPolicy > const & AccessController::getPolicy() SAL_THROW( (RuntimeException) ) { // get policy singleton if (! m_xPolicy.is()) { Reference< security::XPolicy > xPolicy; m_xComponentContext->getValueByName( "/singletons/com.sun.star.security.thePolicy" ) >>= xPolicy; if (xPolicy.is()) { MutexGuard guard( m_mutex ); if (! m_xPolicy.is()) { m_xPolicy = xPolicy; } } else { throw SecurityException( "cannot get policy singleton!", (OWeakObject *)this ); } } return m_xPolicy; } #ifdef __DIAGNOSE static void dumpPermissions( PermissionCollection const & collection, OUString const & userId = OUString() ) SAL_THROW(()) { OUStringBuffer buf( 48 ); if (!userId.isEmpty()) { buf.append( "> dumping permissions of user \"" ); buf.append( userId ); buf.append( "\":" ); } else { buf.append( "> dumping default permissions:" ); } OString str( OUStringToOString( buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) ); OSL_TRACE( "%s", str.getStr() ); Sequence< OUString > permissions( collection.toStrings() ); OUString const * p = permissions.getConstArray(); for ( sal_Int32 nPos = 0; nPos < permissions.getLength(); ++nPos ) { OString str( OUStringToOString( p[ nPos ], RTL_TEXTENCODING_ASCII_US ) ); OSL_TRACE( "%s", str.getStr() ); } OSL_TRACE( "> permission dump done" ); } #endif //__________________________________________________________________________________________________ inline void AccessController::clearPostPoned() SAL_THROW(()) { delete reinterpret_cast< t_rec_vec * >( m_rec.getData() ); m_rec.setData( 0 ); } //__________________________________________________________________________________________________ void AccessController::checkAndClearPostPoned() SAL_THROW( (RuntimeException) ) { // check postponed permissions auto_ptr< t_rec_vec > rec( reinterpret_cast< t_rec_vec * >( m_rec.getData() ) ); m_rec.setData( 0 ); // takeover ownership OSL_ASSERT( rec.get() ); if (rec.get()) { t_rec_vec const & vec = *rec.get(); switch (m_mode) { case SINGLE_USER: { OSL_ASSERT( m_singleUser_init ); for ( size_t nPos = 0; nPos < vec.size(); ++nPos ) { pair< OUString, Any > const & p = vec[ nPos ]; OSL_ASSERT( m_singleUserId.equals( p.first ) ); m_singleUserPermissions.checkPermission( p.second ); } break; } case SINGLE_DEFAULT_USER: { OSL_ASSERT( m_defaultPerm_init ); for ( size_t nPos = 0; nPos < vec.size(); ++nPos ) { pair< OUString, Any > const & p = vec[ nPos ]; OSL_ASSERT( p.first.isEmpty() ); // default-user m_defaultPermissions.checkPermission( p.second ); } break; } case ON: { for ( size_t nPos = 0; nPos < vec.size(); ++nPos ) { pair< OUString, Any > const & p = vec[ nPos ]; PermissionCollection const * pPermissions; // lookup policy for user { MutexGuard guard( m_mutex ); pPermissions = m_user2permissions.lookup( p.first ); } OSL_ASSERT( pPermissions ); if (pPermissions) { pPermissions->checkPermission( p.second ); } } break; } default: OSL_FAIL( "### this should never be called in this ac mode!" ); break; } } } //__________________________________________________________________________________________________ /** this is the only function calling the policy singleton and thus has to take care of recurring calls! @param demanded_perm (if not empty) is the demanded permission of a checkPermission() call which will be postponed for recurring calls */ PermissionCollection AccessController::getEffectivePermissions( Reference< XCurrentContext > const & xContext, Any const & demanded_perm ) SAL_THROW( (RuntimeException) ) { OUString userId; switch (m_mode) { case SINGLE_USER: { if (m_singleUser_init) return m_singleUserPermissions; userId = m_singleUserId; break; } case SINGLE_DEFAULT_USER: { if (m_defaultPerm_init) return m_defaultPermissions; break; } case ON: { if (xContext.is()) { xContext->getValueByName( USER_CREDS ".id" ) >>= userId; } if ( userId.isEmpty() ) { throw SecurityException( "cannot determine current user in multi-user ac!", (OWeakObject *)this ); } // lookup policy for user MutexGuard guard( m_mutex ); PermissionCollection const * pPermissions = m_user2permissions.lookup( userId ); if (pPermissions) return *pPermissions; break; } default: OSL_FAIL( "### this should never be called in this ac mode!" ); return PermissionCollection(); } // call on policy // iff this is a recurring call for the default user, then grant all permissions t_rec_vec * rec = reinterpret_cast< t_rec_vec * >( m_rec.getData() ); if (rec) // tls entry exists => this is recursive call { if (demanded_perm.hasValue()) { // enqueue rec->push_back( pair< OUString, Any >( userId, demanded_perm ) ); } #ifdef __DIAGNOSE OUStringBuffer buf( 48 ); buf.append( "> info: recurring call of user \"" ); buf.append( userId ); buf.append( "\"" ); OString str( OUStringToOString( buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) ); OSL_TRACE( "%s", str.getStr() ); #endif return PermissionCollection( new AllPermission() ); } else // no tls { rec = new t_rec_vec; m_rec.setData( rec ); } try // calls on API { // init default permissions if (! m_defaultPerm_init) { PermissionCollection defaultPermissions( getPolicy()->getDefaultPermissions() ); // assign MutexGuard guard( m_mutex ); if (! m_defaultPerm_init) { m_defaultPermissions = defaultPermissions; m_defaultPerm_init = true; } #ifdef __DIAGNOSE dumpPermissions( m_defaultPermissions ); #endif } PermissionCollection ret; // init user permissions switch (m_mode) { case SINGLE_USER: { ret = PermissionCollection( getPolicy()->getPermissions( userId ), m_defaultPermissions ); { // assign MutexGuard guard( m_mutex ); if (m_singleUser_init) { ret = m_singleUserPermissions; } else { m_singleUserPermissions = ret; m_singleUser_init = true; } } #ifdef __DIAGNOSE dumpPermissions( ret, userId ); #endif break; } case SINGLE_DEFAULT_USER: { ret = m_defaultPermissions; break; } case ON: { ret = PermissionCollection( getPolicy()->getPermissions( userId ), m_defaultPermissions ); { // cache MutexGuard guard( m_mutex ); m_user2permissions.set( userId, ret ); } #ifdef __DIAGNOSE dumpPermissions( ret, userId ); #endif break; } default: break; } // check postponed checkAndClearPostPoned(); return ret; } catch (const security::AccessControlException & exc) // wrapped into DeploymentException { clearPostPoned(); // safety: exception could have happened before checking postponed? OUStringBuffer buf( 64 ); buf.append( "deployment error (AccessControlException occurred): " ); buf.append( exc.Message ); throw DeploymentException( buf.makeStringAndClear(), exc.Context ); } catch (RuntimeException &) { // dont check postponed, just cleanup clearPostPoned(); delete reinterpret_cast< t_rec_vec * >( m_rec.getData() ); m_rec.setData( 0 ); throw; } catch (Exception &) { // check postponed permissions first // => AccessControlExceptions are errors, user exceptions not! checkAndClearPostPoned(); throw; } catch (...) { // dont check postponed, just cleanup clearPostPoned(); throw; } } // XAccessController impl //__________________________________________________________________________________________________ void AccessController::checkPermission( Any const & perm ) throw (RuntimeException) { if (rBHelper.bDisposed) { throw lang::DisposedException( "checkPermission() call on disposed AccessController!", (OWeakObject *)this ); } if (OFF == m_mode) return; // first dynamic check of ac contexts Reference< XCurrentContext > xContext; ::uno_getCurrentContext( (void **)&xContext, s_envType.pData, 0 ); Reference< security::XAccessControlContext > xACC( getDynamicRestriction( xContext ) ); if (xACC.is()) { xACC->checkPermission( perm ); } if (DYNAMIC_ONLY == m_mode) return; // then static check getEffectivePermissions( xContext, perm ).checkPermission( perm ); } //__________________________________________________________________________________________________ Any AccessController::doRestricted( Reference< security::XAction > const & xAction, Reference< security::XAccessControlContext > const & xRestriction ) throw (Exception) { if (rBHelper.bDisposed) { throw lang::DisposedException( "doRestricted() call on disposed AccessController!", (OWeakObject *)this ); } if (OFF == m_mode) // optimize this way, because no dynamic check will be performed return xAction->run(); if (xRestriction.is()) { Reference< XCurrentContext > xContext; ::uno_getCurrentContext( (void **)&xContext, s_envType.pData, 0 ); // override restriction Reference< XCurrentContext > xNewContext( new acc_CurrentContext( xContext, acc_Intersection::create( xRestriction, getDynamicRestriction( xContext ) ) ) ); ::uno_setCurrentContext( xNewContext.get(), s_envType.pData, 0 ); cc_reset reset( xContext.get() ); return xAction->run(); } else { return xAction->run(); } } //__________________________________________________________________________________________________ Any AccessController::doPrivileged( Reference< security::XAction > const & xAction, Reference< security::XAccessControlContext > const & xRestriction ) throw (Exception) { if (rBHelper.bDisposed) { throw lang::DisposedException( "doPrivileged() call on disposed AccessController!", (OWeakObject *)this ); } if (OFF == m_mode) // no dynamic check will be performed { return xAction->run(); } Reference< XCurrentContext > xContext; ::uno_getCurrentContext( (void **)&xContext, s_envType.pData, 0 ); Reference< security::XAccessControlContext > xOldRestr( getDynamicRestriction( xContext ) ); if (xOldRestr.is()) // previous restriction { // override restriction Reference< XCurrentContext > xNewContext( new acc_CurrentContext( xContext, acc_Union::create( xRestriction, xOldRestr ) ) ); ::uno_setCurrentContext( xNewContext.get(), s_envType.pData, 0 ); cc_reset reset( xContext.get() ); return xAction->run(); } else // no previous restriction => never current restriction { return xAction->run(); } } //__________________________________________________________________________________________________ Reference< security::XAccessControlContext > AccessController::getContext() throw (RuntimeException) { if (rBHelper.bDisposed) { throw lang::DisposedException( "getContext() call on disposed AccessController!", (OWeakObject *)this ); } if (OFF == m_mode) // optimize this way, because no dynamic check will be performed { return new acc_Policy( PermissionCollection( new AllPermission() ) ); } Reference< XCurrentContext > xContext; ::uno_getCurrentContext( (void **)&xContext, s_envType.pData, 0 ); return acc_Intersection::create( getDynamicRestriction( xContext ), new acc_Policy( getEffectivePermissions( xContext, Any() ) ) ); } // XServiceInfo impl //__________________________________________________________________________________________________ OUString AccessController::getImplementationName() throw (RuntimeException) { return stoc_bootstrap::ac_getImplementationName(); } //__________________________________________________________________________________________________ sal_Bool AccessController::supportsService( OUString const & serviceName ) throw (RuntimeException) { return cppu::supportsService(this, serviceName); } //__________________________________________________________________________________________________ Sequence< OUString > AccessController::getSupportedServiceNames() throw (RuntimeException) { return stoc_bootstrap::ac_getSupportedServiceNames(); } } //################################################################################################## namespace stoc_bootstrap { //-------------------------------------------------------------------------------------------------- Reference< XInterface > SAL_CALL ac_create( Reference< XComponentContext > const & xComponentContext ) SAL_THROW( (Exception) ) { return (OWeakObject *)new stoc_sec::AccessController( xComponentContext ); } //-------------------------------------------------------------------------------------------------- Sequence< OUString > ac_getSupportedServiceNames() SAL_THROW(()) { Sequence< OUString > aSNS( 1 ); aSNS.getArray()[0] = OUString(SERVICE_NAME); return aSNS; } //-------------------------------------------------------------------------------------------------- OUString ac_getImplementationName() SAL_THROW(()) { return OUString(IMPL_NAME); } //-------------------------------------------------------------------------------------------------- Reference< XInterface > SAL_CALL filepolicy_create( Reference< XComponentContext > const & xComponentContext ) SAL_THROW( (Exception) ); //-------------------------------------------------------------------------------------------------- Sequence< OUString > filepolicy_getSupportedServiceNames() SAL_THROW(()); //-------------------------------------------------------------------------------------------------- OUString filepolicy_getImplementationName() SAL_THROW(()); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */