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 #include <vector>
29 
30 #include <ucbhelper/contentidentifier.hxx>
31 #include <ucbhelper/providerhelper.hxx>
32 
33 #include <com/sun/star/ucb/OpenMode.hpp>
34 
35 #include "gio_datasupplier.hxx"
36 #include "gio_content.hxx"
37 #include "gio_provider.hxx"
38 
39 #include <stdio.h>
40 
41 using namespace com::sun::star;
42 
43 using namespace gio;
44 
45 namespace gio
46 {
47 
48 typedef std::vector< ResultListEntry* > ResultList;
49 
50 DataSupplier::DataSupplier( const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
51     const uno::Reference< ::gio::Content >& rContent, sal_Int32 nOpenMode )
52     : mxContent(rContent), m_xSMgr(rxSMgr), mnOpenMode(nOpenMode), mbCountFinal(false)
53 {
54 }
55 
56 bool DataSupplier::getData()
57 {
58     if (mbCountFinal)
59         return true;
60 
61     GFile *pFile = mxContent->getGFile();
62 
63     GFileEnumerator* pEnumerator = g_file_enumerate_children(pFile, "*",
64         G_FILE_QUERY_INFO_NONE, NULL, NULL);
65 
66     if (!pEnumerator)
67         return sal_False;
68 
69     GFileInfo *pInfo = NULL;
70     while ((pInfo = g_file_enumerator_next_file (pEnumerator, NULL, NULL)))
71     {
72         switch ( mnOpenMode )
73         {
74             case ucb::OpenMode::FOLDERS:
75                 if (g_file_info_get_file_type(pInfo) != G_FILE_TYPE_DIRECTORY)
76                     continue;
77                 break;
78             case ucb::OpenMode::DOCUMENTS:
79                 if (g_file_info_get_file_type(pInfo) != G_FILE_TYPE_REGULAR)
80                     continue;
81                 break;
82             case ucb::OpenMode::ALL:
83             default:
84                 break;
85         }
86 
87         maResults.push_back( new ResultListEntry( pInfo ) );
88         g_object_unref(pInfo);
89     }
90 
91     mbCountFinal = sal_True;
92 
93     g_file_enumerator_close(pEnumerator, NULL, NULL);
94     return true;
95 }
96 
97 DataSupplier::~DataSupplier()
98 {
99     ResultList::const_iterator it  = maResults.begin();
100     ResultList::const_iterator end = maResults.end();
101 
102     while ( it != end )
103     {
104         delete (*it);
105         it++;
106     }
107 }
108 
109 ::rtl::OUString DataSupplier::queryContentIdentifierString( sal_uInt32 nIndex )
110 {
111     if ( nIndex < maResults.size() )
112     {
113         ::rtl::OUString aId = maResults[ nIndex ]->aId;
114         if ( aId.getLength() )
115         {
116             // Already cached.
117             return aId;
118         }
119     }
120 
121     if ( getResult( nIndex ) )
122     {
123         GFile *pFile = mxContent->getGFile();
124         char* parent = g_file_get_uri(pFile);
125         rtl::OUString aId = rtl::OUString::createFromAscii( parent );
126         g_free(parent);
127 
128         char *escaped_name =
129             g_uri_escape_string( g_file_info_get_name(maResults[ nIndex ]->pInfo) , NULL, false);
130 
131         if ( ( aId.lastIndexOf( '/' ) + 1 ) != aId.getLength() )
132                 aId += rtl::OUString::createFromAscii( "/" );
133 
134         aId += rtl::OUString::createFromAscii( escaped_name );
135 
136         g_free( escaped_name );
137 
138         maResults[ nIndex ]->aId = aId;
139         return aId;
140 
141         return aId;
142     }
143 
144     return ::rtl::OUString();
145 }
146 
147 uno::Reference< ucb::XContentIdentifier > DataSupplier::queryContentIdentifier( sal_uInt32 nIndex )
148 {
149     if ( nIndex < maResults.size() )
150     {
151         uno::Reference< ucb::XContentIdentifier > xId = maResults[ nIndex ]->xId;
152         if ( xId.is() )
153         {
154             // Already cached.
155             return xId;
156         }
157     }
158 
159     ::rtl::OUString aId = queryContentIdentifierString( nIndex );
160     if ( aId.getLength() )
161     {
162         uno::Reference< ucb::XContentIdentifier > xId = new ucbhelper::ContentIdentifier( aId );
163         maResults[ nIndex ]->xId = xId;
164         return xId;
165     }
166 
167     return uno::Reference< ucb::XContentIdentifier >();
168 }
169 
170 uno::Reference< ucb::XContent > DataSupplier::queryContent( sal_uInt32 nIndex )
171 {
172     if ( nIndex < maResults.size() )
173     {
174         uno::Reference< ucb::XContent > xContent = maResults[ nIndex ]->xContent;
175         if ( xContent.is() )
176         {
177             // Already cached.
178             return xContent;
179         }
180     }
181 
182     uno::Reference< ucb::XContentIdentifier > xId = queryContentIdentifier( nIndex );
183     if ( xId.is() )
184     {
185         try
186         {
187             uno::Reference< ucb::XContent > xContent = mxContent->getProvider()->queryContent( xId );
188             maResults[ nIndex ]->xContent = xContent;
189             return xContent;
190         }
191         catch ( ucb::IllegalIdentifierException& )
192         {
193         }
194     }
195     return uno::Reference< ucb::XContent >();
196 }
197 
198 sal_Bool DataSupplier::getResult( sal_uInt32 nIndex )
199 {
200     if ( maResults.size() > nIndex ) // Result already present.
201         return sal_True;
202 
203     if ( getData() && maResults.size() > nIndex )
204         return sal_True;
205 
206     return sal_False;
207 }
208 
209 sal_uInt32 DataSupplier::totalCount()
210 {
211     getData();
212     return maResults.size();
213 }
214 
215 sal_uInt32 DataSupplier::currentCount()
216 {
217     return maResults.size();
218 }
219 
220 sal_Bool DataSupplier::isCountFinal()
221 {
222     return mbCountFinal;
223 }
224 
225 uno::Reference< sdbc::XRow > DataSupplier::queryPropertyValues( sal_uInt32 nIndex  )
226 {
227     if ( nIndex < maResults.size() )
228     {
229         uno::Reference< sdbc::XRow > xRow = maResults[ nIndex ]->xRow;
230         if ( xRow.is() )
231         {
232             // Already cached.
233             return xRow;
234         }
235     }
236 
237     if ( getResult( nIndex ) )
238     {
239         uno::Reference< ucb::XContent > xContent( queryContent( nIndex ) );
240         if ( xContent.is() )
241         {
242             try
243             {
244                 uno::Reference< ucb::XCommandProcessor > xCmdProc(
245                     xContent, uno::UNO_QUERY_THROW );
246                 sal_Int32 nCmdId( xCmdProc->createCommandIdentifier() );
247                 ucb::Command aCmd;
248                 aCmd.Name = rtl::OUString::createFromAscii( "getPropertyValues" );
249                 aCmd.Handle = -1;
250                 aCmd.Argument <<= getResultSet()->getProperties();
251                 uno::Any aResult( xCmdProc->execute(
252                     aCmd, nCmdId, getResultSet()->getEnvironment() ) );
253                 uno::Reference< sdbc::XRow > xRow;
254                 if ( aResult >>= xRow )
255                 {
256                     maResults[ nIndex ]->xRow = xRow;
257                     return xRow;
258                 }
259             }
260             catch ( uno::Exception const & )
261             {
262             }
263         }
264     }
265     return uno::Reference< sdbc::XRow >();
266 }
267 
268 void DataSupplier::releasePropertyValues( sal_uInt32 nIndex )
269 {
270     if ( nIndex < maResults.size() )
271         maResults[ nIndex ]->xRow = uno::Reference< sdbc::XRow >();
272 }
273 
274 void DataSupplier::close()
275 {
276 }
277 
278 void DataSupplier::validate() throw( ucb::ResultSetException )
279 {
280 }
281 
282 }
283