1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/sdb/XDatabaseRegistrations.hpp>
22 #include <cppuhelper/basemutex.hxx>
23 #include <cppuhelper/interfacecontainer.hxx>
24 #include <cppuhelper/implbase1.hxx>
25 #include <rtl/ustrbuf.hxx>
26 #include <unotools/pathoptions.hxx>
27 #include <tools/urlobj.hxx>
28 #include <unotools/confignode.hxx>
30 #include <databaseregistrations.hxx>
34 using ::com::sun::star::uno::Reference
;
35 using ::com::sun::star::uno::XInterface
;
36 using ::com::sun::star::uno::UNO_QUERY
;
37 using ::com::sun::star::uno::UNO_QUERY_THROW
;
38 using ::com::sun::star::uno::UNO_SET_THROW
;
39 using ::com::sun::star::uno::Exception
;
40 using ::com::sun::star::uno::RuntimeException
;
41 using ::com::sun::star::uno::Any
;
42 using ::com::sun::star::uno::makeAny
;
43 using ::com::sun::star::uno::Sequence
;
44 using ::com::sun::star::uno::Type
;
45 using ::com::sun::star::uno::XComponentContext
;
46 using ::com::sun::star::container::NoSuchElementException
;
47 using ::com::sun::star::lang::IllegalArgumentException
;
48 using ::com::sun::star::lang::IllegalAccessException
;
49 using ::com::sun::star::container::ElementExistException
;
50 using ::com::sun::star::sdb::XDatabaseRegistrations
;
51 using ::com::sun::star::sdb::XDatabaseRegistrationsListener
;
52 using ::com::sun::star::sdb::DatabaseRegistrationEvent
;
53 using ::com::sun::star::uno::XAggregation
;
55 static OUString
getConfigurationRootPath()
57 return OUString("org.openoffice.Office.DataAccess/RegisteredNames");
60 static OUString
getLocationNodeName()
62 return OUString("Location");
65 static OUString
getNameNodeName()
67 return OUString("Name");
70 // DatabaseRegistrations - declaration
71 typedef ::cppu::WeakAggImplHelper1
< XDatabaseRegistrations
72 > DatabaseRegistrations_Base
;
73 class DatabaseRegistrations
:public ::cppu::BaseMutex
74 ,public DatabaseRegistrations_Base
77 DatabaseRegistrations( const Reference
<XComponentContext
>& _rxContext
);
80 virtual ~DatabaseRegistrations();
83 virtual sal_Bool SAL_CALL
hasRegisteredDatabase( const OUString
& _Name
) throw (IllegalArgumentException
, RuntimeException
, std::exception
) SAL_OVERRIDE
;
84 virtual Sequence
< OUString
> SAL_CALL
getRegistrationNames() throw (RuntimeException
, std::exception
) SAL_OVERRIDE
;
85 virtual OUString SAL_CALL
getDatabaseLocation( const OUString
& _Name
) throw (IllegalArgumentException
, NoSuchElementException
, RuntimeException
, std::exception
) SAL_OVERRIDE
;
86 virtual void SAL_CALL
registerDatabaseLocation( const OUString
& _Name
, const OUString
& _Location
) throw (IllegalArgumentException
, ElementExistException
, RuntimeException
, std::exception
) SAL_OVERRIDE
;
87 virtual void SAL_CALL
revokeDatabaseLocation( const OUString
& _Name
) throw (IllegalArgumentException
, NoSuchElementException
, IllegalAccessException
, RuntimeException
, std::exception
) SAL_OVERRIDE
;
88 virtual void SAL_CALL
changeDatabaseLocation( const OUString
& Name
, const OUString
& NewLocation
) throw (IllegalArgumentException
, NoSuchElementException
, IllegalAccessException
, RuntimeException
, std::exception
) SAL_OVERRIDE
;
89 virtual sal_Bool SAL_CALL
isDatabaseRegistrationReadOnly( const OUString
& _Name
) throw (IllegalArgumentException
, NoSuchElementException
, RuntimeException
, std::exception
) SAL_OVERRIDE
;
90 virtual void SAL_CALL
addDatabaseRegistrationsListener( const Reference
< XDatabaseRegistrationsListener
>& Listener
) throw (RuntimeException
, std::exception
) SAL_OVERRIDE
;
91 virtual void SAL_CALL
removeDatabaseRegistrationsListener( const Reference
< XDatabaseRegistrationsListener
>& Listener
) throw (RuntimeException
, std::exception
) SAL_OVERRIDE
;
95 impl_checkValidName_common(const OUString
& _rName
);
96 ::utl::OConfigurationNode
97 impl_checkValidName_throw_must_exist(const OUString
& _rName
);
98 ::utl::OConfigurationNode
99 impl_checkValidName_throw_must_not_exist(const OUString
& _rName
);
101 void impl_checkValidLocation_throw( const OUString
& _rLocation
);
103 /** retrieves the configuration node whose "Name" sub node has the given value
105 Since we separated the name of the registration node from the "Name" value of the registration, we cannot
106 simply do a "getByName" (equivalent) when we want to retrieve the node for a given registration name.
107 Instead, we must search all nodes.
109 If a node with the given display name does not exist, then a NoSuchElementException is thrown.
111 If no exception is thrown, then a valid node is returned: If the node existed it is returned.
113 ::utl::OConfigurationNode
114 impl_getNodeForName_throw_must_exist(const OUString
& _rName
);
116 /** retrieves the configuration node whose "Name" sub node has the given value
118 Since we separated the name of the registration node from the "Name" value of the registration, we cannot
119 simply do a "getByName" (equivalent) when we want to retrieve the node for a given registration name.
120 Instead, we must search all nodes.
122 If a node with the given name already exists, then a ElementExistException is thrown.
124 If no exception is thrown, then a valid node is returned: If the node did not yet exist a new node is created,
125 in this case the root node is not yet committed.
127 ::utl::OConfigurationNode
128 impl_getNodeForName_throw_must_not_exist(const OUString
& _rName
);
131 ::utl::OConfigurationNode
132 impl_getNodeForName_nothrow(const OUString
& _rName
);
135 Reference
<XComponentContext
> m_aContext
;
136 ::utl::OConfigurationTreeRoot m_aConfigurationRoot
;
137 ::cppu::OInterfaceContainerHelper m_aRegistrationListeners
;
140 // DatabaseRegistrations - implementation
141 DatabaseRegistrations::DatabaseRegistrations( const Reference
<XComponentContext
> & _rxContext
)
142 :m_aContext( _rxContext
)
143 ,m_aConfigurationRoot()
144 ,m_aRegistrationListeners( m_aMutex
)
146 m_aConfigurationRoot
= ::utl::OConfigurationTreeRoot::createWithComponentContext(
147 m_aContext
, getConfigurationRootPath(), -1, ::utl::OConfigurationTreeRoot::CM_UPDATABLE
);
150 DatabaseRegistrations::~DatabaseRegistrations()
154 ::utl::OConfigurationNode
DatabaseRegistrations::impl_getNodeForName_nothrow( const OUString
& _rName
)
156 Sequence
< OUString
> aNames( m_aConfigurationRoot
.getNodeNames() );
157 for ( const OUString
* pName
= aNames
.getConstArray();
158 pName
!= aNames
.getConstArray() + aNames
.getLength();
162 ::utl::OConfigurationNode aNodeForName
= m_aConfigurationRoot
.openNode( *pName
);
165 OSL_VERIFY( aNodeForName
.getNodeValue( getNameNodeName() ) >>= sTestName
);
166 if ( sTestName
== _rName
)
169 return ::utl::OConfigurationNode();
172 ::utl::OConfigurationNode
DatabaseRegistrations::impl_getNodeForName_throw_must_exist(const OUString
& _rName
)
174 ::utl::OConfigurationNode
aNodeForName( impl_getNodeForName_nothrow( _rName
) );
176 if (!aNodeForName
.isValid())
178 throw NoSuchElementException( _rName
, *this );
184 ::utl::OConfigurationNode
DatabaseRegistrations::impl_getNodeForName_throw_must_not_exist(const OUString
& _rName
)
186 ::utl::OConfigurationNode
aNodeForName( impl_getNodeForName_nothrow( _rName
) );
188 if (aNodeForName
.isValid())
189 throw ElementExistException( _rName
, *this );
191 OUString sNewNodeName
;
193 OUStringBuffer aNewNodeName
;
194 aNewNodeName
.appendAscii( "org.openoffice." );
195 aNewNodeName
.append( _rName
);
198 OUStringBuffer
aReset( aNewNodeName
);
199 sNewNodeName
= aNewNodeName
.makeStringAndClear();
201 while ( m_aConfigurationRoot
.hasByName( sNewNodeName
) )
203 aNewNodeName
= aReset
;
204 aNewNodeName
.appendAscii( " " );
205 aNewNodeName
.append( i
);
206 sNewNodeName
= aNewNodeName
.makeStringAndClear();
210 ::utl::OConfigurationNode
aNewNode( m_aConfigurationRoot
.createNode( sNewNodeName
) );
211 aNewNode
.setNodeValue( getNameNodeName(), makeAny( _rName
) );
215 void DatabaseRegistrations::impl_checkValidName_common(const OUString
& _rName
)
217 if ( !m_aConfigurationRoot
.isValid() )
218 throw RuntimeException( OUString(), *this );
220 if ( _rName
.isEmpty() )
221 throw IllegalArgumentException( OUString(), *this, 1 );
224 ::utl::OConfigurationNode
DatabaseRegistrations::impl_checkValidName_throw_must_exist(const OUString
& _rName
)
226 impl_checkValidName_common(_rName
);
227 return impl_getNodeForName_throw_must_exist(_rName
);
230 ::utl::OConfigurationNode
DatabaseRegistrations::impl_checkValidName_throw_must_not_exist(const OUString
& _rName
)
232 impl_checkValidName_common(_rName
);
233 return impl_getNodeForName_throw_must_not_exist(_rName
);
236 void DatabaseRegistrations::impl_checkValidLocation_throw( const OUString
& _rLocation
)
238 if ( _rLocation
.isEmpty() )
239 throw IllegalArgumentException( OUString(), *this, 2 );
241 INetURLObject
aURL( _rLocation
);
242 if ( aURL
.GetProtocol() == INetProtocol::NotValid
)
243 throw IllegalArgumentException( OUString(), *this, 2 );
246 sal_Bool SAL_CALL
DatabaseRegistrations::hasRegisteredDatabase( const OUString
& _Name
) throw (IllegalArgumentException
, RuntimeException
, std::exception
)
248 ::osl::MutexGuard
aGuard( m_aMutex
);
249 ::utl::OConfigurationNode aNodeForName
= impl_getNodeForName_nothrow( _Name
);
250 return aNodeForName
.isValid();
253 Sequence
< OUString
> SAL_CALL
DatabaseRegistrations::getRegistrationNames() throw (RuntimeException
, std::exception
)
255 ::osl::MutexGuard
aGuard( m_aMutex
);
256 if ( !m_aConfigurationRoot
.isValid() )
257 throw RuntimeException( OUString(), *this );
259 Sequence
< OUString
> aProgrammaticNames( m_aConfigurationRoot
.getNodeNames() );
260 Sequence
< OUString
> aDisplayNames( aProgrammaticNames
.getLength() );
261 OUString
* pDisplayName
= aDisplayNames
.getArray();
263 for ( const OUString
* pName
= aProgrammaticNames
.getConstArray();
264 pName
!= aProgrammaticNames
.getConstArray() + aProgrammaticNames
.getLength();
265 ++pName
, ++pDisplayName
268 ::utl::OConfigurationNode aRegistrationNode
= m_aConfigurationRoot
.openNode( *pName
);
269 OSL_VERIFY( aRegistrationNode
.getNodeValue( getNameNodeName() ) >>= *pDisplayName
);
272 return aDisplayNames
;
275 OUString SAL_CALL
DatabaseRegistrations::getDatabaseLocation( const OUString
& _Name
) throw (IllegalArgumentException
, NoSuchElementException
, RuntimeException
, std::exception
)
277 ::osl::MutexGuard
aGuard( m_aMutex
);
279 ::utl::OConfigurationNode aNodeForName
= impl_checkValidName_throw_must_exist(_Name
);
282 OSL_VERIFY( aNodeForName
.getNodeValue( getLocationNodeName() ) >>= sLocation
);
283 sLocation
= SvtPathOptions().SubstituteVariable( sLocation
);
288 void SAL_CALL
DatabaseRegistrations::registerDatabaseLocation( const OUString
& _Name
, const OUString
& _Location
) throw (IllegalArgumentException
, ElementExistException
, RuntimeException
, std::exception
)
290 ::osl::ClearableMutexGuard
aGuard( m_aMutex
);
293 impl_checkValidLocation_throw( _Location
);
294 ::utl::OConfigurationNode aDataSourceRegistration
= impl_checkValidName_throw_must_not_exist(_Name
);
297 aDataSourceRegistration
.setNodeValue( getLocationNodeName(), makeAny( _Location
) );
298 m_aConfigurationRoot
.commit();
301 DatabaseRegistrationEvent
aEvent( *this, _Name
, OUString(), _Location
);
303 m_aRegistrationListeners
.notifyEach( &XDatabaseRegistrationsListener::registeredDatabaseLocation
, aEvent
);
306 void SAL_CALL
DatabaseRegistrations::revokeDatabaseLocation( const OUString
& _Name
) throw (IllegalArgumentException
, NoSuchElementException
, IllegalAccessException
, RuntimeException
, std::exception
)
308 ::osl::ClearableMutexGuard
aGuard( m_aMutex
);
311 ::utl::OConfigurationNode aNodeForName
= impl_checkValidName_throw_must_exist(_Name
);
313 // obtain properties for notification
315 OSL_VERIFY( aNodeForName
.getNodeValue( getLocationNodeName() ) >>= sLocation
);
318 if ( aNodeForName
.isReadonly()
319 || !m_aConfigurationRoot
.removeNode( aNodeForName
.getLocalName() )
321 throw IllegalAccessException( OUString(), *this );
323 m_aConfigurationRoot
.commit();
326 DatabaseRegistrationEvent
aEvent( *this, _Name
, sLocation
, OUString() );
328 m_aRegistrationListeners
.notifyEach( &XDatabaseRegistrationsListener::revokedDatabaseLocation
, aEvent
);
331 void SAL_CALL
DatabaseRegistrations::changeDatabaseLocation( const OUString
& _Name
, const OUString
& _NewLocation
) throw (IllegalArgumentException
, NoSuchElementException
, IllegalAccessException
, RuntimeException
, std::exception
)
333 ::osl::ClearableMutexGuard
aGuard( m_aMutex
);
336 impl_checkValidLocation_throw( _NewLocation
);
337 ::utl::OConfigurationNode aDataSourceRegistration
= impl_checkValidName_throw_must_exist(_Name
);
339 if ( aDataSourceRegistration
.isReadonly() )
340 throw IllegalAccessException( OUString(), *this );
342 // obtain properties for notification
343 OUString sOldLocation
;
344 OSL_VERIFY( aDataSourceRegistration
.getNodeValue( getLocationNodeName() ) >>= sOldLocation
);
347 aDataSourceRegistration
.setNodeValue( getLocationNodeName(), makeAny( _NewLocation
) );
348 m_aConfigurationRoot
.commit();
351 DatabaseRegistrationEvent
aEvent( *this, _Name
, sOldLocation
, _NewLocation
);
353 m_aRegistrationListeners
.notifyEach( &XDatabaseRegistrationsListener::changedDatabaseLocation
, aEvent
);
356 sal_Bool SAL_CALL
DatabaseRegistrations::isDatabaseRegistrationReadOnly( const OUString
& _Name
) throw (IllegalArgumentException
, NoSuchElementException
, RuntimeException
, std::exception
)
358 ::osl::MutexGuard
aGuard( m_aMutex
);
359 ::utl::OConfigurationNode aDataSourceRegistration
= impl_checkValidName_throw_must_exist(_Name
);
360 return aDataSourceRegistration
.isReadonly();
363 void SAL_CALL
DatabaseRegistrations::addDatabaseRegistrationsListener( const Reference
< XDatabaseRegistrationsListener
>& _Listener
) throw (RuntimeException
, std::exception
)
365 if ( _Listener
.is() )
366 m_aRegistrationListeners
.addInterface( _Listener
);
369 void SAL_CALL
DatabaseRegistrations::removeDatabaseRegistrationsListener( const Reference
< XDatabaseRegistrationsListener
>& _Listener
) throw (RuntimeException
, std::exception
)
371 if ( _Listener
.is() )
372 m_aRegistrationListeners
.removeInterface( _Listener
);
375 // DatabaseRegistrations - factory
376 Reference
< XAggregation
> createDataSourceRegistrations( const Reference
<XComponentContext
> & _rxContext
)
378 return new DatabaseRegistrations( _rxContext
);
381 } // namespace dbaccess
383 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */