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