merge the formfield patch from ooo-build
[ooovba.git] / ucb / source / ucp / gvfs / directory.cxx
blob784bd5dfdaebd351daa6539b0aaf2d617f278119
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: directory.cxx,v $
10 * $Revision: 1.7 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_ucb.hxx"
34 * This file pinched from webdavdatasupplier (etc.)
35 * cut & paste + new getData impl. & collate ResultSet code.
37 #include <vector>
38 #include <osl/diagnose.h>
39 #include <com/sun/star/ucb/OpenMode.hpp>
40 #include <ucbhelper/contentidentifier.hxx>
41 #include <ucbhelper/providerhelper.hxx>
43 #include "directory.hxx"
45 #include <libgnomevfs/gnome-vfs-utils.h>
46 #include <libgnomevfs/gnome-vfs-directory.h>
48 using namespace com::sun::star;
49 using namespace gvfs;
51 // DynamicResultSet Implementation.
53 DynamicResultSet::DynamicResultSet(
54 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
55 const rtl::Reference< Content >& rxContent,
56 const ucb::OpenCommandArgument2& rCommand,
57 const uno::Reference< ucb::XCommandEnvironment >& rxEnv )
58 : ResultSetImplHelper( rxSMgr, rCommand ),
59 m_xContent( rxContent ),
60 m_xEnv( rxEnv )
63 void DynamicResultSet::initStatic()
65 m_xResultSet1
66 = new ::ucbhelper::ResultSet( m_xSMgr,
67 m_aCommand.Properties,
68 new DataSupplier( m_xSMgr,
69 m_xContent,
70 m_aCommand.Mode ),
71 m_xEnv );
73 void DynamicResultSet::initDynamic()
75 initStatic();
76 m_xResultSet2 = m_xResultSet1;
79 //=========================================================================
82 // DataSupplier Implementation.
86 struct ResultListEntry
88 rtl::OUString aId;
89 uno::Reference< ucb::XContentIdentifier > xId;
90 uno::Reference< ucb::XContent > xContent;
91 uno::Reference< sdbc::XRow > xRow;
92 GnomeVFSFileInfo aInfo;
94 ResultListEntry( const GnomeVFSFileInfo *fileInfo)
96 gnome_vfs_file_info_copy (&aInfo, fileInfo);
99 ~ResultListEntry()
101 gnome_vfs_file_info_clear (&aInfo);
105 //=========================================================================
107 // ResultList.
109 //=========================================================================
111 typedef std::vector< ResultListEntry* > ResultList;
113 //=========================================================================
115 // struct DataSupplier_Impl.
117 //=========================================================================
119 struct gvfs::DataSupplier_Impl
121 osl::Mutex m_aMutex;
122 ResultList m_aResults;
123 rtl::Reference< Content > m_xContent;
124 uno::Reference< lang::XMultiServiceFactory > m_xSMgr;
125 sal_Int32 m_nOpenMode;
126 sal_Bool m_bCountFinal;
128 DataSupplier_Impl(
129 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
130 const rtl::Reference< Content >& rContent,
131 sal_Int32 nOpenMode )
132 : m_xContent( rContent ), m_xSMgr( rxSMgr ),
133 m_nOpenMode( nOpenMode ), m_bCountFinal( sal_False ) {}
134 ~DataSupplier_Impl()
136 ResultList::const_iterator it = m_aResults.begin();
137 ResultList::const_iterator end = m_aResults.end();
139 while ( it != end )
141 delete (*it);
142 it++;
147 DataSupplier::DataSupplier(
148 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
149 const rtl::Reference< Content >& rContent,
150 sal_Int32 nOpenMode )
151 : m_pImpl( new DataSupplier_Impl( rxSMgr, rContent, nOpenMode ) )
155 //=========================================================================
156 // virtual
157 DataSupplier::~DataSupplier()
159 delete m_pImpl;
162 // virtual
163 rtl::OUString DataSupplier::queryContentIdentifierString( sal_uInt32 nIndex )
165 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
167 if ( nIndex < m_pImpl->m_aResults.size() ) {
168 rtl::OUString aId = m_pImpl->m_aResults[ nIndex ]->aId;
169 if ( aId.getLength() ) // cached
170 return aId;
173 if ( getResult( nIndex ) ) {
174 rtl::OUString aId = m_pImpl->m_xContent->getOUURI();
176 char *escaped_name;
177 escaped_name = gnome_vfs_escape_string( m_pImpl->m_aResults[ nIndex ]->aInfo.name );
179 if ( ( aId.lastIndexOf( '/' ) + 1 ) != aId.getLength() )
180 aId += rtl::OUString::createFromAscii( "/" );
182 aId += rtl::OUString::createFromAscii( escaped_name );
184 g_free( escaped_name );
186 m_pImpl->m_aResults[ nIndex ]->aId = aId;
187 return aId;
190 return rtl::OUString();
193 // virtual
194 uno::Reference< ucb::XContentIdentifier >
195 DataSupplier::queryContentIdentifier( sal_uInt32 nIndex )
197 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
199 if ( nIndex < m_pImpl->m_aResults.size() ) {
200 uno::Reference< ucb::XContentIdentifier > xId
201 = m_pImpl->m_aResults[ nIndex ]->xId;
202 if ( xId.is() ) // Already cached.
203 return xId;
206 rtl::OUString aId = queryContentIdentifierString( nIndex );
207 if ( aId.getLength() ) {
208 uno::Reference< ucb::XContentIdentifier > xId
209 = new ::ucbhelper::ContentIdentifier( aId );
210 m_pImpl->m_aResults[ nIndex ]->xId = xId;
211 return xId;
214 return uno::Reference< ucb::XContentIdentifier >();
217 // virtual
218 uno::Reference< ucb::XContent >
219 DataSupplier::queryContent( sal_uInt32 nIndex )
221 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
223 if ( nIndex < m_pImpl->m_aResults.size() ) {
224 uno::Reference< ucb::XContent > xContent
225 = m_pImpl->m_aResults[ nIndex ]->xContent;
226 if ( xContent.is() ) // Already cached.
227 return xContent;
230 uno::Reference< ucb::XContentIdentifier > xId
231 = queryContentIdentifier( nIndex );
232 if ( xId.is() ) {
235 // FIXME:
236 // It would be really nice to propagate this information
237 // to the Content, but we can't then register it with the
238 // ContentProvider, and the ucbhelper hinders here.
239 uno::Reference< ucb::XContent > xContent
240 = m_pImpl->m_xContent->getProvider()->queryContent( xId );
241 m_pImpl->m_aResults[ nIndex ]->xContent = xContent;
242 return xContent;
245 catch ( ucb::IllegalIdentifierException& ) {
248 return uno::Reference< ucb::XContent >();
251 // virtual
252 sal_Bool DataSupplier::getResult( sal_uInt32 nIndex )
254 osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
256 if ( m_pImpl->m_aResults.size() > nIndex ) // Result already present.
257 return sal_True;
259 if ( getData() && m_pImpl->m_aResults.size() > nIndex )
260 return sal_True;
262 return sal_False;
265 // virtual
266 sal_uInt32 DataSupplier::totalCount()
268 getData();
270 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
272 return m_pImpl->m_aResults.size();
275 // virtual
276 sal_uInt32 DataSupplier::currentCount()
278 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
279 return m_pImpl->m_aResults.size();
282 // virtual
283 sal_Bool DataSupplier::isCountFinal()
285 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
286 return m_pImpl->m_bCountFinal;
289 // virtual
290 uno::Reference< sdbc::XRow > DataSupplier::queryPropertyValues( sal_uInt32 nIndex )
292 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
294 if ( nIndex < m_pImpl->m_aResults.size() ) {
295 uno::Reference< sdbc::XRow > xRow = m_pImpl->m_aResults[ nIndex ]->xRow;
296 if ( xRow.is() ) // Already cached.
297 return xRow;
300 if ( getResult( nIndex ) ) {
301 // Inefficient - but we can't create xContent's sensibly
302 // nor can we do the property code sensibly cleanly staticaly.
303 Content *pContent = static_cast< ::gvfs::Content * >(queryContent( nIndex ).get());
305 uno::Reference< sdbc::XRow > xRow =
306 pContent->getPropertyValues( getResultSet()->getProperties(),
307 getResultSet()->getEnvironment() );
309 m_pImpl->m_aResults[ nIndex ]->xRow = xRow;
311 return xRow;
314 return uno::Reference< sdbc::XRow >();
317 // virtual
318 void DataSupplier::releasePropertyValues( sal_uInt32 nIndex )
320 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
322 if ( nIndex < m_pImpl->m_aResults.size() )
323 m_pImpl->m_aResults[ nIndex ]->xRow = uno::Reference< sdbc::XRow >();
326 // virtual
327 void DataSupplier::close()
331 // virtual
332 void DataSupplier::validate()
333 throw( ucb::ResultSetException )
337 sal_Bool DataSupplier::getData()
339 osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
341 if ( !m_pImpl->m_bCountFinal ) {
342 GnomeVFSResult result;
343 GnomeVFSDirectoryHandle *dirHandle = NULL;
346 Authentication aAuth( getResultSet()->getEnvironment() );
347 char *uri = m_pImpl->m_xContent->getURI();
348 result = gnome_vfs_directory_open
349 ( &dirHandle, uri, GNOME_VFS_FILE_INFO_DEFAULT );
351 if (result != GNOME_VFS_OK) {
352 #ifdef DEBUG
353 g_warning ("Failed open of '%s' with '%s'",
354 uri, gnome_vfs_result_to_string( result ));
355 #endif
356 g_free( uri );
357 return sal_False;
360 g_free( uri );
364 GnomeVFSFileInfo *pFileInfo = gnome_vfs_file_info_new();
365 while ((result = gnome_vfs_directory_read_next (dirHandle, pFileInfo)) == GNOME_VFS_OK) {
366 if( !pFileInfo->name ||
367 pFileInfo->name[0] == '\0' ||
368 ( pFileInfo->name[0] == '.' &&
369 ( pFileInfo->name[1] == '\0' ||
370 ( pFileInfo->name[1] == '.' && pFileInfo->name[2] == '\0' ) ) ) )
371 continue;
373 switch ( m_pImpl->m_nOpenMode ) {
374 case ucb::OpenMode::FOLDERS:
375 if ( !(pFileInfo->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_TYPE) ||
376 pFileInfo->type != GNOME_VFS_FILE_TYPE_DIRECTORY )
377 continue;
378 break;
380 case ucb::OpenMode::DOCUMENTS:
381 if ( !(pFileInfo->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_TYPE) ||
382 pFileInfo->type != GNOME_VFS_FILE_TYPE_REGULAR )
383 continue;
384 break;
386 case ucb::OpenMode::ALL:
387 default:
388 break;
391 m_pImpl->m_aResults.push_back( new ResultListEntry( pFileInfo ) );
393 g_free( pFileInfo );
394 #ifdef DEBUG
395 g_warning ("Got %d directory entries", result);
396 #endif
398 m_pImpl->m_bCountFinal = sal_True;
400 // Callback possible, because listeners may be informed!
401 aGuard.clear();
402 getResultSet()->rowCountFinal();
404 if (result != GNOME_VFS_ERROR_EOF) {
405 #ifdef DEBUG
406 g_warning( "Failed read_next '%s'",
407 gnome_vfs_result_to_string( result ) );
408 #endif
409 return sal_False;
412 result = gnome_vfs_directory_close (dirHandle);
413 if (result != GNOME_VFS_OK) {
414 #ifdef DEBUG
415 g_warning( "Failed close '%s'",
416 gnome_vfs_result_to_string( result ) );
417 #endif
418 return sal_False;
422 return sal_True;