Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
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/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
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 .
18 : : */
19 : :
20 : :
21 : : #include <com/sun/star/sdb/XDatabaseRegistrations.hpp>
22 : :
23 : : #include <comphelper/componentcontext.hxx>
24 : : #include <cppuhelper/basemutex.hxx>
25 : : #include <cppuhelper/interfacecontainer.hxx>
26 : : #include <cppuhelper/implbase1.hxx>
27 : : #include <rtl/ustrbuf.hxx>
28 : : #include <unotools/pathoptions.hxx>
29 : : #include <tools/urlobj.hxx>
30 : : #include <unotools/confignode.hxx>
31 : :
32 : : namespace dbaccess
33 : : {
34 : : /** === begin UNO using === **/
35 : : using ::com::sun::star::uno::Reference;
36 : : using ::com::sun::star::uno::XInterface;
37 : : using ::com::sun::star::uno::UNO_QUERY;
38 : : using ::com::sun::star::uno::UNO_QUERY_THROW;
39 : : using ::com::sun::star::uno::UNO_SET_THROW;
40 : : using ::com::sun::star::uno::Exception;
41 : : using ::com::sun::star::uno::RuntimeException;
42 : : using ::com::sun::star::uno::Any;
43 : : using ::com::sun::star::uno::makeAny;
44 : : using ::com::sun::star::uno::Sequence;
45 : : using ::com::sun::star::uno::Type;
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;
54 : : /** === end UNO using === **/
55 : :
56 : 9 : static const ::rtl::OUString& getConfigurationRootPath()
57 : : {
58 [ + - ][ + - ]: 9 : static ::rtl::OUString s_sNodeName(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Office.DataAccess/RegisteredNames"));
[ + - ][ # # ]
59 : 9 : return s_sNodeName;
60 : : }
61 : :
62 : 630 : const ::rtl::OUString& getLocationNodeName()
63 : : {
64 [ + + ][ + - ]: 630 : static ::rtl::OUString s_sNodeName(RTL_CONSTASCII_USTRINGPARAM("Location"));
[ + - ][ # # ]
65 : 630 : return s_sNodeName;
66 : : }
67 : :
68 : 1280 : const ::rtl::OUString& getNameNodeName()
69 : : {
70 [ + + ][ + - ]: 1280 : static ::rtl::OUString s_sNodeName(RTL_CONSTASCII_USTRINGPARAM("Name"));
[ + - ][ # # ]
71 : 1280 : return s_sNodeName;
72 : : }
73 : :
74 : : //====================================================================
75 : : //= DatabaseRegistrations - declaration
76 : : //====================================================================
77 : : typedef ::cppu::WeakAggImplHelper1 < XDatabaseRegistrations
78 : : > DatabaseRegistrations_Base;
79 : : class DatabaseRegistrations :public ::cppu::BaseMutex
80 : : ,public DatabaseRegistrations_Base
81 : : {
82 : : public:
83 : : DatabaseRegistrations( const ::comphelper::ComponentContext& _rxContext );
84 : :
85 : : protected:
86 : : ~DatabaseRegistrations();
87 : :
88 : : public:
89 : : virtual ::sal_Bool SAL_CALL hasRegisteredDatabase( const ::rtl::OUString& _Name ) throw (IllegalArgumentException, RuntimeException);
90 : : virtual Sequence< ::rtl::OUString > SAL_CALL getRegistrationNames() throw (RuntimeException);
91 : : virtual ::rtl::OUString SAL_CALL getDatabaseLocation( const ::rtl::OUString& _Name ) throw (IllegalArgumentException, NoSuchElementException, RuntimeException);
92 : : virtual void SAL_CALL registerDatabaseLocation( const ::rtl::OUString& _Name, const ::rtl::OUString& _Location ) throw (IllegalArgumentException, ElementExistException, RuntimeException);
93 : : virtual void SAL_CALL revokeDatabaseLocation( const ::rtl::OUString& _Name ) throw (IllegalArgumentException, NoSuchElementException, IllegalAccessException, RuntimeException);
94 : : virtual void SAL_CALL changeDatabaseLocation( const ::rtl::OUString& Name, const ::rtl::OUString& NewLocation ) throw (IllegalArgumentException, NoSuchElementException, IllegalAccessException, RuntimeException);
95 : : virtual ::sal_Bool SAL_CALL isDatabaseRegistrationReadOnly( const ::rtl::OUString& _Name ) throw (IllegalArgumentException, NoSuchElementException, RuntimeException);
96 : : virtual void SAL_CALL addDatabaseRegistrationsListener( const Reference< XDatabaseRegistrationsListener >& Listener ) throw (RuntimeException);
97 : : virtual void SAL_CALL removeDatabaseRegistrationsListener( const Reference< XDatabaseRegistrationsListener >& Listener ) throw (RuntimeException);
98 : :
99 : : private:
100 : : ::utl::OConfigurationNode
101 : : impl_checkValidName_throw( const ::rtl::OUString& _rName, const bool _bMustExist );
102 : :
103 : : void impl_checkValidLocation_throw( const ::rtl::OUString& _rLocation );
104 : :
105 : : /** retrieves the configuration node whose "Name" sub node has the given value
106 : :
107 : : Since we separated the name of the registration node from the "Name" value of the registration, we cannot
108 : : simply do a "getByName" (equivalent) when we want to retrieve the node for a given registration name.
109 : : Instead, we must search all nodes.
110 : :
111 : : If _bMustExist is <TRUE/>, and a node with the given display name does not exist, then a NoSuchElementException
112 : : is thrown.
113 : :
114 : : If _bMustExist is <FALSE/>, and a node with the given name already exists, then a ElementExistException is
115 : : thrown.
116 : :
117 : : In either case, if no exception is thrown, then a valid node is returned: If the node existed and was allowed
118 : : to exist, it is returned, if the node did not yet exist, and was required to not exist, a new node is created.
119 : : However, in this case the root node is not yet committed.
120 : : */
121 : : ::utl::OConfigurationNode
122 : : impl_getNodeForName_throw( const ::rtl::OUString& _rName, const bool _bMustExist );
123 : :
124 : : ::utl::OConfigurationNode
125 : : impl_getNodeForName_nothrow( const ::rtl::OUString& _rName );
126 : :
127 : : private:
128 : : ::comphelper::ComponentContext m_aContext;
129 : : ::utl::OConfigurationTreeRoot m_aConfigurationRoot;
130 : : ::cppu::OInterfaceContainerHelper m_aRegistrationListeners;
131 : : };
132 : :
133 : : //====================================================================
134 : : //= DatabaseRegistrations - implementation
135 : : //====================================================================
136 : 9 : DatabaseRegistrations::DatabaseRegistrations( const ::comphelper::ComponentContext& _rxContext )
137 : : :m_aContext( _rxContext )
138 : : ,m_aConfigurationRoot()
139 [ + - ][ + - ]: 9 : ,m_aRegistrationListeners( m_aMutex )
[ + - ][ + - ]
140 : : {
141 : : m_aConfigurationRoot = ::utl::OConfigurationTreeRoot::createWithServiceFactory(
142 [ + - ][ + - ]: 9 : m_aContext.getLegacyServiceFactory(), getConfigurationRootPath(), -1, ::utl::OConfigurationTreeRoot::CM_UPDATABLE );
[ + - ][ + - ]
[ + - ]
143 : 9 : }
144 : :
145 [ + - ][ + - ]: 9 : DatabaseRegistrations::~DatabaseRegistrations()
[ + - ][ + - ]
146 : : {
147 [ - + ]: 18 : }
148 : :
149 : 924 : ::utl::OConfigurationNode DatabaseRegistrations::impl_getNodeForName_nothrow( const ::rtl::OUString& _rName )
150 : : {
151 : 924 : Sequence< ::rtl::OUString > aNames( m_aConfigurationRoot.getNodeNames() );
152 [ + + ]: 3478 : for ( const ::rtl::OUString* pName = aNames.getConstArray();
153 : 1456 : pName != aNames.getConstArray() + aNames.getLength();
154 : : ++pName
155 : : )
156 : : {
157 : 1098 : ::utl::OConfigurationNode aNodeForName = m_aConfigurationRoot.openNode( *pName );
158 : :
159 : 1098 : ::rtl::OUString sTestName;
160 [ + - ]: 1098 : OSL_VERIFY( aNodeForName.getNodeValue( getNameNodeName() ) >>= sTestName );
161 [ + + ]: 1098 : if ( sTestName == _rName )
162 [ + - ]: 1098 : return aNodeForName;
163 [ + + ][ + - ]: 1098 : }
[ + + ]
164 [ + - ][ + - ]: 924 : return ::utl::OConfigurationNode();
165 : : }
166 : :
167 : 810 : ::utl::OConfigurationNode DatabaseRegistrations::impl_getNodeForName_throw( const ::rtl::OUString& _rName, const bool _bMustExist )
168 : : {
169 [ + - ]: 810 : ::utl::OConfigurationNode aNodeForName( impl_getNodeForName_nothrow( _rName ) );
170 : :
171 [ + + ]: 810 : if ( aNodeForName.isValid() )
172 : : {
173 [ - + ]: 456 : if ( !_bMustExist )
174 [ # # ][ # # ]: 0 : throw ElementExistException( _rName, *this );
175 : :
176 [ + - ]: 456 : return aNodeForName;
177 : : }
178 : :
179 [ + + ]: 354 : if ( _bMustExist )
180 [ + - ][ + - ]: 180 : throw NoSuchElementException( _rName, *this );
181 : :
182 : 174 : ::rtl::OUString sNewNodeName;
183 : : {
184 : 174 : ::rtl::OUStringBuffer aNewNodeName;
185 [ + - ]: 174 : aNewNodeName.appendAscii( "org.openoffice." );
186 [ + - ]: 174 : aNewNodeName.append( _rName );
187 : :
188 : : // make unique
189 [ + - ]: 174 : ::rtl::OUStringBuffer aReset( aNewNodeName );
190 [ + - ]: 174 : sNewNodeName = aNewNodeName.makeStringAndClear();
191 : 174 : sal_Int32 i=2;
192 [ - + ]: 174 : while ( m_aConfigurationRoot.hasByName( sNewNodeName ) )
193 : : {
194 [ # # ]: 0 : aNewNodeName = aReset;
195 [ # # ]: 0 : aNewNodeName.appendAscii( " " );
196 [ # # ]: 0 : aNewNodeName.append( i );
197 [ # # ]: 0 : sNewNodeName = aNewNodeName.makeStringAndClear();
198 : 174 : }
199 : : }
200 : :
201 : 174 : ::utl::OConfigurationNode aNewNode( m_aConfigurationRoot.createNode( sNewNodeName ) );
202 [ + - ][ + - ]: 174 : aNewNode.setNodeValue( getNameNodeName(), makeAny( _rName ) );
203 [ + - ][ + - ]: 810 : return aNewNode;
[ + - ]
204 : : }
205 : :
206 : 810 : ::utl::OConfigurationNode DatabaseRegistrations::impl_checkValidName_throw( const ::rtl::OUString& _rName, const bool _bMustExist )
207 : : {
208 [ - + ]: 810 : if ( !m_aConfigurationRoot.isValid() )
209 [ # # ][ # # ]: 0 : throw RuntimeException( ::rtl::OUString(), *this );
210 : :
211 [ - + ]: 810 : if ( _rName.isEmpty() )
212 [ # # ][ # # ]: 0 : throw IllegalArgumentException( ::rtl::OUString(), *this, 1 );
213 : :
214 : 810 : return impl_getNodeForName_throw( _rName, _bMustExist );
215 : : }
216 : :
217 : 174 : void DatabaseRegistrations::impl_checkValidLocation_throw( const ::rtl::OUString& _rLocation )
218 : : {
219 [ - + ]: 174 : if ( _rLocation.isEmpty() )
220 [ # # ][ # # ]: 0 : throw IllegalArgumentException( ::rtl::OUString(), *this, 2 );
221 : :
222 [ + - ]: 174 : INetURLObject aURL( _rLocation );
223 [ - + ]: 174 : if ( aURL.GetProtocol() == INET_PROT_NOT_VALID )
224 [ # # ][ # # ]: 174 : throw IllegalArgumentException( ::rtl::OUString(), *this, 2 );
[ + - ]
225 : 174 : }
226 : :
227 : 114 : ::sal_Bool SAL_CALL DatabaseRegistrations::hasRegisteredDatabase( const ::rtl::OUString& _Name ) throw (IllegalArgumentException, RuntimeException)
228 : : {
229 [ + - ]: 114 : ::osl::MutexGuard aGuard( m_aMutex );
230 [ + - ]: 114 : ::utl::OConfigurationNode aNodeForName = impl_getNodeForName_nothrow( _Name );
231 [ + - ][ + - ]: 114 : return aNodeForName.isValid();
232 : : }
233 : :
234 : 8 : Sequence< ::rtl::OUString > SAL_CALL DatabaseRegistrations::getRegistrationNames() throw (RuntimeException)
235 : : {
236 [ + - ]: 8 : ::osl::MutexGuard aGuard( m_aMutex );
237 [ - + ]: 8 : if ( !m_aConfigurationRoot.isValid() )
238 [ # # ][ # # ]: 0 : throw RuntimeException( ::rtl::OUString(), *this );
239 : :
240 : 8 : Sequence< ::rtl::OUString > aProgrammaticNames( m_aConfigurationRoot.getNodeNames() );
241 [ + - ]: 8 : Sequence< ::rtl::OUString > aDisplayNames( aProgrammaticNames.getLength() );
242 [ + - ]: 8 : ::rtl::OUString* pDisplayName = aDisplayNames.getArray();
243 : :
244 [ + + ]: 32 : for ( const ::rtl::OUString* pName = aProgrammaticNames.getConstArray();
245 : 16 : pName != aProgrammaticNames.getConstArray() + aProgrammaticNames.getLength();
246 : : ++pName, ++pDisplayName
247 : : )
248 : : {
249 : 8 : ::utl::OConfigurationNode aRegistrationNode = m_aConfigurationRoot.openNode( *pName );
250 [ + - ]: 8 : OSL_VERIFY( aRegistrationNode.getNodeValue( getNameNodeName() ) >>= *pDisplayName );
251 [ + - ]: 8 : }
252 : :
253 [ + - ][ + - ]: 8 : return aDisplayNames;
254 : : }
255 : :
256 : 464 : ::rtl::OUString SAL_CALL DatabaseRegistrations::getDatabaseLocation( const ::rtl::OUString& _Name ) throw (IllegalArgumentException, NoSuchElementException, RuntimeException)
257 : : {
258 [ + - ]: 464 : ::osl::MutexGuard aGuard( m_aMutex );
259 : :
260 [ + + ]: 464 : ::utl::OConfigurationNode aNodeForName = impl_checkValidName_throw( _Name, true );
261 : :
262 : 284 : ::rtl::OUString sLocation;
263 [ + - ]: 284 : OSL_VERIFY( aNodeForName.getNodeValue( getLocationNodeName() ) >>= sLocation );
264 [ + - ][ + - ]: 284 : sLocation = SvtPathOptions().SubstituteVariable( sLocation );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
265 : :
266 [ + - ][ + - ]: 464 : return sLocation;
267 : : }
268 : :
269 : 174 : void SAL_CALL DatabaseRegistrations::registerDatabaseLocation( const ::rtl::OUString& _Name, const ::rtl::OUString& _Location ) throw (IllegalArgumentException, ElementExistException, RuntimeException)
270 : : {
271 [ + - ]: 174 : ::osl::ClearableMutexGuard aGuard( m_aMutex );
272 : :
273 : : // check
274 [ + - ]: 174 : impl_checkValidLocation_throw( _Location );
275 [ + - ]: 174 : ::utl::OConfigurationNode aDataSourceRegistration = impl_checkValidName_throw( _Name, false );
276 : :
277 : : // register
278 [ + - ][ + - ]: 174 : aDataSourceRegistration.setNodeValue( getLocationNodeName(), makeAny( _Location ) );
279 : 174 : m_aConfigurationRoot.commit();
280 : :
281 : : // notify
282 [ + - ][ + - ]: 174 : DatabaseRegistrationEvent aEvent( *this, _Name, ::rtl::OUString(), _Location );
283 [ + - ]: 174 : aGuard.clear();
284 [ + - ][ + - ]: 174 : m_aRegistrationListeners.notifyEach( &XDatabaseRegistrationsListener::registeredDatabaseLocation, aEvent );
[ + - ][ + - ]
285 : 174 : }
286 : :
287 : 172 : void SAL_CALL DatabaseRegistrations::revokeDatabaseLocation( const ::rtl::OUString& _Name ) throw (IllegalArgumentException, NoSuchElementException, IllegalAccessException, RuntimeException)
288 : : {
289 [ + - ]: 172 : ::osl::ClearableMutexGuard aGuard( m_aMutex );
290 : :
291 : : // check
292 [ + - ]: 172 : ::utl::OConfigurationNode aNodeForName = impl_checkValidName_throw( _Name, true );
293 : :
294 : : // obtain properties for notification
295 : 172 : ::rtl::OUString sLocation;
296 [ + - ]: 172 : OSL_VERIFY( aNodeForName.getNodeValue( getLocationNodeName() ) >>= sLocation );
297 : :
298 : : // revoke
299 [ - + ]: 516 : if ( aNodeForName.isReadonly()
[ + - - + ]
300 [ + - ][ + - ]: 344 : || !m_aConfigurationRoot.removeNode( aNodeForName.getLocalName() )
[ # # ]
301 : : )
302 [ # # ][ # # ]: 0 : throw IllegalAccessException( ::rtl::OUString(), *this );
303 : :
304 : 172 : m_aConfigurationRoot.commit();
305 : :
306 : : // notify
307 [ + - ][ + - ]: 172 : DatabaseRegistrationEvent aEvent( *this, _Name, sLocation, ::rtl::OUString() );
308 [ + - ]: 172 : aGuard.clear();
309 [ + - ][ + - ]: 172 : m_aRegistrationListeners.notifyEach( &XDatabaseRegistrationsListener::revokedDatabaseLocation, aEvent );
[ + - ][ + - ]
310 : 172 : }
311 : :
312 : 0 : void SAL_CALL DatabaseRegistrations::changeDatabaseLocation( const ::rtl::OUString& _Name, const ::rtl::OUString& _NewLocation ) throw (IllegalArgumentException, NoSuchElementException, IllegalAccessException, RuntimeException)
313 : : {
314 [ # # ]: 0 : ::osl::ClearableMutexGuard aGuard( m_aMutex );
315 : :
316 : : // check
317 [ # # ]: 0 : impl_checkValidLocation_throw( _NewLocation );
318 [ # # ]: 0 : ::utl::OConfigurationNode aDataSourceRegistration = impl_checkValidName_throw( _Name, true );
319 : :
320 [ # # ]: 0 : if ( aDataSourceRegistration.isReadonly() )
321 [ # # ][ # # ]: 0 : throw IllegalAccessException( ::rtl::OUString(), *this );
322 : :
323 : : // obtain properties for notification
324 : 0 : ::rtl::OUString sOldLocation;
325 [ # # ]: 0 : OSL_VERIFY( aDataSourceRegistration.getNodeValue( getLocationNodeName() ) >>= sOldLocation );
326 : :
327 : : // change
328 [ # # ][ # # ]: 0 : aDataSourceRegistration.setNodeValue( getLocationNodeName(), makeAny( _NewLocation ) );
329 : 0 : m_aConfigurationRoot.commit();
330 : :
331 : : // notify
332 [ # # ][ # # ]: 0 : DatabaseRegistrationEvent aEvent( *this, _Name, sOldLocation, _NewLocation );
333 [ # # ]: 0 : aGuard.clear();
334 [ # # ][ # # ]: 0 : m_aRegistrationListeners.notifyEach( &XDatabaseRegistrationsListener::changedDatabaseLocation, aEvent );
[ # # ][ # # ]
335 : 0 : }
336 : :
337 : 0 : ::sal_Bool SAL_CALL DatabaseRegistrations::isDatabaseRegistrationReadOnly( const ::rtl::OUString& _Name ) throw (IllegalArgumentException, NoSuchElementException, RuntimeException)
338 : : {
339 [ # # ]: 0 : ::osl::MutexGuard aGuard( m_aMutex );
340 [ # # ]: 0 : ::utl::OConfigurationNode aDataSourceRegistration = impl_checkValidName_throw( _Name, true );
341 [ # # ][ # # ]: 0 : return aDataSourceRegistration.isReadonly();
342 : : }
343 : :
344 : 2 : void SAL_CALL DatabaseRegistrations::addDatabaseRegistrationsListener( const Reference< XDatabaseRegistrationsListener >& _Listener ) throw (RuntimeException)
345 : : {
346 [ + - ]: 2 : if ( _Listener.is() )
347 : 2 : m_aRegistrationListeners.addInterface( _Listener );
348 : 2 : }
349 : :
350 : 2 : void SAL_CALL DatabaseRegistrations::removeDatabaseRegistrationsListener( const Reference< XDatabaseRegistrationsListener >& _Listener ) throw (RuntimeException)
351 : : {
352 [ + - ]: 2 : if ( _Listener.is() )
353 : 2 : m_aRegistrationListeners.removeInterface( _Listener );
354 : 2 : }
355 : :
356 : : //====================================================================
357 : : //= DatabaseRegistrations - factory
358 : : //====================================================================
359 : 9 : Reference< XAggregation > createDataSourceRegistrations( const ::comphelper::ComponentContext& _rxContext )
360 : : {
361 [ + - ][ + - ]: 9 : return new DatabaseRegistrations( _rxContext );
362 : : }
363 : :
364 : : } // namespace dbaccess
365 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|