1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 * This file pinched from webdavdatasupplier (etc.)
22 * cut & paste + new getData impl. & collate ResultSet code.
25 #include <osl/diagnose.h>
26 #include <com/sun/star/ucb/OpenMode.hpp>
27 #include <ucbhelper/contentidentifier.hxx>
28 #include <ucbhelper/providerhelper.hxx>
30 #include "gvfs_directory.hxx"
32 #include <libgnomevfs/gnome-vfs-utils.h>
33 #include <libgnomevfs/gnome-vfs-directory.h>
34 #include <comphelper/processfactory.hxx>
36 using namespace com::sun::star
;
39 // DynamicResultSet Implementation.
41 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
),
51 void DynamicResultSet::initStatic()
54 = new ::ucbhelper::ResultSet( m_xContext
,
55 m_aCommand
.Properties
,
56 new DataSupplier( m_xContent
,
60 void DynamicResultSet::initDynamic()
63 m_xResultSet2
= m_xResultSet1
;
66 //=========================================================================
69 // DataSupplier Implementation.
73 struct ResultListEntry
76 uno::Reference
< ucb::XContentIdentifier
> xId
;
77 uno::Reference
< ucb::XContent
> xContent
;
78 uno::Reference
< sdbc::XRow
> xRow
;
79 GnomeVFSFileInfo aInfo
;
81 ResultListEntry( const GnomeVFSFileInfo
*fileInfo
)
83 gnome_vfs_file_info_copy (&aInfo
, fileInfo
);
88 gnome_vfs_file_info_clear (&aInfo
);
92 //=========================================================================
96 //=========================================================================
98 typedef std::vector
< ResultListEntry
* > ResultList
;
100 //=========================================================================
102 // struct DataSupplier_Impl.
104 //=========================================================================
106 struct gvfs::DataSupplier_Impl
109 ResultList m_aResults
;
110 rtl::Reference
< Content
> m_xContent
;
111 sal_Int32 m_nOpenMode
;
112 sal_Bool m_bCountFinal
;
115 const rtl::Reference
< Content
>& rContent
,
116 sal_Int32 nOpenMode
)
117 : m_xContent( rContent
),
118 m_nOpenMode( nOpenMode
), m_bCountFinal( sal_False
) {}
121 ResultList::const_iterator it
= m_aResults
.begin();
122 ResultList::const_iterator end
= m_aResults
.end();
132 DataSupplier::DataSupplier(
133 const rtl::Reference
< Content
>& rContent
,
134 sal_Int32 nOpenMode
)
135 : m_pImpl( new DataSupplier_Impl( rContent
, nOpenMode
) )
139 //=========================================================================
141 DataSupplier::~DataSupplier()
147 rtl::OUString
DataSupplier::queryContentIdentifierString( sal_uInt32 nIndex
)
149 osl::Guard
< osl::Mutex
> aGuard( m_pImpl
->m_aMutex
);
151 if ( nIndex
< m_pImpl
->m_aResults
.size() ) {
152 rtl::OUString aId
= m_pImpl
->m_aResults
[ nIndex
]->aId
;
153 if ( !aId
.isEmpty() ) // cached
157 if ( getResult( nIndex
) ) {
158 rtl::OUString aId
= m_pImpl
->m_xContent
->getOUURI();
161 escaped_name
= gnome_vfs_escape_string( m_pImpl
->m_aResults
[ nIndex
]->aInfo
.name
);
163 if ( ( aId
.lastIndexOf( '/' ) + 1 ) != aId
.getLength() )
164 aId
+= rtl::OUString("/");
166 aId
+= rtl::OUString::createFromAscii( escaped_name
);
168 g_free( escaped_name
);
170 m_pImpl
->m_aResults
[ nIndex
]->aId
= aId
;
174 return rtl::OUString();
178 uno::Reference
< ucb::XContentIdentifier
>
179 DataSupplier::queryContentIdentifier( sal_uInt32 nIndex
)
181 osl::Guard
< osl::Mutex
> aGuard( m_pImpl
->m_aMutex
);
183 if ( nIndex
< m_pImpl
->m_aResults
.size() ) {
184 uno::Reference
< ucb::XContentIdentifier
> xId
185 = m_pImpl
->m_aResults
[ nIndex
]->xId
;
186 if ( xId
.is() ) // Already cached.
190 rtl::OUString aId
= queryContentIdentifierString( nIndex
);
191 if ( !aId
.isEmpty() ) {
192 uno::Reference
< ucb::XContentIdentifier
> xId
193 = new ::ucbhelper::ContentIdentifier( aId
);
194 m_pImpl
->m_aResults
[ nIndex
]->xId
= xId
;
198 return uno::Reference
< ucb::XContentIdentifier
>();
202 uno::Reference
< ucb::XContent
>
203 DataSupplier::queryContent( sal_uInt32 nIndex
)
205 osl::Guard
< osl::Mutex
> aGuard( m_pImpl
->m_aMutex
);
207 if ( nIndex
< m_pImpl
->m_aResults
.size() ) {
208 uno::Reference
< ucb::XContent
> xContent
209 = m_pImpl
->m_aResults
[ nIndex
]->xContent
;
210 if ( xContent
.is() ) // Already cached.
214 uno::Reference
< ucb::XContentIdentifier
> xId
215 = queryContentIdentifier( nIndex
);
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 = m_pImpl
->m_xContent
->getProvider()->queryContent( xId
);
225 m_pImpl
->m_aResults
[ nIndex
]->xContent
= xContent
;
229 catch ( ucb::IllegalIdentifierException
& ) {
232 return uno::Reference
< ucb::XContent
>();
236 sal_Bool
DataSupplier::getResult( sal_uInt32 nIndex
)
238 osl::ClearableGuard
< osl::Mutex
> aGuard( m_pImpl
->m_aMutex
);
240 if ( m_pImpl
->m_aResults
.size() > nIndex
) // Result already present.
243 if ( getData() && m_pImpl
->m_aResults
.size() > nIndex
)
250 sal_uInt32
DataSupplier::totalCount()
254 osl::Guard
< osl::Mutex
> aGuard( m_pImpl
->m_aMutex
);
256 return m_pImpl
->m_aResults
.size();
260 sal_uInt32
DataSupplier::currentCount()
262 osl::Guard
< osl::Mutex
> aGuard( m_pImpl
->m_aMutex
);
263 return m_pImpl
->m_aResults
.size();
267 sal_Bool
DataSupplier::isCountFinal()
269 osl::Guard
< osl::Mutex
> aGuard( m_pImpl
->m_aMutex
);
270 return m_pImpl
->m_bCountFinal
;
274 uno::Reference
< sdbc::XRow
> DataSupplier::queryPropertyValues( sal_uInt32 nIndex
)
276 osl::Guard
< osl::Mutex
> aGuard( m_pImpl
->m_aMutex
);
278 if ( nIndex
< m_pImpl
->m_aResults
.size() ) {
279 uno::Reference
< sdbc::XRow
> xRow
= m_pImpl
->m_aResults
[ nIndex
]->xRow
;
280 if ( xRow
.is() ) // Already cached.
284 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 Content
*pContent
= static_cast< ::gvfs::Content
* >(queryContent( nIndex
).get());
289 uno::Reference
< sdbc::XRow
> xRow
=
290 pContent
->getPropertyValues( getResultSet()->getProperties(),
291 getResultSet()->getEnvironment() );
293 m_pImpl
->m_aResults
[ nIndex
]->xRow
= xRow
;
298 return uno::Reference
< sdbc::XRow
>();
302 void DataSupplier::releasePropertyValues( sal_uInt32 nIndex
)
304 osl::Guard
< osl::Mutex
> aGuard( m_pImpl
->m_aMutex
);
306 if ( nIndex
< m_pImpl
->m_aResults
.size() )
307 m_pImpl
->m_aResults
[ nIndex
]->xRow
= uno::Reference
< sdbc::XRow
>();
311 void DataSupplier::close()
316 void DataSupplier::validate()
317 throw( ucb::ResultSetException
)
321 sal_Bool
DataSupplier::getData()
323 osl::ClearableGuard
< osl::Mutex
> aGuard( m_pImpl
->m_aMutex
);
325 if ( !m_pImpl
->m_bCountFinal
) {
326 GnomeVFSResult result
;
327 GnomeVFSDirectoryHandle
*dirHandle
= NULL
;
330 Authentication
aAuth( getResultSet()->getEnvironment() );
331 char *uri
= m_pImpl
->m_xContent
->getURI();
332 result
= gnome_vfs_directory_open
333 ( &dirHandle
, uri
, GNOME_VFS_FILE_INFO_DEFAULT
);
335 if (result
!= GNOME_VFS_OK
) {
337 g_warning ("Failed open of '%s' with '%s'",
338 uri
, gnome_vfs_result_to_string( result
));
347 GnomeVFSFileInfo
* fileInfo
= gnome_vfs_file_info_new ();
349 while ((result
= gnome_vfs_directory_read_next (dirHandle
, fileInfo
)) == GNOME_VFS_OK
) {
350 if( fileInfo
->name
&& fileInfo
->name
[0] == '.' &&
351 ( fileInfo
->name
[1] == '\0' ||
352 ( fileInfo
->name
[1] == '.' && fileInfo
->name
[2] == '\0' ) ) )
355 switch ( m_pImpl
->m_nOpenMode
) {
356 case ucb::OpenMode::FOLDERS
:
357 if ( !(fileInfo
->valid_fields
& GNOME_VFS_FILE_INFO_FIELDS_TYPE
) ||
358 fileInfo
->type
!= GNOME_VFS_FILE_TYPE_DIRECTORY
)
362 case ucb::OpenMode::DOCUMENTS
:
363 if ( !(fileInfo
->valid_fields
& GNOME_VFS_FILE_INFO_FIELDS_TYPE
) ||
364 fileInfo
->type
!= GNOME_VFS_FILE_TYPE_REGULAR
)
368 case ucb::OpenMode::ALL
:
373 m_pImpl
->m_aResults
.push_back( new ResultListEntry( fileInfo
) );
376 gnome_vfs_file_info_unref (fileInfo
);
378 #if OSL_DEBUG_LEVEL > 1
379 g_warning ("Got %d directory entries", result
);
382 m_pImpl
->m_bCountFinal
= sal_True
;
384 // Callback possible, because listeners may be informed!
386 getResultSet()->rowCountFinal();
388 if (result
!= GNOME_VFS_ERROR_EOF
) {
390 g_warning( "Failed read_next '%s'",
391 gnome_vfs_result_to_string( result
) );
396 result
= gnome_vfs_directory_close (dirHandle
);
397 if (result
!= GNOME_VFS_OK
) {
399 g_warning( "Failed close '%s'",
400 gnome_vfs_result_to_string( result
) );
411 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */