build fix: no comphelper/profilezone.hxx in this branch
[LibreOffice.git] / dbaccess / source / core / dataaccess / databaseregistrations.cxx
blob85f656b1a28f5e364e5ed58ee1995122efeb495e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
32 namespace dbaccess
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
69 public:
70 explicit DatabaseRegistrations( const Reference<XComponentContext>& _rxContext );
72 protected:
73 virtual ~DatabaseRegistrations() override;
75 public:
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;
86 private:
87 void
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);
127 private:
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();
152 ++pName
155 ::utl::OConfigurationNode aNodeForName = m_aConfigurationRoot.openNode( *pName );
157 OUString sTestName;
158 OSL_VERIFY( aNodeForName.getNodeValue( getNameNodeName() ) >>= sTestName );
159 if ( sTestName == _rName )
160 return aNodeForName;
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 );
174 return aNodeForName;
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 );
190 // make unique
191 OUStringBuffer aReset( aNewNodeName );
192 sNewNodeName = aNewNodeName.makeStringAndClear();
193 sal_Int32 i=2;
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 ) );
205 return aNewNode;
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);
274 OUString sLocation;
275 OSL_VERIFY( aNodeForName.getNodeValue( getLocationNodeName() ) >>= sLocation );
276 sLocation = SvtPathOptions().SubstituteVariable( sLocation );
278 return 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 );
285 // check
286 impl_checkValidLocation_throw( Location );
287 ::utl::OConfigurationNode aDataSourceRegistration = impl_checkValidName_throw_must_not_exist(Name);
289 // register
290 aDataSourceRegistration.setNodeValue( getLocationNodeName(), makeAny( Location ) );
291 m_aConfigurationRoot.commit();
293 // notify
294 DatabaseRegistrationEvent aEvent( *this, Name, OUString(), Location );
295 aGuard.clear();
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 );
303 // check
304 ::utl::OConfigurationNode aNodeForName = impl_checkValidName_throw_must_exist(Name);
306 // obtain properties for notification
307 OUString sLocation;
308 OSL_VERIFY( aNodeForName.getNodeValue( getLocationNodeName() ) >>= sLocation );
310 // revoke
311 if ( aNodeForName.isReadonly()
312 || !m_aConfigurationRoot.removeNode( aNodeForName.getLocalName() )
314 throw IllegalAccessException( OUString(), *this );
316 m_aConfigurationRoot.commit();
318 // notify
319 DatabaseRegistrationEvent aEvent( *this, Name, sLocation, OUString() );
320 aGuard.clear();
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 );
328 // check
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 );
339 // change
340 aDataSourceRegistration.setNodeValue( getLocationNodeName(), makeAny( NewLocation ) );
341 m_aConfigurationRoot.commit();
343 // notify
344 DatabaseRegistrationEvent aEvent( *this, Name, sOldLocation, NewLocation );
345 aGuard.clear();
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)
358 if ( Listener.is() )
359 m_aRegistrationListeners.addInterface( Listener );
362 void SAL_CALL DatabaseRegistrations::removeDatabaseRegistrationsListener( const Reference< XDatabaseRegistrationsListener >& Listener ) throw (RuntimeException, std::exception)
364 if ( Listener.is() )
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: */