xref: /trunk/main/ucb/source/ucp/odma/odma_content.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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_ucb.hxx"
26 
27 /**************************************************************************
28                                 TODO
29  **************************************************************************
30 
31  *************************************************************************/
32 #include <osl/diagnose.h>
33 #include "odma_contentprops.hxx"
34 #include <com/sun/star/ucb/XDynamicResultSet.hpp>
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/ucb/UnsupportedDataSinkException.hpp>
39 #include <com/sun/star/sdbc/XRow.hpp>
40 #include <com/sun/star/io/XOutputStream.hpp>
41 #include <com/sun/star/io/XActiveDataSink.hpp>
42 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
43 #include <com/sun/star/ucb/OpenMode.hpp>
44 #include <com/sun/star/ucb/XCommandInfo.hpp>
45 #include <com/sun/star/ucb/XPersistentPropertySet.hpp>
46 #include <ucbhelper/contentidentifier.hxx>
47 #include <ucbhelper/propertyvalueset.hxx>
48 #include <ucbhelper/cancelcommandexecution.hxx>
49 #include <com/sun/star/ucb/UnsupportedOpenModeException.hpp>
50 #include <com/sun/star/ucb/MissingInputStreamException.hpp>
51 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
52 #include <com/sun/star/ucb/MissingPropertiesException.hpp>
53 #include <com/sun/star/io/XActiveDataStreamer.hpp>
54 #include <com/sun/star/ucb/TransferInfo.hpp>
55 #include <com/sun/star/ucb/NameClash.hpp>
56 #include "odma_content.hxx"
57 #include "odma_provider.hxx"
58 #include "odma_resultset.hxx"
59 #include "odma_inputstream.hxx"
60 #include <ucbhelper/content.hxx>
61 #include <com/sun/star/uno/Exception.hpp>
62 #include <rtl/ref.hxx>
63 #include <osl/file.hxx>
64 
65 using namespace com::sun::star;
66 using namespace odma;
67 
68 //=========================================================================
69 //=========================================================================
70 //
71 // Content Implementation.
72 //
73 //=========================================================================
74 //=========================================================================
75 
Content(const uno::Reference<lang::XMultiServiceFactory> & rxSMgr,ContentProvider * pProvider,const uno::Reference<ucb::XContentIdentifier> & Identifier,const::rtl::Reference<ContentProperties> & _rProps)76 Content::Content( const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
77                   ContentProvider* pProvider,
78                   const uno::Reference< ucb::XContentIdentifier >& Identifier,
79                   const ::rtl::Reference<ContentProperties>& _rProps)
80     : ContentImplHelper( rxSMgr, pProvider, Identifier )
81     ,m_aProps(_rProps)
82     ,m_pProvider(pProvider)
83     ,m_pContent(NULL)
84 {
85     OSL_ENSURE(m_aProps.is(),"No valid ContentPropeties!");
86 }
87 
88 //=========================================================================
89 // virtual
~Content()90 Content::~Content()
91 {
92     delete m_pContent;
93 }
94 
95 //=========================================================================
96 //
97 // XInterface methods.
98 //
99 //=========================================================================
100 
101 // virtual
acquire()102 void SAL_CALL Content::acquire() throw()
103 {
104     ContentImplHelper::acquire();
105 }
106 
107 //=========================================================================
108 // virtual
release()109 void SAL_CALL Content::release() throw()
110 {
111     ContentImplHelper::release();
112 }
113 
114 //=========================================================================
115 // virtual
queryInterface(const uno::Type & rType)116 uno::Any SAL_CALL Content::queryInterface( const uno::Type & rType )
117 {
118     uno::Any aRet;
119 
120     // @@@ Add support for additional interfaces.
121 #if 0
122     aRet = cppu::queryInterface( rType,
123                                  static_cast< yyy::Xxxxxxxxx * >( this ) );
124 #endif
125 
126     return aRet.hasValue() ? aRet : ContentImplHelper::queryInterface( rType );
127 }
128 
129 //=========================================================================
130 //
131 // XTypeProvider methods.
132 //
133 //=========================================================================
134 
135 XTYPEPROVIDER_COMMON_IMPL( Content );
136 
137 //=========================================================================
138 // virtual
getTypes()139 uno::Sequence< uno::Type > SAL_CALL Content::getTypes()
140 {
141     // @@@ Add own interfaces.
142 
143     static cppu::OTypeCollection* pCollection = 0;
144 
145     if ( !pCollection )
146     {
147         osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
148         if ( !pCollection )
149         {
150             static cppu::OTypeCollection aCollection(
151                 CPPU_TYPE_REF( lang::XTypeProvider ),
152                 CPPU_TYPE_REF( lang::XServiceInfo ),
153                 CPPU_TYPE_REF( lang::XComponent ),
154                 CPPU_TYPE_REF( ucb::XContent ),
155                 CPPU_TYPE_REF( ucb::XCommandProcessor ),
156                 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
157                 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
158                 CPPU_TYPE_REF( beans::XPropertyContainer ),
159                 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
160                 CPPU_TYPE_REF( container::XChild ) );
161             pCollection = &aCollection;
162         }
163     }
164 
165     return (*pCollection).getTypes();
166 }
167 
168 //=========================================================================
169 //
170 // XServiceInfo methods.
171 //
172 //=========================================================================
173 
174 // virtual
getImplementationName()175 rtl::OUString SAL_CALL Content::getImplementationName()
176 {
177     // @@@ Adjust implementation name. Keep the prefix "com.sun.star.comp."!
178     return rtl::OUString::createFromAscii( "com.sun.star.comp.odma.Content" );
179 }
180 
181 //=========================================================================
182 // virtual
getSupportedServiceNames()183 uno::Sequence< rtl::OUString > SAL_CALL Content::getSupportedServiceNames()
184 {
185     // @@@ Adjust macro name.
186     uno::Sequence< rtl::OUString > aSNS( 1 );
187     aSNS.getArray()[ 0 ]
188             = rtl::OUString::createFromAscii( ODMA_CONTENT_SERVICE_NAME );
189     return aSNS;
190 }
191 
192 //=========================================================================
193 //
194 // XContent methods.
195 //
196 //=========================================================================
197 
198 // virtual
getContentType()199 rtl::OUString SAL_CALL Content::getContentType()
200 {
201     // @@@ Adjust macro name ( def in odma_provider.hxx ).
202     return rtl::OUString::createFromAscii( ODMA_CONTENT_TYPE );
203 }
204 
205 //=========================================================================
206 //
207 // XCommandProcessor methods.
208 //
209 //=========================================================================
210 
211 // virtual
execute(const ucb::Command & aCommand,sal_Int32,const uno::Reference<ucb::XCommandEnvironment> & Environment)212 uno::Any SAL_CALL Content::execute(
213         const ucb::Command& aCommand,
214         sal_Int32 /*CommandId*/,
215         const uno::Reference< ucb::XCommandEnvironment >& Environment )
216 {
217     uno::Any aRet;
218 
219     if ( aCommand.Name.equalsAsciiL(
220             RTL_CONSTASCII_STRINGPARAM( "getPropertyValues" ) ) )
221     {
222         //////////////////////////////////////////////////////////////////
223         // getPropertyValues
224         //////////////////////////////////////////////////////////////////
225 
226         uno::Sequence< beans::Property > Properties;
227         if ( !( aCommand.Argument >>= Properties ) )
228         {
229             OSL_ENSURE( sal_False, "Wrong argument type!" );
230             ucbhelper::cancelCommandExecution(
231                 uno::makeAny( lang::IllegalArgumentException(
232                                     rtl::OUString(),
233                                     static_cast< cppu::OWeakObject * >( this ),
234                                     -1 ) ),
235                 Environment );
236             // Unreachable
237         }
238 
239         aRet <<= getPropertyValues( Properties, Environment );
240     }
241     else if ( aCommand.Name.equalsAsciiL(
242                 RTL_CONSTASCII_STRINGPARAM( "setPropertyValues" ) ) )
243     {
244         //////////////////////////////////////////////////////////////////
245         // setPropertyValues
246         //////////////////////////////////////////////////////////////////
247 
248         uno::Sequence< beans::PropertyValue > aProperties;
249         if ( !( aCommand.Argument >>= aProperties ) )
250         {
251             OSL_ENSURE( sal_False, "Wrong argument type!" );
252             ucbhelper::cancelCommandExecution(
253                 uno::makeAny( lang::IllegalArgumentException(
254                                     rtl::OUString(),
255                                     static_cast< cppu::OWeakObject * >( this ),
256                                     -1 ) ),
257                 Environment );
258             // Unreachable
259         }
260 
261         if ( !aProperties.getLength() )
262         {
263             OSL_ENSURE( sal_False, "No properties!" );
264             ucbhelper::cancelCommandExecution(
265                 uno::makeAny( lang::IllegalArgumentException(
266                                     rtl::OUString(),
267                                     static_cast< cppu::OWeakObject * >( this ),
268                                     -1 ) ),
269                 Environment );
270             // Unreachable
271         }
272 
273         aRet <<= setPropertyValues( aProperties, Environment );
274     }
275     else if ( aCommand.Name.equalsAsciiL(
276                 RTL_CONSTASCII_STRINGPARAM( "getPropertySetInfo" ) ) )
277     {
278         //////////////////////////////////////////////////////////////////
279         // getPropertySetInfo
280         //////////////////////////////////////////////////////////////////
281 
282         // Note: Implemented by base class.
283         aRet <<= getPropertySetInfo( Environment );
284     }
285     else if ( aCommand.Name.equalsAsciiL(
286                 RTL_CONSTASCII_STRINGPARAM( "getCommandInfo" ) ) )
287     {
288         //////////////////////////////////////////////////////////////////
289         // getCommandInfo
290         //////////////////////////////////////////////////////////////////
291 
292         // Note: Implemented by base class.
293         aRet <<= getCommandInfo( Environment );
294     }
295     else if ( aCommand.Name.equalsAsciiL(
296                 RTL_CONSTASCII_STRINGPARAM( "open" ) ) )
297     {
298         ucb::OpenCommandArgument2 aOpenCommand;
299         if ( !( aCommand.Argument >>= aOpenCommand ) )
300         {
301             OSL_ENSURE( sal_False, "Wrong argument type!" );
302             ucbhelper::cancelCommandExecution(
303                 uno::makeAny( lang::IllegalArgumentException(
304                                     rtl::OUString(),
305                                     static_cast< cppu::OWeakObject * >( this ),
306                                     -1 ) ),
307                 Environment );
308             // Unreachable
309         }
310 
311         sal_Bool bOpenFolder =
312             ( ( aOpenCommand.Mode == ucb::OpenMode::ALL ) ||
313               ( aOpenCommand.Mode == ucb::OpenMode::FOLDERS ) ||
314               ( aOpenCommand.Mode == ucb::OpenMode::DOCUMENTS ) );
315 
316         if ( bOpenFolder)
317         {
318             // open as folder - return result set
319 
320             uno::Reference< ucb::XDynamicResultSet > xSet
321                             = new DynamicResultSet( m_xSMgr,
322                                                     this,
323                                                     aOpenCommand,
324                                                     Environment );
325             aRet <<= xSet;
326         }
327 
328         if ( aOpenCommand.Sink.is() )
329         {
330             // Open document - supply document data stream.
331 
332             // Check open mode
333             if ( ( aOpenCommand.Mode
334                     == ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE ) ||
335                  ( aOpenCommand.Mode
336                     == ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE ) )
337             {
338                 // Unsupported.
339                 ucbhelper::cancelCommandExecution(
340                     uno::makeAny( ucb::UnsupportedOpenModeException(
341                                     rtl::OUString(),
342                                     static_cast< cppu::OWeakObject * >( this ),
343                                     sal_Int16( aOpenCommand.Mode ) ) ),
344                     Environment );
345                 // Unreachable
346             }
347 
348 
349             rtl::OUString aURL = m_xIdentifier->getContentIdentifier();
350             rtl::OUString sFileURL = openDoc();
351             delete m_pContent;
352             m_pContent = new ::ucbhelper::Content(sFileURL,NULL);
353             if(!m_pContent->isDocument())
354             {
355                 rtl::OUString sErrorMsg(RTL_CONSTASCII_USTRINGPARAM("File: "));
356                 sErrorMsg += sFileURL;
357                 sErrorMsg += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" could not be found."));
358                 ucbhelper::cancelCommandExecution(
359                         uno::makeAny( io::IOException(
360                                         sErrorMsg,
361                                         static_cast< cppu::OWeakObject * >( this )) ),
362                         Environment );
363             }
364 
365             uno::Reference< io::XOutputStream > xOut
366                 = uno::Reference< io::XOutputStream >(
367                     aOpenCommand.Sink, uno::UNO_QUERY );
368             if ( xOut.is() )
369             {
370                 // @@@ PUSH: write data into xOut
371                 m_pContent->openStream(xOut);
372             }
373             else
374             {
375                 uno::Reference< io::XActiveDataSink > xDataSink
376                     = uno::Reference< io::XActiveDataSink >(
377                         aOpenCommand.Sink, uno::UNO_QUERY );
378                 if ( xDataSink.is() )
379                 {
380                     // @@@ PULL: wait for client read
381                     uno::Reference< io::XInputStream > xIn;
382                     try
383                     {
384                         xIn = m_pContent->openStream();
385                     }
386                     catch(uno::Exception&)
387                     {
388                         OSL_ENSURE(0,"Exception occurred while creating the file content!");
389                     }
390                     xDataSink->setInputStream( xIn );
391                 }
392                 else
393                 {
394                     uno::Reference< io::XActiveDataStreamer > activeDataStreamer( aOpenCommand.Sink,uno::UNO_QUERY );
395                     if(activeDataStreamer.is())
396                     {
397                         activeDataStreamer->setStream(new OOdmaStream(m_pContent,getContentProvider(),m_aProps));
398                         m_pContent = NULL; // don't delete here because the stream is now the owner
399                     }
400                     else
401                     {
402                         // Note: aOpenCommand.Sink may contain an XStream
403                         //       implementation. Support for this type of
404                         //       sink is optional...
405                         ucbhelper::cancelCommandExecution(
406                             uno::makeAny( ucb::UnsupportedDataSinkException(
407                                     rtl::OUString(),
408                                     static_cast< cppu::OWeakObject * >( this ),
409                                     aOpenCommand.Sink ) ),
410                             Environment );
411                         // Unreachable
412                     }
413                 }
414             }
415         }
416     }
417     else if ( aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "close" ) ) )
418     {
419         getContentProvider()->closeDocument(m_aProps->m_sDocumentId);
420     }
421     else if ( aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "delete" ) ) )
422     {
423         //////////////////////////////////////////////////////////////////
424         // delete
425         //////////////////////////////////////////////////////////////////
426 
427         // Remove own and all children's Additional Core Properties.
428         removeAdditionalPropertySet( sal_True );
429         // Remove own and all childrens(!) persistent data.
430         if(!getContentProvider()->deleteDocument(m_aProps))
431             ucbhelper::cancelCommandExecution(
432                 uno::makeAny( lang::IllegalArgumentException(
433                                     rtl::OUString(),
434                                     static_cast< cppu::OWeakObject * >( this ),
435                                     -1 ) ),
436                 Environment );
437     }
438     else if ( aCommand.Name.equalsAsciiL(
439                 RTL_CONSTASCII_STRINGPARAM( "insert" ) ) )
440     {
441         //////////////////////////////////////////////////////////////////
442         // insert
443         //////////////////////////////////////////////////////////////////
444 
445         ucb::InsertCommandArgument arg;
446         if ( !( aCommand.Argument >>= arg ) )
447         {
448             OSL_ENSURE( sal_False, "Wrong argument type!" );
449             ucbhelper::cancelCommandExecution(
450                 uno::makeAny( lang::IllegalArgumentException(
451                                     rtl::OUString(),
452                                     static_cast< cppu::OWeakObject * >( this ),
453                                     -1 ) ),
454                 Environment );
455             // Unreachable
456         }
457 
458         insert( arg.Data, arg.ReplaceExisting, Environment );
459     }
460     else if( ! aCommand.Name.compareToAscii( "transfer" ) )
461     {
462         ucb::TransferInfo aTransferInfo;
463         if( ! ( aCommand.Argument >>= aTransferInfo ) )
464         {
465             OSL_ENSURE( sal_False, "Wrong argument type!" );
466             ucbhelper::cancelCommandExecution(
467                 uno::makeAny( lang::IllegalArgumentException(
468                                     rtl::OUString(),
469                                     static_cast< cppu::OWeakObject * >( this ),
470                                     -1 ) ),
471                 Environment );
472             // Unreachable
473         }
474         ::rtl::Reference<ContentProperties> aProp = m_aProps;
475         if(aProp->m_bIsFolder)
476         {
477             aProp = getContentProvider()->getContentPropertyWithTitle(aTransferInfo.NewTitle);
478             if(!aProp.is())
479                 aProp = getContentProvider()->getContentPropertyWithSavedAsName(aTransferInfo.NewTitle);
480             sal_Bool bError = !aProp.is();
481             if(bError)
482             {
483                 sal_Char* pExtension = NULL;
484                 ::rtl::OString sExt;
485                 sal_Int32 nPos = aTransferInfo.NewTitle.lastIndexOf('.');
486                 if(nPos != -1)
487                 {
488                     sExt = ::rtl::OUStringToOString(aTransferInfo.NewTitle.copy(nPos+1),RTL_TEXTENCODING_ASCII_US);
489                     if(sExt.equalsIgnoreAsciiCase("txt"))
490                         pExtension = ODM_FORMAT_TEXT;
491                     else if(sExt.equalsIgnoreAsciiCase("rtf"))
492                         pExtension = ODM_FORMAT_RTF;
493                     else if(sExt.equalsIgnoreAsciiCase("ps"))
494                         pExtension = ODM_FORMAT_PS;
495                     else
496                         pExtension = const_cast<sal_Char*>(sExt.getStr());
497                 }
498                 else
499                     pExtension = ODM_FORMAT_TEXT;
500 
501                 sal_Char* lpszNewDocId = new sal_Char[ODM_DOCID_MAX];
502                 void *pData = NULL;
503                 DWORD dwFlags = ODM_SILENT;
504                 ODMSTATUS odm = NODMSaveAsEx(ContentProvider::getHandle(),
505                                              NULL, // means it is saved the first time
506                                              lpszNewDocId,
507                                              pExtension,
508                                              NULL, // no callback function here
509                                              pData,
510                                              &dwFlags);
511 
512                 // check if we have to call the DMS dialog
513                 if(odm == ODM_E_USERINT)
514                 {
515                     dwFlags = 0;
516                     odm = NODMSaveAsEx(ContentProvider::getHandle(),
517                                              NULL, // means it is saved the first time
518                                              lpszNewDocId,
519                                              pExtension,
520                                              NULL, // no callback function here
521                                              pData,
522                                              &dwFlags);
523                 }
524                 bError = odm != ODM_SUCCESS;
525                 if(!bError)
526                 {
527                     aProp = new ContentProperties();
528                     aProp->m_sDocumentId    = ::rtl::OString(lpszNewDocId);
529                     aProp->m_sContentType   = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ODMA_CONTENT_TYPE));
530                     aProp->m_sSavedAsName   = aTransferInfo.NewTitle;
531                     getContentProvider()->append(aProp);
532 
533                     // now set the title
534                     WORD nDocInfo = ODM_NAME;
535                     ::rtl::OUString sFileName = aTransferInfo.NewTitle;
536                     sal_Int32 nIndex = aTransferInfo.NewTitle.lastIndexOf( sal_Unicode('.') );
537                     if(nIndex != -1)
538                         sFileName = aTransferInfo.NewTitle.copy(0,nIndex);
539 
540                     ::rtl::OString sDocInfoValue = ::rtl::OUStringToOString(sFileName,RTL_TEXTENCODING_ASCII_US);
541                     odm = NODMSetDocInfo(   ContentProvider::getHandle(),
542                                             lpszNewDocId,
543                                             nDocInfo,
544                                             const_cast<sal_Char*>(sDocInfoValue.getStr())
545                                             );
546 
547                 }
548                 else if ( odm == ODM_E_CANCEL)
549                     NODMActivate(ContentProvider::getHandle(),
550                                  ODM_DELETE,
551                                  lpszNewDocId);
552 
553                 delete [] lpszNewDocId;
554             }
555             if(bError)
556                 ucbhelper::cancelCommandExecution(
557                         uno::makeAny( lang::IllegalArgumentException(
558                                             rtl::OUString(),
559                                             static_cast< cppu::OWeakObject * >( this ),
560                                             -1 ) ),
561                         Environment );
562         }
563         rtl::OUString sFileURL = ContentProvider::openDoc(aProp);
564 
565         sal_Int32 nLastIndex = sFileURL.lastIndexOf( sal_Unicode('/') );
566         ::ucbhelper::Content aContent(sFileURL.copy(0,nLastIndex),NULL);
567         //  aTransferInfo.NameClash = ucb::NameClash::OVERWRITE;
568         aTransferInfo.NewTitle = sFileURL.copy( 1 + nLastIndex );
569         aContent.executeCommand(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("transfer")),uno::makeAny(aTransferInfo));
570         getContentProvider()->saveDocument(aProp->m_sDocumentId);
571     }
572     else
573     {
574         //////////////////////////////////////////////////////////////////
575         // Unsupported command
576         //////////////////////////////////////////////////////////////////
577 
578         OSL_ENSURE( sal_False, "Content::execute - unsupported command!" );
579 
580         ucbhelper::cancelCommandExecution(
581             uno::makeAny( ucb::UnsupportedCommandException(
582                             rtl::OUString(),
583                             static_cast< cppu::OWeakObject * >( this ) ) ),
584             Environment );
585         // Unreachable
586     }
587 
588     return aRet;
589 }
590 
591 //=========================================================================
592 // virtual
abort(sal_Int32)593 void SAL_CALL Content::abort( sal_Int32 /*CommandId*/ )
594 {
595     // @@@ Implement logic to abort running commands, if this makes
596     //     sense for your content.
597 }
598 
599 //=========================================================================
600 //
601 // Non-interface methods.
602 //
603 //=========================================================================
604 
605 // virtual
getParentURL()606 ::rtl::OUString Content::getParentURL()
607 {
608     ::rtl::OUString sURL = m_xIdentifier->getContentIdentifier();
609 
610     // @@@ Extract URL of parent from aURL and return it...
611     static ::rtl::OUString sScheme1(RTL_CONSTASCII_USTRINGPARAM(ODMA_URL_SCHEME ODMA_URL_SHORT "/"));
612     static ::rtl::OUString sScheme2(RTL_CONSTASCII_USTRINGPARAM(ODMA_URL_SCHEME ODMA_URL_SHORT));
613     if(sURL == sScheme1 || sURL == sScheme2)
614         sURL = ::rtl::OUString();
615     else
616         sURL = sScheme1;
617 
618     return sURL;
619 }
620 
621 //=========================================================================
622 // static
getPropertyValues(const uno::Reference<lang::XMultiServiceFactory> & rSMgr,const uno::Sequence<beans::Property> & rProperties,const rtl::Reference<ContentProperties> & rData,const rtl::Reference<::ucbhelper::ContentProviderImplHelper> & rProvider,const rtl::OUString & rContentId)623 uno::Reference< sdbc::XRow > Content::getPropertyValues(
624             const uno::Reference< lang::XMultiServiceFactory >& rSMgr,
625             const uno::Sequence< beans::Property >& rProperties,
626             const rtl::Reference<ContentProperties>& rData,
627             const rtl::Reference< ::ucbhelper::ContentProviderImplHelper >& rProvider,
628             const rtl::OUString& rContentId )
629 {
630     // Note: Empty sequence means "get values of all supported properties".
631 
632     rtl::Reference< ::ucbhelper::PropertyValueSet > xRow
633                                 = new ::ucbhelper::PropertyValueSet( rSMgr );
634 
635     sal_Int32 nCount = rProperties.getLength();
636     if ( nCount )
637     {
638         uno::Reference< beans::XPropertySet > xAdditionalPropSet;
639         sal_Bool bTriedToGetAdditonalPropSet = sal_False;
640 
641         const beans::Property* pProps = rProperties.getConstArray();
642         for ( sal_Int32 n = 0; n < nCount; ++n )
643         {
644             const beans::Property& rProp = pProps[ n ];
645 
646             // Process Core properties.
647 
648             if ( rProp.Name.equalsAsciiL(
649                     RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) )
650             {
651                 xRow->appendString ( rProp, rData->m_sContentType );
652             }
653             else if ( rProp.Name.equalsAsciiL(
654                     RTL_CONSTASCII_STRINGPARAM( "Title" ) ) )
655             {
656                 xRow->appendString ( rProp, rData->m_sTitle );
657             }
658             else if ( rProp.Name.equalsAsciiL(
659                     RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) )
660             {
661                 xRow->appendBoolean( rProp, rData->m_bIsDocument );
662             }
663             else if ( rProp.Name.equalsAsciiL(
664                     RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) )
665             {
666                 xRow->appendBoolean( rProp, rData->m_bIsFolder );
667             }
668             else if ( rProp.Name.equalsAsciiL(
669                     RTL_CONSTASCII_STRINGPARAM( "DateCreated" ) ) )
670             {
671                 xRow->appendTimestamp( rProp, rData->m_aDateCreated );
672             }
673             else if ( rProp.Name.equalsAsciiL(
674                     RTL_CONSTASCII_STRINGPARAM( "DateModified" ) ) )
675             {
676                 xRow->appendTimestamp( rProp, rData->m_aDateModified );
677             }
678             else if ( rProp.Name.equalsAsciiL(
679                     RTL_CONSTASCII_STRINGPARAM( "IsReadOnly" ) ) )
680             {
681                 xRow->appendBoolean( rProp, rData->m_bIsReadOnly );
682             }
683             else if ( rProp.Name.equalsAsciiL(
684                     RTL_CONSTASCII_STRINGPARAM( "Author" ) ) )
685             {
686                 xRow->appendString ( rProp, rData->m_sAuthor );
687             }
688             else if ( rProp.Name.equalsAsciiL(
689                     RTL_CONSTASCII_STRINGPARAM( "Subject" ) ) )
690             {
691                 xRow->appendString ( rProp, rData->m_sSubject );
692             }
693             else if ( rProp.Name.equalsAsciiL(
694                     RTL_CONSTASCII_STRINGPARAM( "Keywords" ) ) )
695             {
696                 xRow->appendString ( rProp, rData->m_sKeywords );
697             }
698             else
699             {
700                 // @@@ Note: If your data source supports adding/removing
701                 //     properties, you should implement the interface
702                 //     XPropertyContainer by yourself and supply your own
703                 //     logic here. The base class uses the service
704                 //     "com.sun.star.ucb.Store" to maintain Additional Core
705                 //     properties. But using server functionality is preferred!
706 
707                 // Not a Core Property! Maybe it's an Additional Core Property?!
708 
709                 if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() )
710                 {
711                     xAdditionalPropSet
712                         = uno::Reference< beans::XPropertySet >(
713                             rProvider->getAdditionalPropertySet( rContentId,
714                                                                  sal_False ),
715                             uno::UNO_QUERY );
716                     bTriedToGetAdditonalPropSet = sal_True;
717                 }
718 
719                 if ( xAdditionalPropSet.is() )
720                 {
721                     if ( !xRow->appendPropertySetValue(
722                                                 xAdditionalPropSet,
723                                                 rProp ) )
724                     {
725                         // Append empty entry.
726                         xRow->appendVoid( rProp );
727                     }
728                 }
729                 else
730                 {
731                     // Append empty entry.
732                     xRow->appendVoid( rProp );
733                 }
734             }
735         }
736     }
737     else
738     {
739         // Append all Core Properties.
740         xRow->appendString (
741             beans::Property( rtl::OUString::createFromAscii( "ContentType" ),
742                       -1,
743                       getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
744                       beans::PropertyAttribute::BOUND
745                         | beans::PropertyAttribute::READONLY ),
746             rData->m_sContentType );
747         xRow->appendString (
748             beans::Property( rtl::OUString::createFromAscii( "Title" ),
749                       -1,
750                       getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
751                       beans::PropertyAttribute::BOUND ),
752             rData->m_sTitle );
753         xRow->appendBoolean(
754             beans::Property( rtl::OUString::createFromAscii( "IsDocument" ),
755                       -1,
756                       getCppuBooleanType(),
757                       beans::PropertyAttribute::BOUND
758                         | beans::PropertyAttribute::READONLY ),
759             rData->m_bIsDocument );
760         xRow->appendBoolean(
761             beans::Property( rtl::OUString::createFromAscii( "IsFolder" ),
762                       -1,
763                       getCppuBooleanType(),
764                       beans::PropertyAttribute::BOUND
765                         | beans::PropertyAttribute::READONLY ),
766             rData->m_bIsFolder );
767 
768         // @@@ Append other properties supported directly.
769         xRow->appendTimestamp(
770             beans::Property( rtl::OUString::createFromAscii( "DateCreated" ),
771                       -1,
772                       getCppuType(static_cast< const util::DateTime * >( 0 ) ),
773                       beans::PropertyAttribute::BOUND
774                         | beans::PropertyAttribute::READONLY ),
775             rData->m_aDateCreated );
776         xRow->appendTimestamp(
777             beans::Property( rtl::OUString::createFromAscii( "DateModified" ),
778                       -1,
779                       getCppuType(static_cast< const util::DateTime * >( 0 ) ),
780                       beans::PropertyAttribute::BOUND
781                         | beans::PropertyAttribute::READONLY ),
782             rData->m_aDateModified );
783         xRow->appendBoolean(
784             beans::Property( rtl::OUString::createFromAscii( "IsReadOnly" ),
785                       -1,
786                       getCppuBooleanType(),
787                       beans::PropertyAttribute::BOUND
788                         | beans::PropertyAttribute::READONLY ),
789             rData->m_bIsReadOnly );
790         xRow->appendString (
791             beans::Property( rtl::OUString::createFromAscii( "Author" ),
792                       -1,
793                       getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
794                       beans::PropertyAttribute::BOUND ),
795             rData->m_sAuthor );
796         xRow->appendString (
797             beans::Property( rtl::OUString::createFromAscii( "Subject" ),
798                       -1,
799                       getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
800                       beans::PropertyAttribute::BOUND ),
801             rData->m_sSubject );
802         xRow->appendString (
803             beans::Property( rtl::OUString::createFromAscii( "Keywords" ),
804                       -1,
805                       getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
806                       beans::PropertyAttribute::BOUND ),
807             rData->m_sKeywords );
808 
809         // @@@ Note: If your data source supports adding/removing
810         //     properties, you should implement the interface
811         //     XPropertyContainer by yourself and supply your own
812         //     logic here. The base class uses the service
813         //     "com.sun.star.ucb.Store" to maintain Additional Core
814         //     properties. But using server functionality is preferred!
815 
816         // Append all Additional Core Properties.
817 
818         uno::Reference< beans::XPropertySet > xSet(
819             rProvider->getAdditionalPropertySet( rContentId, sal_False ),
820             uno::UNO_QUERY );
821         xRow->appendPropertySet( xSet );
822     }
823 
824     return uno::Reference< sdbc::XRow >( xRow.get() );
825 }
826 
827 //=========================================================================
getPropertyValues(const uno::Sequence<beans::Property> & rProperties,const uno::Reference<ucb::XCommandEnvironment> &)828 uno::Reference< sdbc::XRow > Content::getPropertyValues(
829             const uno::Sequence< beans::Property >& rProperties,
830             const uno::Reference< ucb::XCommandEnvironment >& /*xEnv*/ )
831 {
832     osl::Guard< osl::Mutex > aGuard( m_aMutex );
833     return getPropertyValues( m_xSMgr,
834                               rProperties,
835                               m_aProps,
836                               rtl::Reference<
837                                 ::ucbhelper::ContentProviderImplHelper >(
838                                     m_xProvider.get() ),
839                               m_xIdentifier->getContentIdentifier() );
840 }
841 
842 //=========================================================================
setPropertyValues(const uno::Sequence<beans::PropertyValue> & rValues,const uno::Reference<ucb::XCommandEnvironment> &)843 uno::Sequence< uno::Any > Content::setPropertyValues(
844             const uno::Sequence< beans::PropertyValue >& rValues,
845             const uno::Reference< ucb::XCommandEnvironment >& /*xEnv*/ )
846 {
847     osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
848 
849     uno::Sequence< uno::Any > aRet( rValues.getLength() );
850     uno::Sequence< beans::PropertyChangeEvent > aChanges( rValues.getLength() );
851     sal_Int32 nChanged = 0;
852 
853     beans::PropertyChangeEvent aEvent;
854     aEvent.Source         = static_cast< cppu::OWeakObject * >( this );
855     aEvent.Further        = sal_False;
856 //  aEvent.PropertyName   =
857     aEvent.PropertyHandle = -1;
858 //  aEvent.OldValue       =
859 //  aEvent.NewValue       =
860 
861     const beans::PropertyValue* pValues = rValues.getConstArray();
862     sal_Int32 nCount = rValues.getLength();
863 
864     uno::Reference< ucb::XPersistentPropertySet > xAdditionalPropSet;
865     sal_Bool bTriedToGetAdditonalPropSet = sal_False;
866 
867     for ( sal_Int32 n = 0; n < nCount; ++n )
868     {
869         const beans::PropertyValue& rValue = pValues[ n ];
870 
871         if ( rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "Title" ) ) )
872         {
873             changePropertyValue(rValue,n,m_aProps->m_sTitle,nChanged,aRet,aChanges);
874         }
875         else if ( rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "Author") ) )
876         {
877             changePropertyValue(rValue,n,m_aProps->m_sAuthor,nChanged,aRet,aChanges);
878         }
879         else if ( rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "Keywords") ) )
880         {
881             changePropertyValue(rValue,n,m_aProps->m_sKeywords,nChanged,aRet,aChanges);
882         }
883         else if ( rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "Subject") ) )
884         {
885             changePropertyValue(rValue,n,m_aProps->m_sSubject,nChanged,aRet,aChanges);
886         }
887         else if (   rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "ContentType" ) )  ||
888                     rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) )   ||
889                     rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) )     ||
890                     rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "DateCreated" ) )  ||
891                     rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "DateModified" ) ) ||
892                     rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "IsReadOnly" ) ) )
893         {
894             // Read-only property!
895             aRet[ n ] <<= lang::IllegalAccessException(
896                             rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
897                                 "Property is read-only!") ),
898                             static_cast< cppu::OWeakObject * >( this ) );
899         }
900         else
901         {
902             // @@@ Note: If your data source supports adding/removing
903             //     properties, you should implement the interface
904             //     XPropertyContainer by yourself and supply your own
905             //     logic here. The base class uses the service
906             //     "com.sun.star.ucb.Store" to maintain Additional Core
907             //     properties. But using server functionality is preferred!
908 
909             // Not a Core Property! Maybe it's an Additional Core Property?!
910 
911             if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() )
912             {
913                 xAdditionalPropSet = getAdditionalPropertySet( sal_False );
914                 bTriedToGetAdditonalPropSet = sal_True;
915             }
916 
917             if ( xAdditionalPropSet.is() )
918             {
919                 try
920                 {
921                     uno::Any aOldValue
922                         = xAdditionalPropSet->getPropertyValue( rValue.Name );
923                     if ( aOldValue != rValue.Value )
924                     {
925                         xAdditionalPropSet->setPropertyValue(
926                                                 rValue.Name, rValue.Value );
927 
928                         aEvent.PropertyName = rValue.Name;
929                         aEvent.OldValue     = aOldValue;
930                         aEvent.NewValue     = rValue.Value;
931 
932                         aChanges.getArray()[ nChanged ] = aEvent;
933                         nChanged++;
934                     }
935                     else
936                     {
937                         // Old value equals new value. No error!
938                     }
939                 }
940                 catch ( beans::UnknownPropertyException const & e )
941                 {
942                     aRet[ n ] <<= e;
943                 }
944                 catch ( lang::WrappedTargetException const & e )
945                 {
946                     aRet[ n ] <<= e;
947                 }
948                 catch ( beans::PropertyVetoException const & e )
949                 {
950                     aRet[ n ] <<= e;
951                 }
952                 catch ( lang::IllegalArgumentException const & e )
953                 {
954                     aRet[ n ] <<= e;
955                 }
956             }
957             else
958             {
959                 aRet[ n ] <<= uno::Exception(
960                                 rtl::OUString::createFromAscii(
961                                     "No property set for storing the value!" ),
962                                 static_cast< cppu::OWeakObject * >( this ) );
963             }
964         }
965     }
966 
967     if ( nChanged > 0 )
968     {
969         // @@@ Save changes.
970 //      storeData();
971 
972         aGuard.clear();
973         aChanges.realloc( nChanged );
974         notifyPropertiesChange( aChanges );
975     }
976 
977     return aRet;
978 }
979 
980 #if 0
981 //=========================================================================
982 void Content::queryChildren( ContentRefList& rChildren )
983 {
984     // @@@ Adapt method to your URL scheme...
985 
986     // Obtain a list with a snapshot of all currently instantiated contents
987     // from provider and extract the contents which are direct children
988     // of this content.
989 
990     ::ucbhelper::ContentRefList aAllContents;
991     m_xProvider->queryExistingContents( aAllContents );
992 
993     OUString aURL = m_xIdentifier->getContentIdentifier();
994     sal_Int32 nPos = aURL.lastIndexOf( '/' );
995 
996     if ( nPos != ( aURL.getLength() - 1 ) )
997     {
998         // No trailing slash found. Append.
999         aURL += OUString::createFromAscii( "/" );
1000     }
1001 
1002     sal_Int32 nLen = aURL.getLength();
1003 
1004     ::ucbhelper::ContentRefList::const_iterator it  = aAllContents.begin();
1005     ::ucbhelper::ContentRefList::const_iterator end = aAllContents.end();
1006 
1007     while ( it != end )
1008     {
1009         ::ucbhelper::ContentImplHelperRef xChild = (*it);
1010         OUString aChildURL = xChild->getIdentifier()->getContentIdentifier();
1011 
1012         // Is aURL a prefix of aChildURL?
1013         if ( ( aChildURL.getLength() > nLen ) &&
1014              ( aChildURL.compareTo( aURL, nLen ) == 0 ) )
1015         {
1016             sal_Int32 nPos = nLen;
1017             nPos = aChildURL.indexOf( '/', nPos );
1018 
1019             if ( ( nPos == -1 ) ||
1020                  ( nPos == ( aChildURL.getLength() - 1 ) ) )
1021             {
1022                 // No further slashes / only a final slash. It's a child!
1023                 rChildren.push_back(
1024                     ContentRef(
1025                         static_cast< Content * >( xChild.get() ) ) );
1026             }
1027         }
1028         ++it;
1029     }
1030 }
1031 #endif
1032 //=========================================================================
insert(const uno::Reference<io::XInputStream> & xInputStream,sal_Bool bReplaceExisting,const uno::Reference<ucb::XCommandEnvironment> & Environment)1033 void Content::insert(
1034         const uno::Reference< io::XInputStream > & xInputStream,
1035         sal_Bool bReplaceExisting,
1036         const uno::Reference< ucb::XCommandEnvironment >& Environment )
1037 {
1038     osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1039 
1040     // Check, if all required properties were set.
1041     if ( !m_aProps->m_sTitle.getLength())
1042     {
1043         OSL_ENSURE( sal_False, "Content::insert - property value missing!" );
1044 
1045         uno::Sequence< rtl::OUString > aProps( 1 );
1046         aProps[ 0 ] = rtl::OUString::createFromAscii( "zzzz" );
1047         ucbhelper::cancelCommandExecution(
1048             uno::makeAny( ucb::MissingPropertiesException(
1049                                 rtl::OUString(),
1050                                 static_cast< cppu::OWeakObject * >( this ),
1051                                 aProps ) ),
1052             Environment );
1053         // Unreachable
1054     }
1055 
1056     if ( !xInputStream.is() )
1057     {
1058         OSL_ENSURE( sal_False, "Content::insert - No data stream!" );
1059 
1060         ucbhelper::cancelCommandExecution(
1061             uno::makeAny( ucb::MissingInputStreamException(
1062                             rtl::OUString(),
1063                             static_cast< cppu::OWeakObject * >( this ) ) ),
1064             Environment );
1065         // Unreachable
1066     }
1067 
1068     // Assemble new content identifier...
1069 
1070     //  uno::Reference< ucb::XContentIdentifier > xId = ...;
1071 
1072     // Fail, if a resource with given id already exists.
1073     if ( !bReplaceExisting ) // && hasData( m_xIdentifier ) )
1074     {
1075         ucbhelper::cancelCommandExecution(
1076             uno::makeAny( ucb::UnsupportedCommandException(
1077                             rtl::OUString(),
1078                             static_cast< cppu::OWeakObject * >( this ) ) ),
1079             Environment );
1080 //        ucbhelper::cancelCommandExecution(
1081 //                      ucb::IOErrorCode_ALREADY_EXISTING,
1082 //                      Environment,
1083 //                      uno::makeAny(static_cast< cppu::OWeakObject * >( this ))
1084 //                         );
1085         // Unreachable
1086     }
1087 
1088     //  m_xIdentifier = xId;
1089 
1090 //  @@@
1091 //  storeData();
1092 
1093     aGuard.clear();
1094     inserted();
1095 }
1096 #if 0
1097 //=========================================================================
1098 void Content::destroy( sal_Bool bDeletePhysical )
1099 {
1100     // @@@ take care about bDeletePhysical -> trashcan support
1101 
1102     uno::Reference< ucb::XContent > xThis = this;
1103 
1104     deleted();
1105 
1106     osl::Guard< osl::Mutex > aGuard( m_aMutex );
1107 
1108     // Process instantiated children...
1109 
1110     ContentRefList aChildren;
1111     queryChildren( aChildren );
1112 
1113     ContentRefList::const_iterator it  = aChildren.begin();
1114     ContentRefList::const_iterator end = aChildren.end();
1115 
1116     while ( it != end )
1117     {
1118         (*it)->destroy( bDeletePhysical );
1119         ++it;
1120     }
1121 }
1122 #endif
1123 
1124 // -----------------------------------------------------------------------------
openDoc()1125 ::rtl::OUString Content::openDoc()
1126 {
1127     OSL_ENSURE(m_aProps.is(),"No valid content properties!");
1128     return ContentProvider::openDoc(m_aProps);
1129 }
1130 // -----------------------------------------------------------------------------
changePropertyValue(const beans::PropertyValue & _rValue,sal_Int32 _rnCurrentPos,::rtl::OUString & _rsMemberValue,sal_Int32 & _rnChanged,uno::Sequence<uno::Any> & _rRet,uno::Sequence<beans::PropertyChangeEvent> & _rChanges)1131 void Content::changePropertyValue(const beans::PropertyValue& _rValue,
1132                                   sal_Int32 _rnCurrentPos,
1133                                   ::rtl::OUString& _rsMemberValue,
1134                                   sal_Int32& _rnChanged,
1135                                   uno::Sequence< uno::Any >& _rRet,
1136                                   uno::Sequence< beans::PropertyChangeEvent >& _rChanges)
1137 {
1138     rtl::OUString sNewValue;
1139     sal_Bool bError = sal_False;
1140     if ( _rValue.Value >>= sNewValue )
1141     {
1142         if ( sNewValue != _rsMemberValue )
1143         {
1144             osl::Guard< osl::Mutex > aGuard( m_aMutex );
1145             // first we have to check if we could change the property inside the DMS
1146             ::rtl::OString sDocInfoValue = ::rtl::OUStringToOString(sNewValue,RTL_TEXTENCODING_ASCII_US);
1147             WORD nDocInfo = 0;
1148             if(&_rsMemberValue == &m_aProps->m_sTitle)
1149                 nDocInfo = ODM_TITLETEXT;
1150             else if(&_rsMemberValue == &m_aProps->m_sAuthor)
1151                 nDocInfo = ODM_AUTHOR;
1152             else if(&_rsMemberValue == &m_aProps->m_sSubject)
1153                 nDocInfo = ODM_SUBJECT;
1154             else if(&_rsMemberValue == &m_aProps->m_sKeywords)
1155                 nDocInfo = ODM_KEYWORDS;
1156             else
1157                 bError = sal_True;
1158 
1159             if(!bError)
1160             {
1161                 ODMSTATUS odm = NODMSetDocInfo( ContentProvider::getHandle(),
1162                                                 const_cast<sal_Char*>(m_aProps->m_sDocumentId.getStr()),
1163                                                 nDocInfo,
1164                                                 const_cast<sal_Char*>(sDocInfoValue.getStr())
1165                                                 );
1166                 if(odm == ODM_SUCCESS)
1167                 {
1168                     beans::PropertyChangeEvent aEvent;
1169                     aEvent.Source           = static_cast< cppu::OWeakObject * >( this );
1170                     aEvent.Further          = sal_False;
1171                     aEvent.PropertyHandle   = -1;
1172                     aEvent.PropertyName     = _rValue.Name;
1173                     aEvent.OldValue         = uno::makeAny( _rsMemberValue );
1174                     aEvent.NewValue         = uno::makeAny( sNewValue );
1175 
1176                     _rChanges.getArray()[ _rnChanged ] = aEvent;
1177 
1178                     _rsMemberValue = sNewValue;
1179                     ++_rnChanged;
1180                 }
1181             }
1182         }
1183         else
1184         {
1185             // Old value equals new value. No error!
1186         }
1187     }
1188     else
1189         bError = sal_True;
1190 
1191     if(bError)
1192     {
1193         _rRet[ _rnCurrentPos ] <<= beans::IllegalTypeException(
1194                         rtl::OUString::createFromAscii(
1195                             "Property value has wrong type!" ),
1196                         static_cast< cppu::OWeakObject * >( this ) );
1197     }
1198 }
1199 // -----------------------------------------------------------------------------
1200