Bump version to 5.0-14
[LibreOffice.git] / dbaccess / source / core / dataaccess / databaseregistrations.cxx
blobb5f3682d93081a87180d97054bfa0400b564650c
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 <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>
32 namespace dbaccess
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
76 public:
77 DatabaseRegistrations( const Reference<XComponentContext>& _rxContext );
79 protected:
80 virtual ~DatabaseRegistrations();
82 public:
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;
93 private:
94 void
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);
134 private:
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();
159 ++pName
162 ::utl::OConfigurationNode aNodeForName = m_aConfigurationRoot.openNode( *pName );
164 OUString sTestName;
165 OSL_VERIFY( aNodeForName.getNodeValue( getNameNodeName() ) >>= sTestName );
166 if ( sTestName == _rName )
167 return aNodeForName;
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 );
181 return aNodeForName;
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 );
197 // make unique
198 OUStringBuffer aReset( aNewNodeName );
199 sNewNodeName = aNewNodeName.makeStringAndClear();
200 sal_Int32 i=2;
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 ) );
212 return aNewNode;
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);
281 OUString sLocation;
282 OSL_VERIFY( aNodeForName.getNodeValue( getLocationNodeName() ) >>= sLocation );
283 sLocation = SvtPathOptions().SubstituteVariable( sLocation );
285 return 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 );
292 // check
293 impl_checkValidLocation_throw( _Location );
294 ::utl::OConfigurationNode aDataSourceRegistration = impl_checkValidName_throw_must_not_exist(_Name);
296 // register
297 aDataSourceRegistration.setNodeValue( getLocationNodeName(), makeAny( _Location ) );
298 m_aConfigurationRoot.commit();
300 // notify
301 DatabaseRegistrationEvent aEvent( *this, _Name, OUString(), _Location );
302 aGuard.clear();
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 );
310 // check
311 ::utl::OConfigurationNode aNodeForName = impl_checkValidName_throw_must_exist(_Name);
313 // obtain properties for notification
314 OUString sLocation;
315 OSL_VERIFY( aNodeForName.getNodeValue( getLocationNodeName() ) >>= sLocation );
317 // revoke
318 if ( aNodeForName.isReadonly()
319 || !m_aConfigurationRoot.removeNode( aNodeForName.getLocalName() )
321 throw IllegalAccessException( OUString(), *this );
323 m_aConfigurationRoot.commit();
325 // notify
326 DatabaseRegistrationEvent aEvent( *this, _Name, sLocation, OUString() );
327 aGuard.clear();
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 );
335 // check
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 );
346 // change
347 aDataSourceRegistration.setNodeValue( getLocationNodeName(), makeAny( _NewLocation ) );
348 m_aConfigurationRoot.commit();
350 // notify
351 DatabaseRegistrationEvent aEvent( *this, _Name, sOldLocation, _NewLocation );
352 aGuard.clear();
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: */