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