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 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_ucbhelper.hxx"
26 
27 /**************************************************************************
28 								TODO
29  **************************************************************************
30 
31  *************************************************************************/
32 
33 #include "osl/diagnose.h"
34 
35 #include "com/sun/star/beans/PropertyAttribute.hpp"
36 #include "com/sun/star/beans/XPropertyAccess.hpp"
37 #include "com/sun/star/lang/IllegalAccessException.hpp"
38 #include "com/sun/star/sdbc/XRow.hpp"
39 #include "com/sun/star/ucb/XCommandInfo.hpp"
40 #include "com/sun/star/ucb/XPersistentPropertySet.hpp"
41 #include "ucbhelper/contentidentifier.hxx"
42 #include "ucbhelper/propertyvalueset.hxx"
43 #include "ucbhelper/cancelcommandexecution.hxx"
44 
45 #include "myucp_content.hxx"
46 #include "myucp_provider.hxx"
47 
48 #ifdef IMPLEMENT_COMMAND_INSERT
49 #include "com/sun/star/ucb/InsertCommandArgument.hpp"
50 #include "com/sun/star/ucb/MissingInputStreamException.hpp"
51 #include "com/sun/star/ucb/MissingPropertiesException.hpp"
52 #endif
53 #ifdef IMPLEMENT_COMMAND_OPEN
54 #include "com/sun/star/io/XOutputStream.hpp"
55 #include "com/sun/star/io/XActiveDataSink.hpp"
56 #include "com/sun/star/ucb/OpenCommandArgument2.hpp"
57 #include "com/sun/star/ucb/OpenMode.hpp"
58 #include "com/sun/star/ucb/UnsupportedDataSinkException.hpp"
59 #include "com/sun/star/ucb/UnsupportedOpenModeException.hpp"
60 #include "myucp_resultset.hxx"
61 #endif
62 
63 using namespace com::sun::star;
64 
65 // @@@ Adjust namespace name.
66 using namespace myucp;
67 
68 //=========================================================================
69 //=========================================================================
70 //
71 // Content Implementation.
72 //
73 //=========================================================================
74 //=========================================================================
75 
Content(const uno::Reference<lang::XMultiServiceFactory> & rxSMgr,::ucbhelper::ContentProviderImplHelper * pProvider,const uno::Reference<ucb::XContentIdentifier> & Identifier)76 Content::Content( const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
77                   ::ucbhelper::ContentProviderImplHelper* pProvider,
78                   const uno::Reference< ucb::XContentIdentifier >& Identifier )
79 : ContentImplHelper( rxSMgr, pProvider, Identifier )
80 {
81 	// @@@ Fill m_aProps here or implement lazy evaluation logic for this.
82 	// m_aProps.aTitle       =
83 	// m_aprops.aContentType =
84 	// m_aProps.bIsDocument  =
85 	// m_aProps.bIsFolder    =
86 }
87 
88 //=========================================================================
89 // virtual
~Content()90 Content::~Content()
91 {
92 }
93 
94 //=========================================================================
95 //
96 // XInterface methods.
97 //
98 //=========================================================================
99 
100 // virtual
acquire()101 void SAL_CALL Content::acquire()
102     throw()
103 {
104 	ContentImplHelper::acquire();
105 }
106 
107 //=========================================================================
108 // virtual
release()109 void SAL_CALL Content::release()
110     throw()
111 {
112 	ContentImplHelper::release();
113 }
114 
115 //=========================================================================
116 // virtual
queryInterface(const uno::Type & rType)117 uno::Any SAL_CALL Content::queryInterface( const uno::Type & rType )
118     throw ( uno::RuntimeException )
119 {
120     uno::Any aRet;
121 
122 	// @@@ Add support for additional interfaces.
123 #if 0
124   	aRet = cppu::queryInterface( rType,
125                                  static_cast< yyy::Xxxxxxxxx * >( this ) );
126 #endif
127 
128  	return aRet.hasValue() ? aRet : ContentImplHelper::queryInterface( rType );
129 }
130 
131 //=========================================================================
132 //
133 // XTypeProvider methods.
134 //
135 //=========================================================================
136 
137 XTYPEPROVIDER_COMMON_IMPL( Content );
138 
139 //=========================================================================
140 // virtual
getTypes()141 uno::Sequence< uno::Type > SAL_CALL Content::getTypes()
142     throw( uno::RuntimeException )
143 {
144 	// @@@ Add own interfaces.
145 
146     static cppu::OTypeCollection* pCollection = 0;
147 
148 	if ( !pCollection )
149 	{
150 		osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
151 	  	if ( !pCollection )
152 	  	{
153             static cppu::OTypeCollection aCollection(
154                 CPPU_TYPE_REF( lang::XTypeProvider ),
155                 CPPU_TYPE_REF( lang::XServiceInfo ),
156                 CPPU_TYPE_REF( lang::XComponent ),
157                 CPPU_TYPE_REF( ucb::XContent ),
158                 CPPU_TYPE_REF( ucb::XCommandProcessor ),
159                 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
160                 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
161                 CPPU_TYPE_REF( beans::XPropertyContainer ),
162                 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
163                 CPPU_TYPE_REF( container::XChild ) );
164 	  		pCollection = &aCollection;
165 		}
166 	}
167 
168 	return (*pCollection).getTypes();
169 }
170 
171 //=========================================================================
172 //
173 // XServiceInfo methods.
174 //
175 //=========================================================================
176 
177 // virtual
getImplementationName()178 rtl::OUString SAL_CALL Content::getImplementationName()
179     throw( uno::RuntimeException )
180 {
181     // @@@ Adjust implementation name.
182     // Prefix with reversed company domain name.
183     return rtl::OUString::createFromAscii( "com.sun.star.comp.myucp.Content" );
184 }
185 
186 //=========================================================================
187 // virtual
getSupportedServiceNames()188 uno::Sequence< rtl::OUString > SAL_CALL Content::getSupportedServiceNames()
189     throw( uno::RuntimeException )
190 {
191 	// @@@ Adjust macro name.
192     uno::Sequence< rtl::OUString > aSNS( 1 );
193 	aSNS.getArray()[ 0 ]
194             = rtl::OUString::createFromAscii( MYUCP_CONTENT_SERVICE_NAME );
195 	return aSNS;
196 }
197 
198 //=========================================================================
199 //
200 // XContent methods.
201 //
202 //=========================================================================
203 
204 // virtual
getContentType()205 rtl::OUString SAL_CALL Content::getContentType()
206     throw( uno::RuntimeException )
207 {
208 	// @@@ Adjust macro name ( def in myucp_provider.hxx ).
209     return rtl::OUString::createFromAscii( MYUCP_CONTENT_TYPE );
210 }
211 
212 //=========================================================================
213 //
214 // XCommandProcessor methods.
215 //
216 //=========================================================================
217 
218 // virtual
execute(const ucb::Command & aCommand,sal_Int32,const uno::Reference<ucb::XCommandEnvironment> & Environment)219 uno::Any SAL_CALL Content::execute(
220         const ucb::Command& aCommand,
221         sal_Int32 /* CommandId */,
222         const uno::Reference< ucb::XCommandEnvironment >& Environment )
223     throw( uno::Exception,
224            ucb::CommandAbortedException,
225            uno::RuntimeException )
226 {
227     uno::Any aRet;
228 
229     if ( aCommand.Name.equalsAsciiL(
230 			RTL_CONSTASCII_STRINGPARAM( "getPropertyValues" ) ) )
231 	{
232 		//////////////////////////////////////////////////////////////////
233 		// getPropertyValues
234 		//////////////////////////////////////////////////////////////////
235 
236         uno::Sequence< beans::Property > Properties;
237 		if ( !( aCommand.Argument >>= Properties ) )
238 		{
239             OSL_ENSURE( sal_False, "Wrong argument type!" );
240             ::ucbhelper::cancelCommandExecution(
241                 uno::makeAny( lang::IllegalArgumentException(
242                                     rtl::OUString(),
243                                     static_cast< cppu::OWeakObject * >( this ),
244                                     -1 ) ),
245                 Environment );
246             // Unreachable
247 		}
248 
249         aRet <<= getPropertyValues( Properties, Environment );
250 	}
251     else if ( aCommand.Name.equalsAsciiL(
252 				RTL_CONSTASCII_STRINGPARAM( "setPropertyValues" ) ) )
253     {
254 		//////////////////////////////////////////////////////////////////
255 		// setPropertyValues
256 		//////////////////////////////////////////////////////////////////
257 
258         uno::Sequence< beans::PropertyValue > aProperties;
259 		if ( !( aCommand.Argument >>= aProperties ) )
260 		{
261             OSL_ENSURE( sal_False, "Wrong argument type!" );
262             ::ucbhelper::cancelCommandExecution(
263                 uno::makeAny( lang::IllegalArgumentException(
264                                     rtl::OUString(),
265                                     static_cast< cppu::OWeakObject * >( this ),
266                                     -1 ) ),
267                 Environment );
268             // Unreachable
269         }
270 
271 		if ( !aProperties.getLength() )
272 		{
273             OSL_ENSURE( sal_False, "No properties!" );
274             ::ucbhelper::cancelCommandExecution(
275                 uno::makeAny( lang::IllegalArgumentException(
276                                     rtl::OUString(),
277                                     static_cast< cppu::OWeakObject * >( this ),
278                                     -1 ) ),
279                 Environment );
280             // Unreachable
281         }
282 
283         aRet <<= setPropertyValues( aProperties, Environment );
284 	}
285     else if ( aCommand.Name.equalsAsciiL(
286 				RTL_CONSTASCII_STRINGPARAM( "getPropertySetInfo" ) ) )
287     {
288 		//////////////////////////////////////////////////////////////////
289 		// getPropertySetInfo
290 		//////////////////////////////////////////////////////////////////
291 
292 		// Note: Implemented by base class.
293 		aRet <<= getPropertySetInfo( Environment );
294 	}
295     else if ( aCommand.Name.equalsAsciiL(
296 				RTL_CONSTASCII_STRINGPARAM( "getCommandInfo" ) ) )
297     {
298 		//////////////////////////////////////////////////////////////////
299 		// getCommandInfo
300 		//////////////////////////////////////////////////////////////////
301 
302 		// Note: Implemented by base class.
303 		aRet <<= getCommandInfo( Environment );
304 	}
305 #ifdef IMPLEMENT_COMMAND_OPEN
306     else if ( aCommand.Name.equalsAsciiL(
307 				RTL_CONSTASCII_STRINGPARAM( "open" ) ) )
308     {
309         ucb::OpenCommandArgument2 aOpenCommand;
310       	if ( !( aCommand.Argument >>= aOpenCommand ) )
311 		{
312             OSL_ENSURE( sal_False, "Wrong argument type!" );
313             ::ucbhelper::cancelCommandExecution(
314                 uno::makeAny( lang::IllegalArgumentException(
315                                     rtl::OUString(),
316                                     static_cast< cppu::OWeakObject * >( this ),
317                                     -1 ) ),
318                 Environment );
319             // Unreachable
320         }
321 
322         sal_Bool bOpenFolder =
323             ( ( aOpenCommand.Mode == ucb::OpenMode::ALL ) ||
324               ( aOpenCommand.Mode == ucb::OpenMode::FOLDERS ) ||
325               ( aOpenCommand.Mode == ucb::OpenMode::DOCUMENTS ) );
326 
327         if ( bOpenFolder /*&& isFolder( Environment )*/ )
328 		{
329             // open as folder - return result set
330 
331             uno::Reference< ucb::XDynamicResultSet > xSet
332                             = new DynamicResultSet( m_xSMgr,
333 													this,
334 													aOpenCommand,
335 													Environment );
336     		aRet <<= xSet;
337   		}
338 
339         if ( aOpenCommand.Sink.is() )
340         {
341             // Open document - supply document data stream.
342 
343             // Check open mode
344             if ( ( aOpenCommand.Mode
345                     == ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE ) ||
346                  ( aOpenCommand.Mode
347                     == ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE ) )
348             {
349                 // Unsupported.
350                 ::ucbhelper::cancelCommandExecution(
351                     uno::makeAny( ucb::UnsupportedOpenModeException(
352                                     rtl::OUString(),
353                                     static_cast< cppu::OWeakObject * >( this ),
354                                     sal_Int16( aOpenCommand.Mode ) ) ),
355                     Environment );
356                 // Unreachable
357             }
358 
359 
360             rtl::OUString aURL = m_xIdentifier->getContentIdentifier();
361             uno::Reference< io::XOutputStream > xOut
362                 = uno::Reference< io::XOutputStream >(
363                     aOpenCommand.Sink, uno::UNO_QUERY );
364     		if ( xOut.is() )
365       		{
366 				// @@@ write data into xOut
367       		}
368     		else
369       		{
370                 uno::Reference< io::XActiveDataSink > xDataSink(
371                         aOpenCommand.Sink, uno::UNO_QUERY );
372       			if ( xDataSink.is() )
373 				{
374                     uno::Reference< io::XInputStream > xIn
375 						/* @@@ your XInputStream + XSeekable impl. object */;
376     				xDataSink->setInputStream( xIn );
377 				}
378       			else
379 				{
380                     // Note: aOpenCommand.Sink may contain an XStream
381                     //       implementation. Support for this type of
382                     //       sink is optional...
383                     ::ucbhelper::cancelCommandExecution(
384                         uno::makeAny( ucb::UnsupportedDataSinkException(
385                                 rtl::OUString(),
386                                 static_cast< cppu::OWeakObject * >( this ),
387                                 aOpenCommand.Sink ) ),
388                         Environment );
389                     // Unreachable
390                 }
391 	  		}
392 		}
393 	}
394 #endif // IMPLEMENT_COMMAND_OPEN
395 
396 #ifdef IMPLEMENT_COMMAND_INSERT
397     else if ( aCommand.Name.equalsAsciiL(
398 				RTL_CONSTASCII_STRINGPARAM( "insert" ) ) )
399     {
400 		//////////////////////////////////////////////////////////////////
401 		// insert
402 		//////////////////////////////////////////////////////////////////
403 
404         ucb::InsertCommandArgument arg;
405       	if ( !( aCommand.Argument >>= arg ) )
406 		{
407 	  		OSL_ENSURE( sal_False, "Wrong argument type!" );
408             ::ucbhelper::cancelCommandExecution(
409                 uno::makeAny( lang::IllegalArgumentException(
410                                     rtl::OUString(),
411                                     static_cast< cppu::OWeakObject * >( this ),
412                                     -1 ) ),
413                 Environment );
414             // Unreachable
415 		}
416 
417       	insert( arg.Data, arg.ReplaceExisting, Environment );
418     }
419 #endif // IMPLEMENT_COMMAND_INSERT
420 
421 #ifdef IMPLEMENT_COMMAND_DELETE
422     else if ( aCommand.Name.equalsAsciiL(
423 					RTL_CONSTASCII_STRINGPARAM( "delete" ) ) )
424     {
425 		//////////////////////////////////////////////////////////////////
426 		// delete
427 		//////////////////////////////////////////////////////////////////
428 
429 		sal_Bool bDeletePhysical = sal_False;
430 		aCommand.Argument >>= bDeletePhysical;
431 		destroy( bDeletePhysical );
432 
433 		// Remove own and all children's Additional Core Properties.
434 		removeAdditionalPropertySet( sal_True );
435 
436 		// Remove own and all childrens(!) persistent data.
437 //		removeData();
438 	}
439 #endif // IMPLEMENT_COMMAND_DELETE
440 	else
441 	{
442 		//////////////////////////////////////////////////////////////////
443 		// Unsupported command
444 		//////////////////////////////////////////////////////////////////
445 
446         OSL_ENSURE( sal_False, "Content::execute - unsupported command!" );
447 
448         ::ucbhelper::cancelCommandExecution(
449             uno::makeAny( ucb::UnsupportedCommandException(
450                             rtl::OUString(),
451                             static_cast< cppu::OWeakObject * >( this ) ) ),
452             Environment );
453         // Unreachable
454     }
455 
456 	return aRet;
457 }
458 
459 //=========================================================================
460 // virtual
abort(sal_Int32)461 void SAL_CALL Content::abort( sal_Int32 )
462     throw( uno::RuntimeException )
463 {
464 	// @@@ Implement logic to abort running commands, if this makes
465 	//     sense for your content.
466 }
467 
468 //=========================================================================
469 //
470 // Non-interface methods.
471 //
472 //=========================================================================
473 
474 // virtual
getParentURL()475 rtl::OUString Content::getParentURL()
476 {
477     rtl::OUString aURL = m_xIdentifier->getContentIdentifier();
478 
479     // @@@ Extract URL of parent from aURL and return it...
480 
481     return rtl::OUString();
482 }
483 
484 //=========================================================================
485 // static
getPropertyValues(const uno::Reference<lang::XMultiServiceFactory> & rSMgr,const uno::Sequence<beans::Property> & rProperties,const ContentProperties & rData,const rtl::Reference<::ucbhelper::ContentProviderImplHelper> & rProvider,const rtl::OUString & rContentId)486 uno::Reference< sdbc::XRow > Content::getPropertyValues(
487             const uno::Reference< lang::XMultiServiceFactory >& rSMgr,
488             const uno::Sequence< beans::Property >& rProperties,
489             const ContentProperties& rData,
490             const rtl::Reference<
491                 ::ucbhelper::ContentProviderImplHelper >& rProvider,
492             const rtl::OUString& rContentId )
493 {
494 	// Note: Empty sequence means "get values of all supported properties".
495 
496     rtl::Reference< ::ucbhelper::PropertyValueSet > xRow
497         = new ::ucbhelper::PropertyValueSet( rSMgr );
498 
499 	sal_Int32 nCount = rProperties.getLength();
500 	if ( nCount )
501 	{
502         uno::Reference< beans::XPropertySet > xAdditionalPropSet;
503 		sal_Bool bTriedToGetAdditonalPropSet = sal_False;
504 
505         const beans::Property* pProps = rProperties.getConstArray();
506 		for ( sal_Int32 n = 0; n < nCount; ++n )
507 		{
508             const beans::Property& rProp = pProps[ n ];
509 
510 			// Process Core properties.
511 
512             if ( rProp.Name.equalsAsciiL(
513 					RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) )
514             {
515 				xRow->appendString ( rProp, rData.aContentType );
516 			}
517             else if ( rProp.Name.equalsAsciiL(
518                     RTL_CONSTASCII_STRINGPARAM( "Title" ) ) )
519 			{
520 				xRow->appendString ( rProp, rData.aTitle );
521 			}
522             else if ( rProp.Name.equalsAsciiL(
523                     RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) )
524 			{
525 				xRow->appendBoolean( rProp, rData.bIsDocument );
526 			}
527             else if ( rProp.Name.equalsAsciiL(
528                     RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) )
529 			{
530 				xRow->appendBoolean( rProp, rData.bIsFolder );
531 			}
532 
533 			// @@@ Process other properties supported directly.
534 #if 0
535             else if ( rProp.Name.equalsAsciiL(
536                     RTL_CONSTASCII_STRINGPARAM( "xxxxxx" ) ) )
537 			{
538 			}
539 #endif
540 			else
541 			{
542 				// @@@ Note: If your data source supports adding/removing
543 				//     properties, you should implement the interface
544 				//     XPropertyContainer by yourself and supply your own
545 				//     logic here. The base class uses the service
546 				//     "com.sun.star.ucb.Store" to maintain Additional Core
547 				//     properties. But using server functionality is preferred!
548 
549 				// Not a Core Property! Maybe it's an Additional Core Property?!
550 
551 				if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() )
552 				{
553 					xAdditionalPropSet
554                         = uno::Reference< beans::XPropertySet >(
555 							rProvider->getAdditionalPropertySet( rContentId,
556 																 sal_False ),
557                             uno::UNO_QUERY );
558 					bTriedToGetAdditonalPropSet = sal_True;
559 				}
560 
561 				if ( xAdditionalPropSet.is() )
562 				{
563 					if ( !xRow->appendPropertySetValue(
564 												xAdditionalPropSet,
565 												rProp ) )
566 					{
567 						// Append empty entry.
568 						xRow->appendVoid( rProp );
569 					}
570 				}
571 				else
572 				{
573 					// Append empty entry.
574 					xRow->appendVoid( rProp );
575 				}
576 			}
577 		}
578 	}
579 	else
580 	{
581 		// Append all Core Properties.
582 		xRow->appendString (
583             beans::Property( rtl::OUString::createFromAscii( "ContentType" ),
584 					  -1,
585                       getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
586                       beans::PropertyAttribute::BOUND
587                         | beans::PropertyAttribute::READONLY ),
588 			rData.aContentType );
589 		xRow->appendString (
590             beans::Property( rtl::OUString::createFromAscii( "Title" ),
591 					  -1,
592                       getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
593                       beans::PropertyAttribute::BOUND ),
594 			rData.aTitle );
595 		xRow->appendBoolean(
596             beans::Property( rtl::OUString::createFromAscii( "IsDocument" ),
597 					  -1,
598 					  getCppuBooleanType(),
599                       beans::PropertyAttribute::BOUND
600                         | beans::PropertyAttribute::READONLY ),
601 			rData.bIsDocument );
602 		xRow->appendBoolean(
603             beans::Property( rtl::OUString::createFromAscii( "IsFolder" ),
604 					  -1,
605 					  getCppuBooleanType(),
606                       beans::PropertyAttribute::BOUND
607                         | beans::PropertyAttribute::READONLY ),
608 			rData.bIsFolder );
609 
610 		// @@@ Append other properties supported directly.
611 
612 		// @@@ Note: If your data source supports adding/removing
613 		//     properties, you should implement the interface
614 		//     XPropertyContainer by yourself and supply your own
615 		//     logic here. The base class uses the service
616 		//     "com.sun.star.ucb.Store" to maintain Additional Core
617 		//     properties. But using server functionality is preferred!
618 
619 		// Append all Additional Core Properties.
620 
621         uno::Reference< beans::XPropertySet > xSet(
622 			rProvider->getAdditionalPropertySet( rContentId, sal_False ),
623             uno::UNO_QUERY );
624 		xRow->appendPropertySet( xSet );
625 	}
626 
627     return uno::Reference< sdbc::XRow >( xRow.get() );
628 }
629 
630 //=========================================================================
getPropertyValues(const uno::Sequence<beans::Property> & rProperties,const uno::Reference<ucb::XCommandEnvironment> &)631 uno::Reference< sdbc::XRow > Content::getPropertyValues(
632             const uno::Sequence< beans::Property >& rProperties,
633             const uno::Reference< ucb::XCommandEnvironment >& /* xEnv */)
634 {
635 	osl::Guard< osl::Mutex > aGuard( m_aMutex );
636 	return getPropertyValues( m_xSMgr,
637 							  rProperties,
638 							  m_aProps,
639                               rtl::Reference<
640                                 ::ucbhelper::ContentProviderImplHelper >(
641                                     m_xProvider.get() ),
642 							  m_xIdentifier->getContentIdentifier() );
643 }
644 
645 //=========================================================================
setPropertyValues(const uno::Sequence<beans::PropertyValue> & rValues,const uno::Reference<ucb::XCommandEnvironment> &)646 uno::Sequence< uno::Any > Content::setPropertyValues(
647             const uno::Sequence< beans::PropertyValue >& rValues,
648             const uno::Reference< ucb::XCommandEnvironment >& /* xEnv */)
649 {
650 	osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
651 
652     uno::Sequence< uno::Any > aRet( rValues.getLength() );
653     uno::Sequence< beans::PropertyChangeEvent > aChanges( rValues.getLength() );
654 	sal_Int32 nChanged = 0;
655 
656     beans::PropertyChangeEvent aEvent;
657     aEvent.Source         = static_cast< cppu::OWeakObject * >( this );
658 	aEvent.Further 		  = sal_False;
659 //	aEvent.PropertyName	  =
660 	aEvent.PropertyHandle = -1;
661 //	aEvent.OldValue		  =
662 //	aEvent.NewValue       =
663 
664     const beans::PropertyValue* pValues = rValues.getConstArray();
665 	sal_Int32 nCount = rValues.getLength();
666 
667     uno::Reference< ucb::XPersistentPropertySet > xAdditionalPropSet;
668 	sal_Bool bTriedToGetAdditonalPropSet = sal_False;
669 
670 	for ( sal_Int32 n = 0; n < nCount; ++n )
671 	{
672         const beans::PropertyValue& rValue = pValues[ n ];
673 
674         if ( rValue.Name.equalsAsciiL(
675                         RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) )
676         {
677 			// Read-only property!
678             aRet[ n ] <<= lang::IllegalAccessException(
679                             rtl::OUString::createFromAscii(
680                                 "Property is read-only!" ),
681                             static_cast< cppu::OWeakObject * >( this ) );
682 		}
683         else if ( rValue.Name.equalsAsciiL(
684                         RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) )
685 		{
686 			// Read-only property!
687             aRet[ n ] <<= lang::IllegalAccessException(
688                             rtl::OUString::createFromAscii(
689                                 "Property is read-only!" ),
690                             static_cast< cppu::OWeakObject * >( this ) );
691 		}
692         else if ( rValue.Name.equalsAsciiL(
693                         RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) )
694 		{
695 			// Read-only property!
696             aRet[ n ] <<= lang::IllegalAccessException(
697                             rtl::OUString::createFromAscii(
698                                 "Property is read-only!" ),
699                             static_cast< cppu::OWeakObject * >( this ) );
700 		}
701         else if ( rValue.Name.equalsAsciiL(
702                         RTL_CONSTASCII_STRINGPARAM( "Title" ) ) )
703 		{
704             rtl::OUString aNewValue;
705 			if ( rValue.Value >>= aNewValue )
706 			{
707 				if ( aNewValue != m_aProps.aTitle )
708 				{
709 					aEvent.PropertyName = rValue.Name;
710                     aEvent.OldValue     = uno::makeAny( m_aProps.aTitle );
711                     aEvent.NewValue     = uno::makeAny( aNewValue );
712 
713 					aChanges.getArray()[ nChanged ] = aEvent;
714 
715 					m_aProps.aTitle = aNewValue;
716 					nChanged++;
717 				}
718                 else
719                 {
720                     // Old value equals new value. No error!
721                 }
722 			}
723             else
724             {
725                 aRet[ n ] <<= beans::IllegalTypeException(
726                                 rtl::OUString::createFromAscii(
727                                     "Property value has wrong type!" ),
728                                 static_cast< cppu::OWeakObject * >( this ) );
729             }
730 		}
731 
732 		// @@@ Process other properties supported directly.
733 #if 0
734         else if ( rValue.Name.equalsAsciiL(
735                         RTL_CONSTASCII_STRINGPARAM( "xxxxxx" ) ) )
736 		{
737 		}
738 #endif
739 		else
740 		{
741 			// @@@ Note: If your data source supports adding/removing
742 			//     properties, you should implement the interface
743 			//     XPropertyContainer by yourself and supply your own
744 			//     logic here. The base class uses the service
745 			//     "com.sun.star.ucb.Store" to maintain Additional Core
746 			//     properties. But using server functionality is preferred!
747 
748 			// Not a Core Property! Maybe it's an Additional Core Property?!
749 
750 			if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() )
751 			{
752 				xAdditionalPropSet = getAdditionalPropertySet( sal_False );
753 				bTriedToGetAdditonalPropSet = sal_True;
754 			}
755 
756 			if ( xAdditionalPropSet.is() )
757 			{
758 				try
759 				{
760                     uno::Any aOldValue
761                         = xAdditionalPropSet->getPropertyValue( rValue.Name );
762 					if ( aOldValue != rValue.Value )
763 					{
764 						xAdditionalPropSet->setPropertyValue(
765 												rValue.Name, rValue.Value );
766 
767 						aEvent.PropertyName = rValue.Name;
768 						aEvent.OldValue		= aOldValue;
769 						aEvent.NewValue     = rValue.Value;
770 
771 						aChanges.getArray()[ nChanged ] = aEvent;
772 						nChanged++;
773 					}
774                     else
775                     {
776                         // Old value equals new value. No error!
777                     }
778 				}
779                 catch ( beans::UnknownPropertyException const & e )
780 				{
781                     aRet[ n ] <<= e;
782 				}
783                 catch ( lang::WrappedTargetException const & e )
784 				{
785                     aRet[ n ] <<= e;
786 				}
787                 catch ( beans::PropertyVetoException const & e )
788 				{
789                     aRet[ n ] <<= e;
790 				}
791                 catch ( lang::IllegalArgumentException const & e )
792 				{
793                     aRet[ n ] <<= e;
794 				}
795 			}
796             else
797             {
798                 aRet[ n ] <<= uno::Exception(
799                                 rtl::OUString::createFromAscii(
800                                     "No property set for storing the value!" ),
801                                 static_cast< cppu::OWeakObject * >( this ) );
802             }
803 		}
804 	}
805 
806 	if ( nChanged > 0 )
807 	{
808 		// @@@ Save changes.
809 //		storeData();
810 
811 		aGuard.clear();
812 		aChanges.realloc( nChanged );
813 		notifyPropertiesChange( aChanges );
814 	}
815 
816     return aRet;
817 }
818 
819 #ifdef IMPLEMENT_COMMAND_INSERT
820 
821 //=========================================================================
queryChildren(ContentRefList & rChildren)822 void Content::queryChildren( ContentRefList& rChildren )
823 {
824 	// @@@ Adapt method to your URL scheme...
825 
826 	// Obtain a list with a snapshot of all currently instanciated contents
827 	// from provider and extract the contents which are direct children
828 	// of this content.
829 
830 	::ucbhelper::ContentRefList aAllContents;
831 	m_xProvider->queryExistingContents( aAllContents );
832 
833 	::rtl::OUString aURL = m_xIdentifier->getContentIdentifier();
834 	sal_Int32 nPos = aURL.lastIndexOf( '/' );
835 
836 	if ( nPos != ( aURL.getLength() - 1 ) )
837 	{
838 		// No trailing slash found. Append.
839 		aURL += ::rtl::OUString::createFromAscii( "/" );
840 	}
841 
842 	sal_Int32 nLen = aURL.getLength();
843 
844 	::ucbhelper::ContentRefList::const_iterator it  = aAllContents.begin();
845 	::ucbhelper::ContentRefList::const_iterator end = aAllContents.end();
846 
847 	while ( it != end )
848 	{
849 		::ucbhelper::ContentImplHelperRef xChild = (*it);
850 		::rtl::OUString aChildURL
851               = xChild->getIdentifier()->getContentIdentifier();
852 
853 		// Is aURL a prefix of aChildURL?
854 		if ( ( aChildURL.getLength() > nLen ) &&
855 			 ( aChildURL.compareTo( aURL, nLen ) == 0 ) )
856 		{
857 			nPos = aChildURL.indexOf( '/', nLen );
858 
859 			if ( ( nPos == -1 ) ||
860 				 ( nPos == ( aChildURL.getLength() - 1 ) ) )
861 			{
862 				// No further slashes / only a final slash. It's a child!
863 				rChildren.push_back(
864 					ContentRef(
865 						static_cast< Content * >( xChild.get() ) ) );
866 			}
867 		}
868 		++it;
869 	}
870 }
871 
872 //=========================================================================
insert(const uno::Reference<io::XInputStream> & xInputStream,sal_Bool bReplaceExisting,const uno::Reference<ucb::XCommandEnvironment> & Environment)873 void Content::insert(
874         const uno::Reference< io::XInputStream > & xInputStream,
875         sal_Bool bReplaceExisting,
876         const uno::Reference< ucb::XCommandEnvironment >& Environment )
877     throw( uno::Exception )
878 {
879 	osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
880 
881 	// Check, if all required properties were set.
882 
883 #if 0
884     // @@@ add checks for property presence
885 	if ( m_aProps.xxxx == yyyyy )
886 	{
887         OSL_ENSURE( sal_False, "Content::insert - property value missing!" );
888 
889         uno::Sequence< rtl::OUString > aProps( 1 );
890         aProps[ 0 ] = rtl::OUString::createFromAscii( "zzzz" );
891         ::ucbhelper::cancelCommandExecution(
892             uno::makeAny( ucb::MissingPropertiesException(
893                                 rtl::OUString(),
894                                 static_cast< cppu::OWeakObject * >( this ),
895                                 aProps ) ),
896             Environment );
897         // Unreachable
898 	}
899 #endif
900 
901     bool bNeedInputStream = true; // @@@ adjust to real requirements
902     if ( bNeedInputStream && !xInputStream.is() )
903     {
904         OSL_ENSURE( sal_False, "Content::insert - No data stream!" );
905 
906         ::ucbhelper::cancelCommandExecution(
907             uno::makeAny( ucb::MissingInputStreamException(
908                             rtl::OUString(),
909                             static_cast< cppu::OWeakObject * >( this ) ) ),
910             Environment );
911         // Unreachable
912     }
913 
914 	// Assemble new content identifier...
915 
916     uno::Reference< ucb::XContentIdentifier > xId /* @@@ create content identifier */;
917 
918     // Fail, if a resource with given id already exists.
919     if ( !bReplaceExisting /*&& hasData( xId ) @@@ impl for hasData() */ )
920     {
921         uno::Any aProps
922             = uno::makeAny( beans::PropertyValue(
923                                   rtl::OUString(
924                                       RTL_CONSTASCII_USTRINGPARAM( "Uri" ) ),
925                                   -1,
926                                   uno::makeAny( xId->getContentIdentifier() ),
927                                   beans::PropertyState_DIRECT_VALUE ) );
928         ucbhelper::cancelCommandExecution(
929             ucb::IOErrorCode_ALREADY_EXISTING,
930             uno::Sequence< uno::Any >(&aProps, 1),
931             Environment,
932             rtl::OUString::createFromAscii( "content already existing!!" ),
933             this );
934         // Unreachable
935     }
936 
937 	m_xIdentifier = xId;
938 
939 //  @@@
940 //	storeData();
941 
942 	aGuard.clear();
943 	inserted();
944 }
945 
946 #endif // IMPLEMENT_COMMAND_INSERT
947 
948 #ifdef IMPLEMENT_COMMAND_DELETE
949 
950 //=========================================================================
destroy(sal_Bool bDeletePhysical)951 void Content::destroy( sal_Bool bDeletePhysical )
952     throw( uno::Exception )
953 {
954 	// @@@ take care about bDeletePhysical -> trashcan support
955 
956     uno::Reference< ucb::XContent > xThis = this;
957 
958 	deleted();
959 
960 	osl::Guard< osl::Mutex > aGuard( m_aMutex );
961 
962 	// Process instanciated children...
963 
964 	ContentRefList aChildren;
965 	queryChildren( aChildren );
966 
967 	ContentRefList::const_iterator it  = aChildren.begin();
968 	ContentRefList::const_iterator end = aChildren.end();
969 
970 	while ( it != end )
971 	{
972 		(*it)->destroy( bDeletePhysical );
973 		++it;
974 	}
975 }
976 
977 #endif // IMPLEMENT_COMMAND_DELETE
978 
979 
980