1 /*************************************************************************
2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3  *
4  * Copyright 2000, 2010 Oracle and/or its affiliates.
5  *
6  * OpenOffice.org - a multi-platform office productivity suite
7  *
8  * This file is part of OpenOffice.org.
9  *
10  * OpenOffice.org is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU Lesser General Public License version 3
12  * only, as published by the Free Software Foundation.
13  *
14  * OpenOffice.org is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU Lesser General Public License version 3 for more details
18  * (a copy is included in the LICENSE file that accompanied this code).
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * version 3 along with OpenOffice.org.  If not, see
22  * <http://www.openoffice.org/license.html>
23  * for a copy of the LGPLv3 License.
24  *
25 ************************************************************************/
26 
27 #include "precompiled_ucb.hxx"
28 
29 #include "ucpext_datasupplier.hxx"
30 #include "ucpext_content.hxx"
31 #include "ucpext_provider.hxx"
32 
33 /** === begin UNO includes === **/
34 #include <com/sun/star/deployment/XPackageInformationProvider.hpp>
35 /** === end UNO includes === **/
36 
37 #include <ucbhelper/contentidentifier.hxx>
38 #include <comphelper/componentcontext.hxx>
39 #include <ucbhelper/providerhelper.hxx>
40 #include <ucbhelper/content.hxx>
41 #include <ucbhelper/propertyvalueset.hxx>
42 #include <tools/diagnose_ex.h>
43 #include <rtl/ustrbuf.hxx>
44 
45 #include <vector>
46 #include <boost/shared_ptr.hpp>
47 
48 //......................................................................................................................
49 namespace ucb { namespace ucp { namespace ext
50 {
51 //......................................................................................................................
52 
53 	/** === begin UNO using === **/
54 	using ::com::sun::star::uno::Reference;
55 	using ::com::sun::star::uno::XInterface;
56 	using ::com::sun::star::uno::UNO_QUERY;
57 	using ::com::sun::star::uno::UNO_QUERY_THROW;
58 	using ::com::sun::star::uno::UNO_SET_THROW;
59 	using ::com::sun::star::uno::Exception;
60 	using ::com::sun::star::uno::RuntimeException;
61 	using ::com::sun::star::uno::Any;
62 	using ::com::sun::star::uno::makeAny;
63 	using ::com::sun::star::uno::Sequence;
64 	using ::com::sun::star::uno::Type;
65     using ::com::sun::star::ucb::XContent;
66     using ::com::sun::star::ucb::XContentIdentifier;
67     using ::com::sun::star::sdbc::XRow;
68     using ::com::sun::star::lang::XMultiServiceFactory;
69     using ::com::sun::star::ucb::IllegalIdentifierException;
70     using ::com::sun::star::ucb::ResultSetException;
71     using ::com::sun::star::deployment::XPackageInformationProvider;
72     using ::com::sun::star::beans::Property;
73     using ::com::sun::star::sdbc::XResultSet;
74     using ::com::sun::star::sdbc::XRow;
75     using ::com::sun::star::ucb::XCommandEnvironment;
76 	/** === end UNO using === **/
77     //==================================================================================================================
78     //= ResultListEntry
79     //==================================================================================================================
80     struct ResultListEntry
81     {
82         ::rtl::OUString					sId;
83 	    Reference< XContentIdentifier > xId;
84         ::rtl::Reference< Content >     pContent;
85 	    Reference< XRow > 			    xRow;
86     };
87 
88     typedef ::std::vector< ResultListEntry >    ResultList;
89 
90     //==================================================================================================================
91     //= DataSupplier_Impl
92     //==================================================================================================================
93     struct DataSupplier_Impl
94     {
95         ::osl::Mutex                                m_aMutex;
96         ResultList					                m_aResults;
97         ::rtl::Reference< Content >                 m_xContent;
98         Reference< XMultiServiceFactory >           m_xSMgr;
99         sal_Int32                                   m_nOpenMode;
100 
101         DataSupplier_Impl( const Reference< XMultiServiceFactory >& i_rORB, const ::rtl::Reference< Content >& i_rContent,
102 					       const sal_Int32 i_nOpenMode )
103 	        :m_xContent( i_rContent )
104             ,m_xSMgr( i_rORB )
105             ,m_nOpenMode( i_nOpenMode )
106         {
107         }
108 	    ~DataSupplier_Impl();
109     };
110 
111     //------------------------------------------------------------------------------------------------------------------
112     DataSupplier_Impl::~DataSupplier_Impl()
113     {
114     }
115 
116     //==================================================================================================================
117     //= helper
118     //==================================================================================================================
119     namespace
120     {
121         ::rtl::OUString lcl_compose( const ::rtl::OUString& i_rBaseURL, const ::rtl::OUString& i_rRelativeURL )
122         {
123             ENSURE_OR_RETURN( i_rBaseURL.getLength(), "illegal base URL", i_rRelativeURL );
124 
125             ::rtl::OUStringBuffer aComposer( i_rBaseURL );
126             if ( i_rBaseURL.getStr()[ i_rBaseURL.getLength() - 1 ] != '/' )
127                 aComposer.append( sal_Unicode( '/' ) );
128             aComposer.append( i_rRelativeURL );
129             return aComposer.makeStringAndClear();
130         }
131     }
132 
133 
134     //==================================================================================================================
135     //= DataSupplier
136     //==================================================================================================================
137     //------------------------------------------------------------------------------------------------------------------
138     DataSupplier::DataSupplier( const Reference< XMultiServiceFactory >& i_rORB,
139 							    const ::rtl::Reference< Content >& i_rContent,
140 							    const sal_Int32 i_nOpenMode )
141         :m_pImpl( new DataSupplier_Impl( i_rORB, i_rContent, i_nOpenMode ) )
142     {
143     }
144 
145     //------------------------------------------------------------------------------------------------------------------
146     void DataSupplier::fetchData()
147     {
148         try
149         {
150             const ::comphelper::ComponentContext aContext( m_pImpl->m_xSMgr );
151             const Reference< XPackageInformationProvider > xPackageInfo(
152                 aContext.getSingleton( "com.sun.star.deployment.PackageInformationProvider" ), UNO_QUERY_THROW );
153 
154             const ::rtl::OUString sContentIdentifier( m_pImpl->m_xContent->getIdentifier()->getContentIdentifier() );
155 
156             switch ( m_pImpl->m_xContent->getExtensionContentType() )
157             {
158             case E_ROOT:
159             {
160                 Sequence< Sequence< ::rtl::OUString > > aExtensionInfo( xPackageInfo->getExtensionList() );
161                 for (   const Sequence< ::rtl::OUString >* pExtInfo = aExtensionInfo.getConstArray();
162                         pExtInfo != aExtensionInfo.getConstArray() + aExtensionInfo.getLength();
163                         ++pExtInfo
164                     )
165                 {
166                     ENSURE_OR_CONTINUE( pExtInfo->getLength() > 0, "illegal extension info" );
167 
168                     const ::rtl::OUString& rLocalId = (*pExtInfo)[0];
169                     ResultListEntry aEntry;
170                     aEntry.sId = ContentProvider::getRootURL() + Content::encodeIdentifier( rLocalId ) + ::rtl::OUString( sal_Unicode( '/' ) );
171                     m_pImpl->m_aResults.push_back( aEntry );
172                 }
173             }
174             break;
175             case E_EXTENSION_ROOT:
176             case E_EXTENSION_CONTENT:
177             {
178                 const ::rtl::OUString sPackageLocation( m_pImpl->m_xContent->getPhysicalURL() );
179                 ::ucbhelper::Content aWrappedContent( sPackageLocation, getResultSet()->getEnvironment() );
180 
181                 // obtain the properties which our result set is set up for from the wrapped content
182                 Sequence< ::rtl::OUString > aPropertyNames(1);
183                 aPropertyNames[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) );
184 
185                 const Reference< XResultSet > xFolderContent( aWrappedContent.createCursor( aPropertyNames ), UNO_SET_THROW );
186                 const Reference< XRow > xContentRow( xFolderContent, UNO_QUERY_THROW );
187                 while ( xFolderContent->next() )
188                 {
189                     ResultListEntry aEntry;
190                     aEntry.sId = lcl_compose( sContentIdentifier, xContentRow->getString( 1 ) );
191                     m_pImpl->m_aResults.push_back( aEntry );
192                 }
193             }
194             break;
195             default:
196                 OSL_ENSURE( false, "DataSupplier::fetchData: unimplemented content type!" );
197                 break;
198             }
199         }
200         catch( const Exception& )
201         {
202         	DBG_UNHANDLED_EXCEPTION();
203         }
204     }
205 
206     //------------------------------------------------------------------------------------------------------------------
207     DataSupplier::~DataSupplier()
208     {
209     }
210 
211     //------------------------------------------------------------------------------------------------------------------
212     ::rtl::OUString DataSupplier::queryContentIdentifierString( sal_uInt32 i_nIndex )
213     {
214 	    ::osl::Guard< ::osl::Mutex > aGuard( m_pImpl->m_aMutex );
215 
216 	    if ( i_nIndex < m_pImpl->m_aResults.size() )
217 	    {
218             const ::rtl::OUString sId = m_pImpl->m_aResults[ i_nIndex ].sId;
219 		    if ( sId.getLength() )
220 			    return sId;
221 	    }
222 
223         OSL_ENSURE( false, "DataSupplier::queryContentIdentifierString: illegal index, or illegal result entry id!" );
224 	    return ::rtl::OUString();
225     }
226 
227     //------------------------------------------------------------------------------------------------------------------
228     Reference< XContentIdentifier > DataSupplier::queryContentIdentifier( sal_uInt32 i_nIndex )
229     {
230 	    ::osl::Guard< ::osl::Mutex > aGuard( m_pImpl->m_aMutex );
231 
232 	    if ( i_nIndex < m_pImpl->m_aResults.size() )
233 	    {
234 		    Reference< XContentIdentifier > xId( m_pImpl->m_aResults[ i_nIndex ].xId );
235 		    if ( xId.is() )
236 			    return xId;
237 	    }
238 
239 	    ::rtl::OUString sId = queryContentIdentifierString( i_nIndex );
240 	    if ( sId.getLength() )
241 	    {
242 		    Reference< XContentIdentifier > xId = new ::ucbhelper::ContentIdentifier( sId );
243 		    m_pImpl->m_aResults[ i_nIndex ].xId = xId;
244 		    return xId;
245 	    }
246 
247 	    return Reference< XContentIdentifier >();
248     }
249 
250     //------------------------------------------------------------------------------------------------------------------
251     Reference< XContent > DataSupplier::queryContent( sal_uInt32 i_nIndex )
252     {
253         ::osl::Guard< ::osl::Mutex > aGuard( m_pImpl->m_aMutex );
254         ENSURE_OR_RETURN( i_nIndex < m_pImpl->m_aResults.size(), "illegal index!", NULL );
255 
256 
257         ::rtl::Reference< Content > pContent( m_pImpl->m_aResults[ i_nIndex ].pContent );
258 	    if ( pContent.is() )
259 		    return pContent.get();
260 
261 	    Reference< XContentIdentifier > xId( queryContentIdentifier( i_nIndex ) );
262 	    if ( xId.is() )
263 	    {
264 		    try
265 		    {
266 			    Reference< XContent > xContent( m_pImpl->m_xContent->getProvider()->queryContent( xId ) );
267                 pContent.set( dynamic_cast< Content* >( xContent.get() ) );
268                 OSL_ENSURE( pContent.is() || !xContent.is(), "DataSupplier::queryContent: invalid content implementation!" );
269 			    m_pImpl->m_aResults[ i_nIndex ].pContent = pContent;
270 			    return pContent.get();
271 
272 		    }
273 		    catch ( const IllegalIdentifierException& )
274 		    {
275                 DBG_UNHANDLED_EXCEPTION();
276 		    }
277 	    }
278 
279 	    return Reference< XContent >();
280     }
281 
282     //------------------------------------------------------------------------------------------------------------------
283     sal_Bool DataSupplier::getResult( sal_uInt32 i_nIndex )
284     {
285 	    ::osl::ClearableGuard< ::osl::Mutex > aGuard( m_pImpl->m_aMutex );
286 
287 	    if ( m_pImpl->m_aResults.size() > i_nIndex )
288 		    // result already present.
289 		    return sal_True;
290 
291         return sal_False;
292     }
293 
294     //------------------------------------------------------------------------------------------------------------------
295     sal_uInt32 DataSupplier::totalCount()
296     {
297 	    ::osl::ClearableGuard< ::osl::Mutex > aGuard( m_pImpl->m_aMutex );
298 	    return m_pImpl->m_aResults.size();
299     }
300 
301     //------------------------------------------------------------------------------------------------------------------
302     sal_uInt32 DataSupplier::currentCount()
303     {
304 	    return m_pImpl->m_aResults.size();
305     }
306 
307     //------------------------------------------------------------------------------------------------------------------
308     sal_Bool DataSupplier::isCountFinal()
309     {
310 	    return sal_True;
311     }
312 
313     //------------------------------------------------------------------------------------------------------------------
314     Reference< XRow > DataSupplier::queryPropertyValues( sal_uInt32 i_nIndex  )
315     {
316 	    ::osl::MutexGuard aGuard( m_pImpl->m_aMutex );
317         ENSURE_OR_RETURN( i_nIndex < m_pImpl->m_aResults.size(), "DataSupplier::queryPropertyValues: illegal index!", NULL );
318 
319 	    Reference< XRow > xRow = m_pImpl->m_aResults[ i_nIndex ].xRow;
320 	    if ( xRow.is() )
321 		    return xRow;
322 
323         ENSURE_OR_RETURN( queryContent( i_nIndex ).is(), "could not retrieve the content", NULL );
324 
325         switch ( m_pImpl->m_xContent->getExtensionContentType() )
326         {
327         case E_ROOT:
328         {
329             const ::rtl::OUString& rId( m_pImpl->m_aResults[ i_nIndex ].sId );
330             const ::rtl::OUString sRootURL( ContentProvider::getRootURL() );
331             ::rtl::OUString sTitle = Content::decodeIdentifier( rId.copy( sRootURL.getLength() ) );
332             if ( ( sTitle.getLength() > 0 ) && ( sTitle[ sTitle.getLength() - 1 ] == '/' ) )
333                 sTitle = sTitle.copy( 0, sTitle.getLength() - 1 );
334             xRow = Content::getArtificialNodePropertyValues( m_pImpl->m_xSMgr, getResultSet()->getProperties(), sTitle );
335         }
336         break;
337 
338         case E_EXTENSION_ROOT:
339         case E_EXTENSION_CONTENT:
340         {
341             xRow = m_pImpl->m_aResults[ i_nIndex ].pContent->getPropertyValues(
342                 getResultSet()->getProperties(), getResultSet()->getEnvironment() );
343         }
344         break;
345         default:
346             OSL_ENSURE( false, "DataSupplier::queryPropertyValues: unhandled case!" );
347             break;
348         }
349 
350         m_pImpl->m_aResults[ i_nIndex ].xRow = xRow;
351 	    return xRow;
352     }
353 
354     //------------------------------------------------------------------------------------------------------------------
355     void DataSupplier::releasePropertyValues( sal_uInt32 i_nIndex )
356     {
357 	    ::osl::Guard< ::osl::Mutex > aGuard( m_pImpl->m_aMutex );
358 
359 	    if ( i_nIndex < m_pImpl->m_aResults.size() )
360 		    m_pImpl->m_aResults[ i_nIndex ].xRow.clear();
361     }
362 
363     //------------------------------------------------------------------------------------------------------------------
364     void DataSupplier::close()
365     {
366     }
367 
368     //------------------------------------------------------------------------------------------------------------------
369     void DataSupplier::validate() throw( ResultSetException )
370     {
371     }
372 
373 //......................................................................................................................
374 } } }   // namespace ucp::ext
375 //......................................................................................................................
376