xref: /AOO41X/main/ucbhelper/workben/myucp/myucp_content.cxx (revision ac9096f48ddc8269a54878c5b102c19157b971bd)
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