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_ext.hxx"
25 
26 #include "ucpext_content.hxx"
27 
28 #include "ucpext_content.hxx"
29 #include "ucpext_provider.hxx"
30 #include "ucpext_resultset.hxx"
31 
32 /** === begin UNO includes === **/
33 #include <com/sun/star/beans/PropertyAttribute.hpp>
34 #include <com/sun/star/beans/XPropertyAccess.hpp>
35 #include <com/sun/star/lang/IllegalAccessException.hpp>
36 #include <com/sun/star/sdbc/XRow.hpp>
37 #include <com/sun/star/ucb/XCommandInfo.hpp>
38 #include <com/sun/star/ucb/XPersistentPropertySet.hpp>
39 #include <com/sun/star/io/XOutputStream.hpp>
40 #include <com/sun/star/io/XActiveDataSink.hpp>
41 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
42 #include <com/sun/star/ucb/OpenMode.hpp>
43 #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
44 #include <com/sun/star/ucb/UnsupportedOpenModeException.hpp>
45 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
46 #include <com/sun/star/ucb/OpenMode.hpp>
47 #include <com/sun/star/ucb/XDynamicResultSet.hpp>
48 #include <com/sun/star/lang/IllegalAccessException.hpp>
49 #include <com/sun/star/deployment/XPackageInformationProvider.hpp>
50 /** === end UNO includes === **/
51 
52 #include <ucbhelper/contentidentifier.hxx>
53 #include <ucbhelper/propertyvalueset.hxx>
54 #include <ucbhelper/cancelcommandexecution.hxx>
55 #include <ucbhelper/content.hxx>
56 #include <tools/diagnose_ex.h>
57 #include <comphelper/string.hxx>
58 #include <comphelper/componentcontext.hxx>
59 #include <rtl/ustrbuf.hxx>
60 #include <rtl/uri.hxx>
61 
62 #include <algorithm>
63 
64 //......................................................................................................................
65 namespace ucb { namespace ucp { namespace ext
66 {
67 //......................................................................................................................
68 
69 	/** === begin UNO using === **/
70 	using ::com::sun::star::uno::Reference;
71 	using ::com::sun::star::uno::XInterface;
72 	using ::com::sun::star::uno::UNO_QUERY;
73 	using ::com::sun::star::uno::UNO_QUERY_THROW;
74 	using ::com::sun::star::uno::UNO_SET_THROW;
75 	using ::com::sun::star::uno::Exception;
76 	using ::com::sun::star::uno::RuntimeException;
77 	using ::com::sun::star::uno::Any;
78 	using ::com::sun::star::uno::makeAny;
79 	using ::com::sun::star::uno::Sequence;
80 	using ::com::sun::star::uno::Type;
81     using ::com::sun::star::lang::XMultiServiceFactory;
82     using ::com::sun::star::ucb::XContentIdentifier;
83     using ::com::sun::star::ucb::IllegalIdentifierException;
84     using ::com::sun::star::ucb::XContent;
85     using ::com::sun::star::ucb::XCommandEnvironment;
86     using ::com::sun::star::ucb::Command;
87     using ::com::sun::star::ucb::CommandAbortedException;
88     using ::com::sun::star::beans::Property;
89     using ::com::sun::star::lang::IllegalArgumentException;
90     using ::com::sun::star::beans::PropertyValue;
91     using ::com::sun::star::ucb::OpenCommandArgument2;
92     using ::com::sun::star::ucb::XDynamicResultSet;
93     using ::com::sun::star::ucb::UnsupportedOpenModeException;
94     using ::com::sun::star::io::XOutputStream;
95     using ::com::sun::star::io::XActiveDataSink;
96     using ::com::sun::star::io::XInputStream;
97     using ::com::sun::star::ucb::UnsupportedDataSinkException;
98     using ::com::sun::star::ucb::UnsupportedCommandException;
99     using ::com::sun::star::sdbc::XRow;
100     using ::com::sun::star::beans::XPropertySet;
101     using ::com::sun::star::beans::PropertyChangeEvent;
102     using ::com::sun::star::lang::IllegalAccessException;
103     using ::com::sun::star::ucb::CommandInfo;
104     using ::com::sun::star::deployment::XPackageInformationProvider;
105 	/** === end UNO using === **/
106     namespace OpenMode = ::com::sun::star::ucb::OpenMode;
107     namespace PropertyAttribute = ::com::sun::star::beans::PropertyAttribute;
108 
109     //==================================================================================================================
110     //= helper
111     //==================================================================================================================
112     namespace
113     {
114         //--------------------------------------------------------------------------------------------------------------
lcl_compose(const::rtl::OUString & i_rBaseURL,const::rtl::OUString & i_rRelativeURL)115         ::rtl::OUString lcl_compose( const ::rtl::OUString& i_rBaseURL, const ::rtl::OUString& i_rRelativeURL )
116         {
117             ENSURE_OR_RETURN( i_rBaseURL.getLength(), "illegal base URL", i_rRelativeURL );
118 
119             ::rtl::OUStringBuffer aComposer( i_rBaseURL );
120             if ( i_rBaseURL.getStr()[ i_rBaseURL.getLength() - 1 ] != '/' )
121                 aComposer.append( sal_Unicode( '/' ) );
122             aComposer.append( i_rRelativeURL );
123             return aComposer.makeStringAndClear();
124         }
125 
126         //--------------------------------------------------------------------------------------------------------------
127         struct SelectPropertyName : public ::std::unary_function< Property, ::rtl::OUString >
128         {
operator ()ucb::ucp::ext::__anonea28d32b0111::SelectPropertyName129             const ::rtl::OUString& operator()( const Property& i_rProperty ) const
130             {
131                 return i_rProperty.Name;
132             }
133         };
134     }
135 
136     //==================================================================================================================
137     //= Content
138     //==================================================================================================================
139     //------------------------------------------------------------------------------------------------------------------
Content(const Reference<XMultiServiceFactory> & i_rORB,::ucbhelper::ContentProviderImplHelper * i_pProvider,const Reference<XContentIdentifier> & i_rIdentifier)140     Content::Content( const Reference< XMultiServiceFactory >& i_rORB, ::ucbhelper::ContentProviderImplHelper* i_pProvider,
141                       const Reference< XContentIdentifier >& i_rIdentifier )
142         :Content_Base( i_rORB, i_pProvider, i_rIdentifier )
143         ,m_eExtContentType( E_UNKNOWN )
144         ,m_aIsFolder()
145         ,m_aContentType()
146         ,m_sExtensionId()
147         ,m_sPathIntoExtension()
148     {
149         const ::rtl::OUString sURL( getIdentifier()->getContentIdentifier() );
150         if ( denotesRootContent( sURL ) )
151         {
152             m_eExtContentType = E_ROOT;
153         }
154         else
155         {
156             const ::rtl::OUString sRelativeURL( sURL.copy( ContentProvider::getRootURL().getLength() ) );
157             const sal_Int32 nSepPos = sRelativeURL.indexOf( '/' );
158             if ( ( nSepPos == -1 ) || ( nSepPos == sRelativeURL.getLength() - 1 ) )
159             {
160                 m_eExtContentType = E_EXTENSION_ROOT;
161             }
162             else
163             {
164                 m_eExtContentType = E_EXTENSION_CONTENT;
165             }
166         }
167 
168         if ( m_eExtContentType != E_ROOT )
169         {
170             const ::rtl::OUString sRootURL = ContentProvider::getRootURL();
171             m_sExtensionId = sURL.copy( sRootURL.getLength() );
172 
173             const sal_Int32 nNextSep = m_sExtensionId.indexOf( '/' );
174             if ( nNextSep > -1 )
175             {
176                 m_sPathIntoExtension = m_sExtensionId.copy( nNextSep + 1 );
177                 m_sExtensionId = m_sExtensionId.copy( 0, nNextSep );
178             }
179             m_sExtensionId = Content::decodeIdentifier( m_sExtensionId );
180         }
181     }
182 
183     //------------------------------------------------------------------------------------------------------------------
~Content()184     Content::~Content()
185     {
186     }
187 
188     //------------------------------------------------------------------------------------------------------------------
getImplementationName()189     ::rtl::OUString SAL_CALL Content::getImplementationName() throw( RuntimeException )
190     {
191         return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.comp.ucp.ext.Content" ) );
192     }
193 
194     //------------------------------------------------------------------------------------------------------------------
getSupportedServiceNames()195     Sequence< ::rtl::OUString > SAL_CALL Content::getSupportedServiceNames() throw( RuntimeException )
196     {
197         Sequence< ::rtl::OUString > aServiceNames(2);
198         aServiceNames[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ucb.Content" ) );
199         aServiceNames[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ucb.ExtensionContent" ) );
200         return aServiceNames;
201     }
202 
203     //------------------------------------------------------------------------------------------------------------------
getContentType()204     ::rtl::OUString SAL_CALL Content::getContentType() throw( RuntimeException )
205     {
206         impl_determineContentType();
207         return *m_aContentType;
208     }
209 
210     //------------------------------------------------------------------------------------------------------------------
execute(const Command & aCommand,sal_Int32,const Reference<XCommandEnvironment> & i_rEvironment)211     Any SAL_CALL Content::execute( const Command& aCommand, sal_Int32 /* CommandId */, const Reference< XCommandEnvironment >& i_rEvironment )
212         throw( Exception, CommandAbortedException, RuntimeException )
213     {
214         Any aRet;
215 
216         if ( aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "getPropertyValues" ) ) )
217 	    {
218             Sequence< Property > Properties;
219 		    if ( !( aCommand.Argument >>= Properties ) )
220 		    {
221                 ::ucbhelper::cancelCommandExecution( makeAny( IllegalArgumentException(
222                     ::rtl::OUString(), *this, -1 ) ),
223                     i_rEvironment );
224                 // unreachable
225 		    }
226 
227             aRet <<= getPropertyValues( Properties, i_rEvironment );
228 	    }
229         else if ( aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "setPropertyValues" ) ) )
230         {
231             Sequence< PropertyValue > aProperties;
232 		    if ( !( aCommand.Argument >>= aProperties ) )
233 		    {
234                 ::ucbhelper::cancelCommandExecution( makeAny( IllegalArgumentException(
235                     ::rtl::OUString(), *this, -1 ) ),
236                     i_rEvironment );
237                 // unreachable
238             }
239 
240 		    if ( !aProperties.getLength() )
241 		    {
242                 ::ucbhelper::cancelCommandExecution( makeAny( IllegalArgumentException(
243                     ::rtl::OUString(), *this, -1 ) ),
244                     i_rEvironment );
245                 // unreachable
246             }
247 
248             aRet <<= setPropertyValues( aProperties, i_rEvironment );
249 	    }
250         else if ( aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "getPropertySetInfo" ) ) )
251         {
252 		    // implemented by base class.
253 		    aRet <<= getPropertySetInfo( i_rEvironment );
254 	    }
255         else if ( aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "getCommandInfo" ) ) )
256         {
257 		    // implemented by base class.
258 		    aRet <<= getCommandInfo( i_rEvironment );
259 	    }
260         else if ( aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "open" ) ) )
261         {
262             OpenCommandArgument2 aOpenCommand;
263       	    if ( !( aCommand.Argument >>= aOpenCommand ) )
264 		    {
265                 ::ucbhelper::cancelCommandExecution( makeAny( IllegalArgumentException(
266                     ::rtl::OUString(), *this, -1 ) ),
267                     i_rEvironment );
268                 // unreachable
269             }
270 
271             sal_Bool bOpenFolder =
272                 ( ( aOpenCommand.Mode == OpenMode::ALL ) ||
273                   ( aOpenCommand.Mode == OpenMode::FOLDERS ) ||
274                   ( aOpenCommand.Mode == OpenMode::DOCUMENTS ) );
275 
276 
277             if ( bOpenFolder && impl_isFolder() )
278 		    {
279                 Reference< XDynamicResultSet > xSet = new ResultSet(
280                     m_xSMgr, this, aOpenCommand, i_rEvironment );
281     		    aRet <<= xSet;
282   		    }
283 
284             if ( aOpenCommand.Sink.is() )
285             {
286                 const ::rtl::OUString sPhysicalContentURL( getPhysicalURL() );
287                 ::ucbhelper::Content aRequestedContent( sPhysicalContentURL, i_rEvironment );
288                 aRet = aRequestedContent.executeCommand( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ), makeAny( aOpenCommand ) );
289 		    }
290 	    }
291 
292 	    else
293 	    {
294             ::ucbhelper::cancelCommandExecution( makeAny( UnsupportedCommandException(
295                 ::rtl::OUString(), *this ) ),
296                 i_rEvironment );
297             // unreachable
298         }
299 
300 	    return aRet;
301     }
302 
303     //------------------------------------------------------------------------------------------------------------------
abort(sal_Int32)304     void SAL_CALL Content::abort( sal_Int32 ) throw( RuntimeException )
305     {
306     }
307 
308     //------------------------------------------------------------------------------------------------------------------
encodeIdentifier(const::rtl::OUString & i_rIdentifier)309     ::rtl::OUString Content::encodeIdentifier( const ::rtl::OUString& i_rIdentifier )
310     {
311         return ::rtl::Uri::encode( i_rIdentifier, rtl_UriCharClassRegName, rtl_UriEncodeIgnoreEscapes,
312             RTL_TEXTENCODING_UTF8 );
313     }
314 
315     //------------------------------------------------------------------------------------------------------------------
decodeIdentifier(const::rtl::OUString & i_rIdentifier)316     ::rtl::OUString Content::decodeIdentifier( const ::rtl::OUString& i_rIdentifier )
317     {
318         return ::rtl::Uri::decode( i_rIdentifier, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 );
319     }
320 
321     //------------------------------------------------------------------------------------------------------------------
denotesRootContent(const::rtl::OUString & i_rContentIdentifier)322     bool Content::denotesRootContent( const ::rtl::OUString& i_rContentIdentifier )
323     {
324         const ::rtl::OUString sRootURL( ContentProvider::getRootURL() );
325         if ( i_rContentIdentifier == sRootURL )
326             return true;
327 
328         // the root URL contains only two trailing /, but we also recognize 3 of them as denoting the root URL
329         if  (   i_rContentIdentifier.match( sRootURL )
330             &&  ( i_rContentIdentifier.getLength() == sRootURL.getLength() + 1 )
331             &&  ( i_rContentIdentifier[ i_rContentIdentifier.getLength() - 1 ] == '/' )
332             )
333             return true;
334 
335         return false;
336     }
337 
338     //------------------------------------------------------------------------------------------------------------------
getParentURL()339     ::rtl::OUString Content::getParentURL()
340     {
341         const ::rtl::OUString sRootURL( ContentProvider::getRootURL() );
342 
343         switch ( m_eExtContentType )
344         {
345         case E_ROOT:
346             // don't have a parent
347             return sRootURL;
348 
349         case E_EXTENSION_ROOT:
350             // our parent is the root itself
351             return sRootURL;
352 
353         case E_EXTENSION_CONTENT:
354         {
355             const ::rtl::OUString sURL = m_xIdentifier->getContentIdentifier();
356 
357             // cut the root URL
358             ENSURE_OR_BREAK( sURL.match( sRootURL, 0 ), "illegal URL structure - no root" );
359             ::rtl::OUString sRelativeURL( sURL.copy( sRootURL.getLength() ) );
360 
361             // cut the extension ID
362             const ::rtl::OUString sSeparatedExtensionId( encodeIdentifier( m_sExtensionId ) + ::rtl::OUString( sal_Unicode( '/' ) ) );
363             ENSURE_OR_BREAK( sRelativeURL.match( sSeparatedExtensionId ), "illegal URL structure - no extension ID" );
364             sRelativeURL = sRelativeURL.copy( sSeparatedExtensionId.getLength() );
365 
366             // cut the final slash (if any)
367             ENSURE_OR_BREAK( sRelativeURL.getLength(), "illegal URL structure - ExtensionContent should have a level below the extension ID" );
368             if ( sRelativeURL.getStr()[ sRelativeURL.getLength() - 1 ] == '/' )
369                 sRelativeURL = sRelativeURL.copy( 0, sRelativeURL.getLength() - 1 );
370 
371             // remove the last segment
372             const sal_Int32 nLastSep = sRelativeURL.lastIndexOf( '/' );
373             sRelativeURL = sRelativeURL.copy( 0, nLastSep != -1 ? nLastSep : 0 );
374 
375             ::rtl::OUStringBuffer aComposer;
376             aComposer.append( sRootURL );
377             aComposer.append( sSeparatedExtensionId );
378             aComposer.append( sRelativeURL );
379             return aComposer.makeStringAndClear();
380         }
381 
382         default:
383             OSL_ENSURE( false, "Content::getParentURL: unhandled case!" );
384             break;
385         }
386         return ::rtl::OUString();
387     }
388 
389     //------------------------------------------------------------------------------------------------------------------
getArtificialNodePropertyValues(const Reference<XMultiServiceFactory> & i_rORB,const Sequence<Property> & i_rProperties,const::rtl::OUString & i_rTitle)390     Reference< XRow > Content::getArtificialNodePropertyValues( const Reference< XMultiServiceFactory >& i_rORB,
391         const Sequence< Property >& i_rProperties, const ::rtl::OUString& i_rTitle )
392     {
393 	    // note: empty sequence means "get values of all supported properties".
394         ::rtl::Reference< ::ucbhelper::PropertyValueSet > xRow = new ::ucbhelper::PropertyValueSet( i_rORB );
395 
396 	    const sal_Int32 nCount = i_rProperties.getLength();
397 	    if ( nCount )
398 	    {
399             Reference< XPropertySet > xAdditionalPropSet;
400 
401             const Property* pProps = i_rProperties.getConstArray();
402 		    for ( sal_Int32 n = 0; n < nCount; ++n )
403 		    {
404                 const Property& rProp = pProps[ n ];
405 
406 			    // Process Core properties.
407                 if ( rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) )
408                 {
409                     xRow->appendString ( rProp, ContentProvider::getArtificialNodeContentType() );
410 			    }
411                 else if ( rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Title" ) ) )
412 			    {
413 				    xRow->appendString ( rProp, i_rTitle );
414 			    }
415                 else if ( rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) )
416 			    {
417 				    xRow->appendBoolean( rProp, sal_False );
418 			    }
419                 else if ( rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) )
420 			    {
421 				    xRow->appendBoolean( rProp, sal_True );
422 			    }
423 			    else
424 			    {
425 				    // append empty entry.
426 				    xRow->appendVoid( rProp );
427 			    }
428 		    }
429 	    }
430 	    else
431 	    {
432 		    // Append all Core Properties.
433 		    xRow->appendString ( Property( ::rtl::OUString::createFromAscii( "ContentType" ),
434 					      -1,
435                           getCppuType( static_cast< const ::rtl::OUString * >( 0 ) ),
436                           PropertyAttribute::BOUND | PropertyAttribute::READONLY ),
437 			    ContentProvider::getArtificialNodeContentType() );
438 		    xRow->appendString ( Property( ::rtl::OUString::createFromAscii( "Title" ),
439 					      -1,
440                           getCppuType( static_cast< const ::rtl::OUString * >( 0 ) ),
441                           PropertyAttribute::BOUND | PropertyAttribute::READONLY ),
442 			    i_rTitle );
443 		    xRow->appendBoolean( Property( ::rtl::OUString::createFromAscii( "IsDocument" ),
444 					      -1,
445 					      getCppuBooleanType(),
446                           PropertyAttribute::BOUND | PropertyAttribute::READONLY ),
447 			    sal_False );
448 		    xRow->appendBoolean( Property( ::rtl::OUString::createFromAscii( "IsFolder" ),
449 					      -1,
450 					      getCppuBooleanType(),
451                           PropertyAttribute::BOUND | PropertyAttribute::READONLY ),
452 			    sal_True );
453 	    }
454 
455         return Reference< XRow >( xRow.get() );
456     }
457 
458     //------------------------------------------------------------------------------------------------------------------
getPhysicalURL() const459     ::rtl::OUString Content::getPhysicalURL() const
460     {
461         ENSURE_OR_RETURN( m_eExtContentType != E_ROOT, "illegal call", ::rtl::OUString() );
462 
463         // create an ucb::XContent for the physical file within the deployed extension
464         const ::comphelper::ComponentContext aContext( m_xSMgr );
465         const Reference< XPackageInformationProvider > xPackageInfo(
466             aContext.getSingleton( "com.sun.star.deployment.PackageInformationProvider" ), UNO_QUERY_THROW );
467         const ::rtl::OUString sPackageLocation( xPackageInfo->getPackageLocation( m_sExtensionId ) );
468 
469         if ( m_sPathIntoExtension.getLength() == 0 )
470             return sPackageLocation;
471         return lcl_compose( sPackageLocation, m_sPathIntoExtension );
472     }
473 
474     //------------------------------------------------------------------------------------------------------------------
getPropertyValues(const Sequence<Property> & i_rProperties,const Reference<XCommandEnvironment> & i_rEnv)475     Reference< XRow > Content::getPropertyValues( const Sequence< Property >& i_rProperties, const Reference< XCommandEnvironment >& i_rEnv )
476     {
477         ::osl::Guard< ::osl::Mutex > aGuard( m_aMutex );
478 
479         switch ( m_eExtContentType )
480         {
481         case E_ROOT:
482 	        return getArtificialNodePropertyValues( m_xSMgr, i_rProperties, ContentProvider::getRootURL() );
483         case E_EXTENSION_ROOT:
484 	        return getArtificialNodePropertyValues( m_xSMgr, i_rProperties, m_sExtensionId );
485         case E_EXTENSION_CONTENT:
486         {
487             const ::rtl::OUString sPhysicalContentURL( getPhysicalURL() );
488             ::ucbhelper::Content aRequestedContent( sPhysicalContentURL, i_rEnv );
489 
490             // translate the property request
491             Sequence< ::rtl::OUString > aPropertyNames( i_rProperties.getLength() );
492             ::std::transform(
493                 i_rProperties.getConstArray(),
494                 i_rProperties.getConstArray() + i_rProperties.getLength(),
495                 aPropertyNames.getArray(),
496                 SelectPropertyName()
497             );
498             const Sequence< Any > aPropertyValues = aRequestedContent.getPropertyValues( aPropertyNames );
499             const ::rtl::Reference< ::ucbhelper::PropertyValueSet > xValueRow = new ::ucbhelper::PropertyValueSet( m_xSMgr );
500             sal_Int32 i=0;
501             for (   const Any* value = aPropertyValues.getConstArray();
502                     value != aPropertyValues.getConstArray() + aPropertyValues.getLength();
503                     ++value, ++i
504                 )
505             {
506                 xValueRow->appendObject( aPropertyNames[i], *value );
507             }
508             return xValueRow.get();
509         }
510 
511         default:
512             OSL_ENSURE( false, "Content::getPropertyValues: unhandled case!" );
513             break;
514         }
515 
516         OSL_ENSURE( false, "Content::getPropertyValues: unreachable!" );
517         return NULL;
518     }
519 
520     //------------------------------------------------------------------------------------------------------------------
setPropertyValues(const Sequence<PropertyValue> & i_rValues,const Reference<XCommandEnvironment> &)521     Sequence< Any > Content::setPropertyValues( const Sequence< PropertyValue >& i_rValues, const Reference< XCommandEnvironment >& /* xEnv */)
522     {
523         ::osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
524 
525         Sequence< Any > aRet( i_rValues.getLength() );
526         Sequence< PropertyChangeEvent > aChanges( i_rValues.getLength() );
527 
528         PropertyChangeEvent aEvent;
529         aEvent.Source         = static_cast< cppu::OWeakObject * >( this );
530 	    aEvent.Further 		  = sal_False;
531         aEvent.PropertyHandle = -1;
532 
533         const PropertyValue* pValues = i_rValues.getConstArray();
534 	    const sal_Int32 nCount = i_rValues.getLength();
535 
536 	    for ( sal_Int32 n = 0; n < nCount; ++n, ++pValues )
537 	    {
538 		    // all our properties are read-only ...
539             aRet[ n ] <<= IllegalAccessException( ::rtl::OUString::createFromAscii( "property is read-only." ), *this );
540 	    }
541 
542         return aRet;
543     }
544 
545     //------------------------------------------------------------------------------------------------------------------
getCommands(const Reference<XCommandEnvironment> &)546     Sequence< CommandInfo > Content::getCommands( const Reference< XCommandEnvironment > & /*xEnv*/ )
547     {
548 	    sal_uInt32 nCommandCount = 5;
549         static const CommandInfo aCommandInfoTable[] =
550 	    {
551 		    ///////////////////////////////////////////////////////////////
552 		    // Mandatory commands
553 		    ///////////////////////////////////////////////////////////////
554             CommandInfo(
555                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ),
556 			    -1,
557 			    getCppuVoidType()
558 		    ),
559             CommandInfo(
560                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ),
561 			    -1,
562 			    getCppuVoidType()
563 		    ),
564             CommandInfo(
565                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ),
566 			    -1,
567                 getCppuType(
568                     static_cast< Sequence< Property > * >( 0 ) )
569 		    ),
570             CommandInfo(
571                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ),
572 			    -1,
573                 getCppuType(
574                     static_cast< Sequence< PropertyValue > * >( 0 ) )
575 		    )
576 		    ///////////////////////////////////////////////////////////////
577 		    // Optional standard commands
578 		    ///////////////////////////////////////////////////////////////
579             , CommandInfo(
580                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ),
581 			    -1,
582                 getCppuType( static_cast< OpenCommandArgument2 * >( 0 ) )
583 		    )
584 	    };
585 
586         return Sequence< CommandInfo >( aCommandInfoTable, nCommandCount );
587     }
588 
589     //------------------------------------------------------------------------------------------------------------------
getProperties(const Reference<XCommandEnvironment> &)590     Sequence< Property > Content::getProperties( const Reference< XCommandEnvironment > & /*xEnv*/ )
591     {
592         static Property aProperties[] =
593 	    {
594             Property(
595                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ),
596 			    -1,
597                 getCppuType( static_cast< const ::rtl::OUString * >( 0 ) ),
598                 PropertyAttribute::BOUND | PropertyAttribute::READONLY
599 		    ),
600             Property(
601                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ),
602 			    -1,
603 			    getCppuBooleanType(),
604                 PropertyAttribute::BOUND | PropertyAttribute::READONLY
605 		    ),
606             Property(
607                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ),
608 			    -1,
609 			    getCppuBooleanType(),
610                 PropertyAttribute::BOUND | PropertyAttribute::READONLY
611 		    ),
612             Property(
613                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ),
614 			    -1,
615                 getCppuType( static_cast< const ::rtl::OUString * >( 0 ) ),
616                 PropertyAttribute::BOUND | PropertyAttribute::READONLY
617 		    )
618 	    };
619         return Sequence< Property >( aProperties, sizeof( aProperties ) / sizeof( aProperties[0] ) );
620     }
621 
622     //------------------------------------------------------------------------------------------------------------------
impl_isFolder()623     bool Content::impl_isFolder()
624     {
625         if ( !!m_aIsFolder )
626             return *m_aIsFolder;
627 
628         bool bIsFolder = false;
629         try
630         {
631             Sequence< Property > aProps(1);
632             aProps[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) );
633             Reference< XRow > xRow( getPropertyValues( aProps, NULL ), UNO_SET_THROW );
634             bIsFolder = xRow->getBoolean(1);
635         }
636         catch( const Exception& )
637         {
638         	DBG_UNHANDLED_EXCEPTION();
639         }
640         m_aIsFolder.reset( bIsFolder );
641         return *m_aIsFolder;
642     }
643 
644     //------------------------------------------------------------------------------------------------------------------
impl_determineContentType()645     void Content::impl_determineContentType()
646     {
647         if ( !!m_aContentType )
648             return;
649 
650         m_aContentType.reset( ContentProvider::getArtificialNodeContentType() );
651         if ( m_eExtContentType == E_EXTENSION_CONTENT )
652         {
653             try
654             {
655                 Sequence< Property > aProps(1);
656                 aProps[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) );
657                 Reference< XRow > xRow( getPropertyValues( aProps, NULL ), UNO_SET_THROW );
658                 m_aContentType.reset( xRow->getString(1) );
659             }
660             catch( const Exception& )
661             {
662         	    DBG_UNHANDLED_EXCEPTION();
663             }
664         }
665     }
666 
667 //......................................................................................................................
668 } } }   // namespace ucp::ext
669 //......................................................................................................................
670