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 <comphelper/interfacecontainer2.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::RuntimeException
;
36 using ::com::sun::star::uno::makeAny
;
37 using ::com::sun::star::uno::Sequence
;
38 using ::com::sun::star::uno::XComponentContext
;
39 using ::com::sun::star::container::NoSuchElementException
;
40 using ::com::sun::star::lang::IllegalArgumentException
;
41 using ::com::sun::star::lang::IllegalAccessException
;
42 using ::com::sun::star::container::ElementExistException
;
43 using ::com::sun::star::sdb::XDatabaseRegistrations
;
44 using ::com::sun::star::sdb::XDatabaseRegistrationsListener
;
45 using ::com::sun::star::sdb::DatabaseRegistrationEvent
;
46 using ::com::sun::star::uno::XAggregation
;
48 static OUString
getConfigurationRootPath()
50 return OUString("org.openoffice.Office.DataAccess/RegisteredNames");
53 static OUString
getLocationNodeName()
55 return OUString("Location");
58 static OUString
getNameNodeName()
60 return OUString("Name");
63 // DatabaseRegistrations - declaration
64 typedef ::cppu::WeakAggImplHelper1
< XDatabaseRegistrations
65 > DatabaseRegistrations_Base
;
66 class DatabaseRegistrations
:public ::cppu::BaseMutex
67 ,public DatabaseRegistrations_Base
70 explicit DatabaseRegistrations( const Reference
<XComponentContext
>& _rxContext
);
73 virtual ~DatabaseRegistrations() override
;
76 virtual sal_Bool SAL_CALL
hasRegisteredDatabase( const OUString
& Name
) throw (IllegalArgumentException
, RuntimeException
, std::exception
) override
;
77 virtual Sequence
< OUString
> SAL_CALL
getRegistrationNames() throw (RuntimeException
, std::exception
) override
;
78 virtual OUString SAL_CALL
getDatabaseLocation( const OUString
& Name
) throw (IllegalArgumentException
, NoSuchElementException
, RuntimeException
, std::exception
) override
;
79 virtual void SAL_CALL
registerDatabaseLocation( const OUString
& Name
, const OUString
& Location
) throw (IllegalArgumentException
, ElementExistException
, RuntimeException
, std::exception
) override
;
80 virtual void SAL_CALL
revokeDatabaseLocation( const OUString
& Name
) throw (IllegalArgumentException
, NoSuchElementException
, IllegalAccessException
, RuntimeException
, std::exception
) override
;
81 virtual void SAL_CALL
changeDatabaseLocation( const OUString
& Name
, const OUString
& NewLocation
) throw (IllegalArgumentException
, NoSuchElementException
, IllegalAccessException
, RuntimeException
, std::exception
) override
;
82 virtual sal_Bool SAL_CALL
isDatabaseRegistrationReadOnly( const OUString
& Name
) throw (IllegalArgumentException
, NoSuchElementException
, RuntimeException
, std::exception
) override
;
83 virtual void SAL_CALL
addDatabaseRegistrationsListener( const Reference
< XDatabaseRegistrationsListener
>& Listener
) throw (RuntimeException
, std::exception
) override
;
84 virtual void SAL_CALL
removeDatabaseRegistrationsListener( const Reference
< XDatabaseRegistrationsListener
>& Listener
) throw (RuntimeException
, std::exception
) override
;
88 impl_checkValidName_common(const OUString
& _rName
);
89 ::utl::OConfigurationNode
90 impl_checkValidName_throw_must_exist(const OUString
& _rName
);
91 ::utl::OConfigurationNode
92 impl_checkValidName_throw_must_not_exist(const OUString
& _rName
);
94 void impl_checkValidLocation_throw( const OUString
& _rLocation
);
96 /** retrieves the configuration node whose "Name" sub node has the given value
98 Since we separated the name of the registration node from the "Name" value of the registration, we cannot
99 simply do a "getByName" (equivalent) when we want to retrieve the node for a given registration name.
100 Instead, we must search all nodes.
102 If a node with the given display name does not exist, then a NoSuchElementException is thrown.
104 If no exception is thrown, then a valid node is returned: If the node existed it is returned.
106 ::utl::OConfigurationNode
107 impl_getNodeForName_throw_must_exist(const OUString
& _rName
);
109 /** retrieves the configuration node whose "Name" sub node has the given value
111 Since we separated the name of the registration node from the "Name" value of the registration, we cannot
112 simply do a "getByName" (equivalent) when we want to retrieve the node for a given registration name.
113 Instead, we must search all nodes.
115 If a node with the given name already exists, then a ElementExistException is thrown.
117 If no exception is thrown, then a valid node is returned: If the node did not yet exist a new node is created,
118 in this case the root node is not yet committed.
120 ::utl::OConfigurationNode
121 impl_getNodeForName_throw_must_not_exist(const OUString
& _rName
);
124 ::utl::OConfigurationNode
125 impl_getNodeForName_nothrow(const OUString
& _rName
);
128 Reference
<XComponentContext
> m_aContext
;
129 ::utl::OConfigurationTreeRoot m_aConfigurationRoot
;
130 ::comphelper::OInterfaceContainerHelper2 m_aRegistrationListeners
;
133 // DatabaseRegistrations - implementation
134 DatabaseRegistrations::DatabaseRegistrations( const Reference
<XComponentContext
> & _rxContext
)
135 :m_aContext( _rxContext
)
136 ,m_aConfigurationRoot()
137 ,m_aRegistrationListeners( m_aMutex
)
139 m_aConfigurationRoot
= ::utl::OConfigurationTreeRoot::createWithComponentContext(
140 m_aContext
, getConfigurationRootPath() );
143 DatabaseRegistrations::~DatabaseRegistrations()
147 ::utl::OConfigurationNode
DatabaseRegistrations::impl_getNodeForName_nothrow( const OUString
& _rName
)
149 Sequence
< OUString
> aNames( m_aConfigurationRoot
.getNodeNames() );
150 for ( const OUString
* pName
= aNames
.getConstArray();
151 pName
!= aNames
.getConstArray() + aNames
.getLength();
155 ::utl::OConfigurationNode aNodeForName
= m_aConfigurationRoot
.openNode( *pName
);
158 OSL_VERIFY( aNodeForName
.getNodeValue( getNameNodeName() ) >>= sTestName
);
159 if ( sTestName
== _rName
)
162 return ::utl::OConfigurationNode();
165 ::utl::OConfigurationNode
DatabaseRegistrations::impl_getNodeForName_throw_must_exist(const OUString
& _rName
)
167 ::utl::OConfigurationNode
aNodeForName( impl_getNodeForName_nothrow( _rName
) );
169 if (!aNodeForName
.isValid())
171 throw NoSuchElementException( _rName
, *this );
177 ::utl::OConfigurationNode
DatabaseRegistrations::impl_getNodeForName_throw_must_not_exist(const OUString
& _rName
)
179 ::utl::OConfigurationNode
aNodeForName( impl_getNodeForName_nothrow( _rName
) );
181 if (aNodeForName
.isValid())
182 throw ElementExistException( _rName
, *this );
184 OUString sNewNodeName
;
186 OUStringBuffer aNewNodeName
;
187 aNewNodeName
.append( "org.openoffice." );
188 aNewNodeName
.append( _rName
);
191 OUStringBuffer
aReset( aNewNodeName
);
192 sNewNodeName
= aNewNodeName
.makeStringAndClear();
194 while ( m_aConfigurationRoot
.hasByName( sNewNodeName
) )
196 aNewNodeName
= aReset
;
197 aNewNodeName
.append( " " );
198 aNewNodeName
.append( i
);
199 sNewNodeName
= aNewNodeName
.makeStringAndClear();
203 ::utl::OConfigurationNode
aNewNode( m_aConfigurationRoot
.createNode( sNewNodeName
) );
204 aNewNode
.setNodeValue( getNameNodeName(), makeAny( _rName
) );
208 void DatabaseRegistrations::impl_checkValidName_common(const OUString
& _rName
)
210 if ( !m_aConfigurationRoot
.isValid() )
211 throw RuntimeException( OUString(), *this );
213 if ( _rName
.isEmpty() )
214 throw IllegalArgumentException( OUString(), *this, 1 );
217 ::utl::OConfigurationNode
DatabaseRegistrations::impl_checkValidName_throw_must_exist(const OUString
& _rName
)
219 impl_checkValidName_common(_rName
);
220 return impl_getNodeForName_throw_must_exist(_rName
);
223 ::utl::OConfigurationNode
DatabaseRegistrations::impl_checkValidName_throw_must_not_exist(const OUString
& _rName
)
225 impl_checkValidName_common(_rName
);
226 return impl_getNodeForName_throw_must_not_exist(_rName
);
229 void DatabaseRegistrations::impl_checkValidLocation_throw( const OUString
& _rLocation
)
231 if ( _rLocation
.isEmpty() )
232 throw IllegalArgumentException( OUString(), *this, 2 );
234 INetURLObject
aURL( _rLocation
);
235 if ( aURL
.GetProtocol() == INetProtocol::NotValid
)
236 throw IllegalArgumentException( OUString(), *this, 2 );
239 sal_Bool SAL_CALL
DatabaseRegistrations::hasRegisteredDatabase( const OUString
& Name
) throw (IllegalArgumentException
, RuntimeException
, std::exception
)
241 ::osl::MutexGuard
aGuard( m_aMutex
);
242 ::utl::OConfigurationNode aNodeForName
= impl_getNodeForName_nothrow( Name
);
243 return aNodeForName
.isValid();
246 Sequence
< OUString
> SAL_CALL
DatabaseRegistrations::getRegistrationNames() throw (RuntimeException
, std::exception
)
248 ::osl::MutexGuard
aGuard( m_aMutex
);
249 if ( !m_aConfigurationRoot
.isValid() )
250 throw RuntimeException( OUString(), *this );
252 Sequence
< OUString
> aProgrammaticNames( m_aConfigurationRoot
.getNodeNames() );
253 Sequence
< OUString
> aDisplayNames( aProgrammaticNames
.getLength() );
254 OUString
* pDisplayName
= aDisplayNames
.getArray();
256 for ( const OUString
* pName
= aProgrammaticNames
.getConstArray();
257 pName
!= aProgrammaticNames
.getConstArray() + aProgrammaticNames
.getLength();
258 ++pName
, ++pDisplayName
261 ::utl::OConfigurationNode aRegistrationNode
= m_aConfigurationRoot
.openNode( *pName
);
262 OSL_VERIFY( aRegistrationNode
.getNodeValue( getNameNodeName() ) >>= *pDisplayName
);
265 return aDisplayNames
;
268 OUString SAL_CALL
DatabaseRegistrations::getDatabaseLocation( const OUString
& Name
) throw (IllegalArgumentException
, NoSuchElementException
, RuntimeException
, std::exception
)
270 ::osl::MutexGuard
aGuard( m_aMutex
);
272 ::utl::OConfigurationNode aNodeForName
= impl_checkValidName_throw_must_exist(Name
);
275 OSL_VERIFY( aNodeForName
.getNodeValue( getLocationNodeName() ) >>= sLocation
);
276 sLocation
= SvtPathOptions().SubstituteVariable( sLocation
);
281 void SAL_CALL
DatabaseRegistrations::registerDatabaseLocation( const OUString
& Name
, const OUString
& Location
) throw (IllegalArgumentException
, ElementExistException
, RuntimeException
, std::exception
)
283 ::osl::ClearableMutexGuard
aGuard( m_aMutex
);
286 impl_checkValidLocation_throw( Location
);
287 ::utl::OConfigurationNode aDataSourceRegistration
= impl_checkValidName_throw_must_not_exist(Name
);
290 aDataSourceRegistration
.setNodeValue( getLocationNodeName(), makeAny( Location
) );
291 m_aConfigurationRoot
.commit();
294 DatabaseRegistrationEvent
aEvent( *this, Name
, OUString(), Location
);
296 m_aRegistrationListeners
.notifyEach( &XDatabaseRegistrationsListener::registeredDatabaseLocation
, aEvent
);
299 void SAL_CALL
DatabaseRegistrations::revokeDatabaseLocation( const OUString
& Name
) throw (IllegalArgumentException
, NoSuchElementException
, IllegalAccessException
, RuntimeException
, std::exception
)
301 ::osl::ClearableMutexGuard
aGuard( m_aMutex
);
304 ::utl::OConfigurationNode aNodeForName
= impl_checkValidName_throw_must_exist(Name
);
306 // obtain properties for notification
308 OSL_VERIFY( aNodeForName
.getNodeValue( getLocationNodeName() ) >>= sLocation
);
311 if ( aNodeForName
.isReadonly()
312 || !m_aConfigurationRoot
.removeNode( aNodeForName
.getLocalName() )
314 throw IllegalAccessException( OUString(), *this );
316 m_aConfigurationRoot
.commit();
319 DatabaseRegistrationEvent
aEvent( *this, Name
, sLocation
, OUString() );
321 m_aRegistrationListeners
.notifyEach( &XDatabaseRegistrationsListener::revokedDatabaseLocation
, aEvent
);
324 void SAL_CALL
DatabaseRegistrations::changeDatabaseLocation( const OUString
& Name
, const OUString
& NewLocation
) throw (IllegalArgumentException
, NoSuchElementException
, IllegalAccessException
, RuntimeException
, std::exception
)
326 ::osl::ClearableMutexGuard
aGuard( m_aMutex
);
329 impl_checkValidLocation_throw( NewLocation
);
330 ::utl::OConfigurationNode aDataSourceRegistration
= impl_checkValidName_throw_must_exist(Name
);
332 if ( aDataSourceRegistration
.isReadonly() )
333 throw IllegalAccessException( OUString(), *this );
335 // obtain properties for notification
336 OUString sOldLocation
;
337 OSL_VERIFY( aDataSourceRegistration
.getNodeValue( getLocationNodeName() ) >>= sOldLocation
);
340 aDataSourceRegistration
.setNodeValue( getLocationNodeName(), makeAny( NewLocation
) );
341 m_aConfigurationRoot
.commit();
344 DatabaseRegistrationEvent
aEvent( *this, Name
, sOldLocation
, NewLocation
);
346 m_aRegistrationListeners
.notifyEach( &XDatabaseRegistrationsListener::changedDatabaseLocation
, aEvent
);
349 sal_Bool SAL_CALL
DatabaseRegistrations::isDatabaseRegistrationReadOnly( const OUString
& Name
) throw (IllegalArgumentException
, NoSuchElementException
, RuntimeException
, std::exception
)
351 ::osl::MutexGuard
aGuard( m_aMutex
);
352 ::utl::OConfigurationNode aDataSourceRegistration
= impl_checkValidName_throw_must_exist(Name
);
353 return aDataSourceRegistration
.isReadonly();
356 void SAL_CALL
DatabaseRegistrations::addDatabaseRegistrationsListener( const Reference
< XDatabaseRegistrationsListener
>& Listener
) throw (RuntimeException
, std::exception
)
359 m_aRegistrationListeners
.addInterface( Listener
);
362 void SAL_CALL
DatabaseRegistrations::removeDatabaseRegistrationsListener( const Reference
< XDatabaseRegistrationsListener
>& Listener
) throw (RuntimeException
, std::exception
)
365 m_aRegistrationListeners
.removeInterface( Listener
);
368 // DatabaseRegistrations - factory
369 Reference
< XAggregation
> createDataSourceRegistrations( const Reference
<XComponentContext
> & _rxContext
)
371 return new DatabaseRegistrations( _rxContext
);
374 } // namespace dbaccess
376 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */