Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : /*
30 : : * This file pinched from webdavdatasupplier (etc.)
31 : : * cut & paste + new getData impl. & collate ResultSet code.
32 : : */
33 : : #include <vector>
34 : : #include <osl/diagnose.h>
35 : : #include <com/sun/star/ucb/OpenMode.hpp>
36 : : #include <ucbhelper/contentidentifier.hxx>
37 : : #include <ucbhelper/providerhelper.hxx>
38 : :
39 : : #include "gvfs_directory.hxx"
40 : :
41 : : #include <libgnomevfs/gnome-vfs-utils.h>
42 : : #include <libgnomevfs/gnome-vfs-directory.h>
43 : :
44 : : using namespace com::sun::star;
45 : : using namespace gvfs;
46 : :
47 : : // DynamicResultSet Implementation.
48 : :
49 : 0 : DynamicResultSet::DynamicResultSet(
50 : : const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
51 : : const rtl::Reference< Content >& rxContent,
52 : : const ucb::OpenCommandArgument2& rCommand,
53 : : const uno::Reference< ucb::XCommandEnvironment >& rxEnv )
54 : : : ResultSetImplHelper( rxSMgr, rCommand ),
55 : : m_xContent( rxContent ),
56 : 0 : m_xEnv( rxEnv )
57 : : {
58 : 0 : }
59 : 0 : void DynamicResultSet::initStatic()
60 : : {
61 : : m_xResultSet1
62 : : = new ::ucbhelper::ResultSet( m_xSMgr,
63 : : m_aCommand.Properties,
64 : : new DataSupplier( m_xSMgr,
65 : : m_xContent,
66 : 0 : m_aCommand.Mode ),
67 : 0 : m_xEnv );
68 : 0 : }
69 : 0 : void DynamicResultSet::initDynamic()
70 : : {
71 : 0 : initStatic();
72 : 0 : m_xResultSet2 = m_xResultSet1;
73 : 0 : }
74 : :
75 : : //=========================================================================
76 : :
77 : :
78 : : // DataSupplier Implementation.
79 : :
80 : :
81 : :
82 : : struct ResultListEntry
83 : : {
84 : : rtl::OUString aId;
85 : : uno::Reference< ucb::XContentIdentifier > xId;
86 : : uno::Reference< ucb::XContent > xContent;
87 : : uno::Reference< sdbc::XRow > xRow;
88 : : GnomeVFSFileInfo aInfo;
89 : :
90 : 0 : ResultListEntry( const GnomeVFSFileInfo *fileInfo)
91 : 0 : {
92 : 0 : gnome_vfs_file_info_copy (&aInfo, fileInfo);
93 : 0 : }
94 : :
95 : 0 : ~ResultListEntry()
96 : 0 : {
97 : 0 : gnome_vfs_file_info_clear (&aInfo);
98 : 0 : }
99 : : };
100 : :
101 : : //=========================================================================
102 : : //
103 : : // ResultList.
104 : : //
105 : : //=========================================================================
106 : :
107 : : typedef std::vector< ResultListEntry* > ResultList;
108 : :
109 : : //=========================================================================
110 : : //
111 : : // struct DataSupplier_Impl.
112 : : //
113 : : //=========================================================================
114 : :
115 : : struct gvfs::DataSupplier_Impl
116 : : {
117 : : osl::Mutex m_aMutex;
118 : : ResultList m_aResults;
119 : : rtl::Reference< Content > m_xContent;
120 : : uno::Reference< lang::XMultiServiceFactory > m_xSMgr;
121 : : sal_Int32 m_nOpenMode;
122 : : sal_Bool m_bCountFinal;
123 : :
124 : 0 : DataSupplier_Impl(
125 : : const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
126 : : const rtl::Reference< Content >& rContent,
127 : : sal_Int32 nOpenMode )
128 : : : m_xContent( rContent ), m_xSMgr( rxSMgr ),
129 : 0 : m_nOpenMode( nOpenMode ), m_bCountFinal( sal_False ) {}
130 : 0 : ~DataSupplier_Impl()
131 : 0 : {
132 : 0 : ResultList::const_iterator it = m_aResults.begin();
133 : 0 : ResultList::const_iterator end = m_aResults.end();
134 : :
135 : 0 : while ( it != end )
136 : : {
137 : 0 : delete (*it);
138 : 0 : ++it;
139 : : }
140 : 0 : }
141 : : };
142 : :
143 : 0 : DataSupplier::DataSupplier(
144 : : const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
145 : : const rtl::Reference< Content >& rContent,
146 : : sal_Int32 nOpenMode )
147 : 0 : : m_pImpl( new DataSupplier_Impl( rxSMgr, rContent, nOpenMode ) )
148 : : {
149 : 0 : }
150 : :
151 : : //=========================================================================
152 : : // virtual
153 : 0 : DataSupplier::~DataSupplier()
154 : : {
155 : 0 : delete m_pImpl;
156 : 0 : }
157 : :
158 : : // virtual
159 : 0 : rtl::OUString DataSupplier::queryContentIdentifierString( sal_uInt32 nIndex )
160 : : {
161 : 0 : osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
162 : :
163 : 0 : if ( nIndex < m_pImpl->m_aResults.size() ) {
164 : 0 : rtl::OUString aId = m_pImpl->m_aResults[ nIndex ]->aId;
165 : 0 : if ( !aId.isEmpty() ) // cached
166 : 0 : return aId;
167 : : }
168 : :
169 : 0 : if ( getResult( nIndex ) ) {
170 : 0 : rtl::OUString aId = m_pImpl->m_xContent->getOUURI();
171 : :
172 : : char *escaped_name;
173 : 0 : escaped_name = gnome_vfs_escape_string( m_pImpl->m_aResults[ nIndex ]->aInfo.name );
174 : :
175 : 0 : if ( ( aId.lastIndexOf( '/' ) + 1 ) != aId.getLength() )
176 : 0 : aId += rtl::OUString("/");
177 : :
178 : 0 : aId += rtl::OUString::createFromAscii( escaped_name );
179 : :
180 : 0 : g_free( escaped_name );
181 : :
182 : 0 : m_pImpl->m_aResults[ nIndex ]->aId = aId;
183 : 0 : return aId;
184 : : }
185 : :
186 : 0 : return rtl::OUString();
187 : : }
188 : :
189 : : // virtual
190 : : uno::Reference< ucb::XContentIdentifier >
191 : 0 : DataSupplier::queryContentIdentifier( sal_uInt32 nIndex )
192 : : {
193 : 0 : osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
194 : :
195 : 0 : if ( nIndex < m_pImpl->m_aResults.size() ) {
196 : : uno::Reference< ucb::XContentIdentifier > xId
197 : 0 : = m_pImpl->m_aResults[ nIndex ]->xId;
198 : 0 : if ( xId.is() ) // Already cached.
199 : 0 : return xId;
200 : : }
201 : :
202 : 0 : rtl::OUString aId = queryContentIdentifierString( nIndex );
203 : 0 : if ( !aId.isEmpty() ) {
204 : : uno::Reference< ucb::XContentIdentifier > xId
205 : 0 : = new ::ucbhelper::ContentIdentifier( aId );
206 : 0 : m_pImpl->m_aResults[ nIndex ]->xId = xId;
207 : 0 : return xId;
208 : : }
209 : :
210 : 0 : return uno::Reference< ucb::XContentIdentifier >();
211 : : }
212 : :
213 : : // virtual
214 : : uno::Reference< ucb::XContent >
215 : 0 : DataSupplier::queryContent( sal_uInt32 nIndex )
216 : : {
217 : 0 : osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
218 : :
219 : 0 : if ( nIndex < m_pImpl->m_aResults.size() ) {
220 : : uno::Reference< ucb::XContent > xContent
221 : 0 : = m_pImpl->m_aResults[ nIndex ]->xContent;
222 : 0 : if ( xContent.is() ) // Already cached.
223 : 0 : return xContent;
224 : : }
225 : :
226 : : uno::Reference< ucb::XContentIdentifier > xId
227 : 0 : = queryContentIdentifier( nIndex );
228 : 0 : if ( xId.is() ) {
229 : : try
230 : : {
231 : : // FIXME:
232 : : // It would be really nice to propagate this information
233 : : // to the Content, but we can't then register it with the
234 : : // ContentProvider, and the ucbhelper hinders here.
235 : : uno::Reference< ucb::XContent > xContent
236 : 0 : = m_pImpl->m_xContent->getProvider()->queryContent( xId );
237 : 0 : m_pImpl->m_aResults[ nIndex ]->xContent = xContent;
238 : 0 : return xContent;
239 : :
240 : : }
241 : 0 : catch ( ucb::IllegalIdentifierException& ) {
242 : : }
243 : : }
244 : 0 : return uno::Reference< ucb::XContent >();
245 : : }
246 : :
247 : : // virtual
248 : 0 : sal_Bool DataSupplier::getResult( sal_uInt32 nIndex )
249 : : {
250 : 0 : osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
251 : :
252 : 0 : if ( m_pImpl->m_aResults.size() > nIndex ) // Result already present.
253 : 0 : return sal_True;
254 : :
255 : 0 : if ( getData() && m_pImpl->m_aResults.size() > nIndex )
256 : 0 : return sal_True;
257 : :
258 : 0 : return sal_False;
259 : : }
260 : :
261 : : // virtual
262 : 0 : sal_uInt32 DataSupplier::totalCount()
263 : : {
264 : 0 : getData();
265 : :
266 : 0 : osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
267 : :
268 : 0 : return m_pImpl->m_aResults.size();
269 : : }
270 : :
271 : : // virtual
272 : 0 : sal_uInt32 DataSupplier::currentCount()
273 : : {
274 : 0 : osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
275 : 0 : return m_pImpl->m_aResults.size();
276 : : }
277 : :
278 : : // virtual
279 : 0 : sal_Bool DataSupplier::isCountFinal()
280 : : {
281 : 0 : osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
282 : 0 : return m_pImpl->m_bCountFinal;
283 : : }
284 : :
285 : : // virtual
286 : 0 : uno::Reference< sdbc::XRow > DataSupplier::queryPropertyValues( sal_uInt32 nIndex )
287 : : {
288 : 0 : osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
289 : :
290 : 0 : if ( nIndex < m_pImpl->m_aResults.size() ) {
291 : 0 : uno::Reference< sdbc::XRow > xRow = m_pImpl->m_aResults[ nIndex ]->xRow;
292 : 0 : if ( xRow.is() ) // Already cached.
293 : 0 : return xRow;
294 : : }
295 : :
296 : 0 : if ( getResult( nIndex ) ) {
297 : : // Inefficient - but we can't create xContent's sensibly
298 : : // nor can we do the property code sensibly cleanly staticaly.
299 : 0 : Content *pContent = static_cast< ::gvfs::Content * >(queryContent( nIndex ).get());
300 : :
301 : : uno::Reference< sdbc::XRow > xRow =
302 : 0 : pContent->getPropertyValues( getResultSet()->getProperties(),
303 : 0 : getResultSet()->getEnvironment() );
304 : :
305 : 0 : m_pImpl->m_aResults[ nIndex ]->xRow = xRow;
306 : :
307 : 0 : return xRow;
308 : : }
309 : :
310 : 0 : return uno::Reference< sdbc::XRow >();
311 : : }
312 : :
313 : : // virtual
314 : 0 : void DataSupplier::releasePropertyValues( sal_uInt32 nIndex )
315 : : {
316 : 0 : osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
317 : :
318 : 0 : if ( nIndex < m_pImpl->m_aResults.size() )
319 : 0 : m_pImpl->m_aResults[ nIndex ]->xRow = uno::Reference< sdbc::XRow >();
320 : 0 : }
321 : :
322 : : // virtual
323 : 0 : void DataSupplier::close()
324 : : {
325 : 0 : }
326 : :
327 : : // virtual
328 : 0 : void DataSupplier::validate()
329 : : throw( ucb::ResultSetException )
330 : : {
331 : 0 : }
332 : :
333 : 0 : sal_Bool DataSupplier::getData()
334 : : {
335 : 0 : osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
336 : :
337 : 0 : if ( !m_pImpl->m_bCountFinal ) {
338 : : GnomeVFSResult result;
339 : 0 : GnomeVFSDirectoryHandle *dirHandle = NULL;
340 : :
341 : : {
342 : 0 : Authentication aAuth( getResultSet()->getEnvironment() );
343 : 0 : char *uri = m_pImpl->m_xContent->getURI();
344 : : result = gnome_vfs_directory_open
345 : 0 : ( &dirHandle, uri, GNOME_VFS_FILE_INFO_DEFAULT );
346 : :
347 : 0 : if (result != GNOME_VFS_OK) {
348 : : #ifdef DEBUG
349 : : g_warning ("Failed open of '%s' with '%s'",
350 : : uri, gnome_vfs_result_to_string( result ));
351 : : #endif
352 : 0 : g_free( uri );
353 : 0 : return sal_False;
354 : : }
355 : :
356 : 0 : g_free( uri );
357 : : }
358 : :
359 : 0 : GnomeVFSFileInfo* fileInfo = gnome_vfs_file_info_new ();
360 : :
361 : 0 : while ((result = gnome_vfs_directory_read_next (dirHandle, fileInfo)) == GNOME_VFS_OK) {
362 : 0 : if( fileInfo->name && fileInfo->name[0] == '.' &&
363 : 0 : ( fileInfo->name[1] == '\0' ||
364 : 0 : ( fileInfo->name[1] == '.' && fileInfo->name[2] == '\0' ) ) )
365 : 0 : continue;
366 : :
367 : 0 : switch ( m_pImpl->m_nOpenMode ) {
368 : : case ucb::OpenMode::FOLDERS:
369 : 0 : if ( !(fileInfo->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_TYPE) ||
370 : : fileInfo->type != GNOME_VFS_FILE_TYPE_DIRECTORY )
371 : 0 : continue;
372 : 0 : break;
373 : :
374 : : case ucb::OpenMode::DOCUMENTS:
375 : 0 : if ( !(fileInfo->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_TYPE) ||
376 : : fileInfo->type != GNOME_VFS_FILE_TYPE_REGULAR )
377 : 0 : continue;
378 : 0 : break;
379 : :
380 : : case ucb::OpenMode::ALL:
381 : : default:
382 : 0 : break;
383 : : }
384 : :
385 : 0 : m_pImpl->m_aResults.push_back( new ResultListEntry( fileInfo ) );
386 : : }
387 : :
388 : 0 : gnome_vfs_file_info_unref (fileInfo);
389 : :
390 : : #if OSL_DEBUG_LEVEL > 1
391 : : g_warning ("Got %d directory entries", result);
392 : : #endif
393 : :
394 : 0 : m_pImpl->m_bCountFinal = sal_True;
395 : :
396 : : // Callback possible, because listeners may be informed!
397 : 0 : aGuard.clear();
398 : 0 : getResultSet()->rowCountFinal();
399 : :
400 : 0 : if (result != GNOME_VFS_ERROR_EOF) {
401 : : #ifdef DEBUG
402 : : g_warning( "Failed read_next '%s'",
403 : : gnome_vfs_result_to_string( result ) );
404 : : #endif
405 : 0 : return sal_False;
406 : : }
407 : :
408 : 0 : result = gnome_vfs_directory_close (dirHandle);
409 : 0 : if (result != GNOME_VFS_OK) {
410 : : #ifdef DEBUG
411 : : g_warning( "Failed close '%s'",
412 : : gnome_vfs_result_to_string( result ) );
413 : : #endif
414 : 0 : return sal_False;
415 : : }
416 : : }
417 : :
418 : 0 : return sal_True;
419 : : }
420 : :
421 : :
422 : :
423 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|