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