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