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