Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : /**************************************************************************
22 : TODO
23 : **************************************************************************
24 :
25 : *************************************************************************/
26 :
27 : #include "osl/diagnose.h"
28 : #include "osl/doublecheckedlocking.h"
29 : #include "rtl/ustrbuf.hxx"
30 :
31 : #include "com/sun/star/beans/PropertyAttribute.hpp"
32 : #include "com/sun/star/beans/PropertyValue.hpp"
33 : #include "com/sun/star/beans/XPropertySet.hpp"
34 : #include "com/sun/star/embed/ElementModes.hpp"
35 : #include "com/sun/star/embed/XStorage.hpp"
36 : #include "com/sun/star/embed/XTransactedObject.hpp"
37 : #include "com/sun/star/io/XActiveDataSink.hpp"
38 : #include "com/sun/star/io/XActiveDataStreamer.hpp"
39 : #include "com/sun/star/lang/IllegalAccessException.hpp"
40 : #include "com/sun/star/sdbc/XRow.hpp"
41 : #include "com/sun/star/ucb/ContentAction.hpp"
42 : #include "com/sun/star/ucb/ContentInfoAttribute.hpp"
43 : #include "com/sun/star/ucb/InsertCommandArgument.hpp"
44 : #include "com/sun/star/ucb/InteractiveBadTransferURLException.hpp"
45 : #include "com/sun/star/ucb/MissingInputStreamException.hpp"
46 : #include "com/sun/star/ucb/MissingPropertiesException.hpp"
47 : #include "com/sun/star/ucb/NameClash.hpp"
48 : #include "com/sun/star/ucb/NameClashException.hpp"
49 : #include "com/sun/star/ucb/OpenCommandArgument2.hpp"
50 : #include "com/sun/star/ucb/OpenMode.hpp"
51 : #include "com/sun/star/ucb/TransferInfo.hpp"
52 : #include "com/sun/star/ucb/UnsupportedCommandException.hpp"
53 : #include "com/sun/star/ucb/UnsupportedDataSinkException.hpp"
54 : #include "com/sun/star/ucb/UnsupportedNameClashException.hpp"
55 : #include "com/sun/star/ucb/UnsupportedOpenModeException.hpp"
56 : #include "com/sun/star/ucb/XCommandInfo.hpp"
57 : #include "com/sun/star/ucb/XPersistentPropertySet.hpp"
58 :
59 : #include "comphelper/processfactory.hxx"
60 : #include "ucbhelper/cancelcommandexecution.hxx"
61 : #include "ucbhelper/contentidentifier.hxx"
62 : #include "ucbhelper/propertyvalueset.hxx"
63 :
64 : #include "tdoc_content.hxx"
65 : #include "tdoc_resultset.hxx"
66 : #include "tdoc_passwordrequest.hxx"
67 :
68 : #include "../inc/urihelper.hxx"
69 :
70 : using namespace com::sun::star;
71 : using namespace tdoc_ucp;
72 :
73 : //=========================================================================
74 0 : static ContentType lcl_getContentType( const rtl::OUString & rType )
75 : {
76 0 : if ( rType == TDOC_ROOT_CONTENT_TYPE )
77 0 : return ROOT;
78 0 : else if ( rType == TDOC_DOCUMENT_CONTENT_TYPE )
79 0 : return DOCUMENT;
80 0 : else if ( rType == TDOC_FOLDER_CONTENT_TYPE )
81 0 : return FOLDER;
82 0 : else if ( rType == TDOC_STREAM_CONTENT_TYPE )
83 0 : return STREAM;
84 : else
85 : {
86 : OSL_FAIL( "Content::Content - unsupported content type string" );
87 0 : return STREAM;
88 : }
89 : }
90 :
91 : //=========================================================================
92 : //=========================================================================
93 : //
94 : // Content Implementation.
95 : //
96 : //=========================================================================
97 : //=========================================================================
98 :
99 : // static ( "virtual" ctor )
100 5 : Content* Content::create(
101 : const uno::Reference< uno::XComponentContext >& rxContext,
102 : ContentProvider* pProvider,
103 : const uno::Reference< ucb::XContentIdentifier >& Identifier )
104 : {
105 : // Fail, if resource does not exist.
106 5 : ContentProperties aProps;
107 10 : if ( !Content::loadData( pProvider,
108 5 : Uri( Identifier->getContentIdentifier() ),
109 10 : aProps ) )
110 0 : return 0;
111 :
112 5 : return new Content( rxContext, pProvider, Identifier, aProps );
113 : }
114 :
115 : //=========================================================================
116 : // static ( "virtual" ctor )
117 0 : Content* Content::create(
118 : const uno::Reference< uno::XComponentContext >& rxContext,
119 : ContentProvider* pProvider,
120 : const uno::Reference< ucb::XContentIdentifier >& Identifier,
121 : const ucb::ContentInfo& Info )
122 : {
123 0 : if ( Info.Type.isEmpty() )
124 0 : return 0;
125 :
126 0 : if ( Info.Type != TDOC_FOLDER_CONTENT_TYPE && Info.Type != TDOC_STREAM_CONTENT_TYPE )
127 : {
128 : OSL_FAIL( "Content::create - unsupported content type!" );
129 0 : return 0;
130 : }
131 :
132 0 : return new Content( rxContext, pProvider, Identifier, Info );
133 : }
134 :
135 : //=========================================================================
136 5 : Content::Content(
137 : const uno::Reference< uno::XComponentContext > & rxContext,
138 : ContentProvider * pProvider,
139 : const uno::Reference< ucb::XContentIdentifier > & Identifier,
140 : const ContentProperties & rProps )
141 : : ContentImplHelper( rxContext, pProvider, Identifier ),
142 : m_aProps( rProps ),
143 : m_eState( PERSISTENT ),
144 5 : m_pProvider( pProvider )
145 : {
146 5 : }
147 :
148 : //=========================================================================
149 : // ctor for a content just created via XContentCreator::createNewContent()
150 0 : Content::Content(
151 : const uno::Reference< uno::XComponentContext >& rxContext,
152 : ContentProvider* pProvider,
153 : const uno::Reference< ucb::XContentIdentifier >& Identifier,
154 : const ucb::ContentInfo& Info )
155 : : ContentImplHelper( rxContext, pProvider, Identifier ),
156 0 : m_aProps( lcl_getContentType( Info.Type ), rtl::OUString() ), // no Title (yet)
157 : m_eState( TRANSIENT ),
158 0 : m_pProvider( pProvider )
159 : {
160 0 : }
161 :
162 : //=========================================================================
163 : // virtual
164 10 : Content::~Content()
165 : {
166 10 : }
167 :
168 : //=========================================================================
169 : //
170 : // XInterface methods.
171 : //
172 : //=========================================================================
173 :
174 : // virtual
175 43 : void SAL_CALL Content::acquire()
176 : throw( )
177 : {
178 43 : ContentImplHelper::acquire();
179 43 : }
180 :
181 : //=========================================================================
182 : // virtual
183 43 : void SAL_CALL Content::release()
184 : throw( )
185 : {
186 43 : ContentImplHelper::release();
187 43 : }
188 :
189 : //=========================================================================
190 : // virtual
191 6 : uno::Any SAL_CALL Content::queryInterface( const uno::Type & rType )
192 : throw ( uno::RuntimeException )
193 : {
194 6 : uno::Any aRet = ContentImplHelper::queryInterface( rType );
195 :
196 6 : if ( !aRet.hasValue() )
197 : {
198 : aRet = cppu::queryInterface(
199 0 : rType, static_cast< ucb::XContentCreator * >( this ) );
200 0 : if ( aRet.hasValue() )
201 : {
202 0 : if ( !m_aProps.isContentCreator() )
203 0 : return uno::Any();
204 : }
205 : }
206 :
207 6 : return aRet;
208 : }
209 :
210 : //=========================================================================
211 : //
212 : // XTypeProvider methods.
213 : //
214 : //=========================================================================
215 :
216 0 : XTYPEPROVIDER_COMMON_IMPL( Content );
217 :
218 : //=========================================================================
219 : // virtual
220 0 : uno::Sequence< uno::Type > SAL_CALL Content::getTypes()
221 : throw( uno::RuntimeException )
222 : {
223 0 : cppu::OTypeCollection * pCollection = 0;
224 :
225 0 : if ( m_aProps.isContentCreator() )
226 : {
227 : static cppu::OTypeCollection* pFolderTypes = 0;
228 :
229 0 : pCollection = pFolderTypes;
230 0 : if ( !pCollection )
231 : {
232 0 : osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
233 :
234 0 : pCollection = pFolderTypes;
235 0 : if ( !pCollection )
236 : {
237 : static cppu::OTypeCollection aCollection(
238 0 : CPPU_TYPE_REF( lang::XTypeProvider ),
239 0 : CPPU_TYPE_REF( lang::XServiceInfo ),
240 0 : CPPU_TYPE_REF( lang::XComponent ),
241 0 : CPPU_TYPE_REF( ucb::XContent ),
242 0 : CPPU_TYPE_REF( ucb::XCommandProcessor ),
243 0 : CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
244 0 : CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
245 0 : CPPU_TYPE_REF( beans::XPropertyContainer ),
246 0 : CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
247 0 : CPPU_TYPE_REF( container::XChild ),
248 0 : CPPU_TYPE_REF( ucb::XContentCreator ) ); // !!
249 0 : pCollection = &aCollection;
250 : OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
251 0 : pFolderTypes = pCollection;
252 0 : }
253 : }
254 : else {
255 : OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
256 : }
257 : }
258 : else
259 : {
260 : static cppu::OTypeCollection* pDocumentTypes = 0;
261 :
262 0 : pCollection = pDocumentTypes;
263 0 : if ( !pCollection )
264 : {
265 0 : osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
266 :
267 0 : pCollection = pDocumentTypes;
268 0 : if ( !pCollection )
269 : {
270 : static cppu::OTypeCollection aCollection(
271 0 : CPPU_TYPE_REF( lang::XTypeProvider ),
272 0 : CPPU_TYPE_REF( lang::XServiceInfo ),
273 0 : CPPU_TYPE_REF( lang::XComponent ),
274 0 : CPPU_TYPE_REF( ucb::XContent ),
275 0 : CPPU_TYPE_REF( ucb::XCommandProcessor ),
276 0 : CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
277 0 : CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
278 0 : CPPU_TYPE_REF( beans::XPropertyContainer ),
279 0 : CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
280 0 : CPPU_TYPE_REF( container::XChild ) );
281 0 : pCollection = &aCollection;
282 : OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
283 0 : pDocumentTypes = pCollection;
284 0 : }
285 : }
286 : else {
287 : OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
288 : }
289 : }
290 :
291 0 : return (*pCollection).getTypes();
292 : }
293 :
294 : //=========================================================================
295 : //
296 : // XServiceInfo methods.
297 : //
298 : //=========================================================================
299 :
300 : // virtual
301 0 : rtl::OUString SAL_CALL Content::getImplementationName()
302 : throw( uno::RuntimeException )
303 : {
304 0 : return rtl::OUString( "com.sun.star.comp.ucb.TransientDocumentsContent" );
305 : }
306 :
307 : //=========================================================================
308 : // virtual
309 0 : uno::Sequence< rtl::OUString > SAL_CALL Content::getSupportedServiceNames()
310 : throw( uno::RuntimeException )
311 : {
312 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
313 :
314 0 : uno::Sequence< rtl::OUString > aSNS( 1 );
315 :
316 0 : if ( m_aProps.getType() == STREAM )
317 0 : aSNS.getArray()[ 0 ] = rtl::OUString( TDOC_STREAM_CONTENT_SERVICE_NAME );
318 0 : else if ( m_aProps.getType() == FOLDER )
319 0 : aSNS.getArray()[ 0 ] = rtl::OUString( TDOC_FOLDER_CONTENT_SERVICE_NAME );
320 0 : else if ( m_aProps.getType() == DOCUMENT )
321 0 : aSNS.getArray()[ 0 ] = rtl::OUString( TDOC_DOCUMENT_CONTENT_SERVICE_NAME );
322 : else
323 0 : aSNS.getArray()[ 0 ] = rtl::OUString( TDOC_ROOT_CONTENT_SERVICE_NAME );
324 :
325 0 : return aSNS;
326 : }
327 :
328 : //=========================================================================
329 : //
330 : // XContent methods.
331 : //
332 : //=========================================================================
333 :
334 : // virtual
335 0 : rtl::OUString SAL_CALL Content::getContentType()
336 : throw( uno::RuntimeException )
337 : {
338 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
339 0 : return m_aProps.getContentType();
340 : }
341 :
342 : //=========================================================================
343 : // virtual
344 : uno::Reference< ucb::XContentIdentifier > SAL_CALL
345 5 : Content::getIdentifier()
346 : throw( uno::RuntimeException )
347 : {
348 : {
349 5 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
350 :
351 : // Transient?
352 5 : if ( m_eState == TRANSIENT )
353 : {
354 : // Transient contents have no identifier.
355 0 : return uno::Reference< ucb::XContentIdentifier >();
356 5 : }
357 : }
358 5 : return ContentImplHelper::getIdentifier();
359 : }
360 :
361 : //=========================================================================
362 : //
363 : // XCommandProcessor methods.
364 : //
365 : //=========================================================================
366 :
367 : // virtual
368 3 : uno::Any SAL_CALL Content::execute(
369 : const ucb::Command& aCommand,
370 : sal_Int32 /*CommandId*/,
371 : const uno::Reference< ucb::XCommandEnvironment >& Environment )
372 : throw( uno::Exception,
373 : ucb::CommandAbortedException,
374 : uno::RuntimeException )
375 : {
376 3 : uno::Any aRet;
377 :
378 3 : if ( aCommand.Name == "getPropertyValues" )
379 : {
380 : //////////////////////////////////////////////////////////////////
381 : // getPropertyValues
382 : //////////////////////////////////////////////////////////////////
383 :
384 3 : uno::Sequence< beans::Property > Properties;
385 3 : if ( !( aCommand.Argument >>= Properties ) )
386 : {
387 : ucbhelper::cancelCommandExecution(
388 : uno::makeAny( lang::IllegalArgumentException(
389 : rtl::OUString( "Wrong argument type!" ),
390 : static_cast< cppu::OWeakObject * >( this ),
391 : -1 ) ),
392 0 : Environment );
393 : // Unreachable
394 : }
395 :
396 3 : aRet <<= getPropertyValues( Properties );
397 : }
398 0 : else if ( aCommand.Name == "setPropertyValues" )
399 : {
400 : //////////////////////////////////////////////////////////////////
401 : // setPropertyValues
402 : //////////////////////////////////////////////////////////////////
403 :
404 0 : uno::Sequence< beans::PropertyValue > aProperties;
405 0 : if ( !( aCommand.Argument >>= aProperties ) )
406 : {
407 : ucbhelper::cancelCommandExecution(
408 : uno::makeAny( lang::IllegalArgumentException(
409 : rtl::OUString( "Wrong argument type!" ),
410 : static_cast< cppu::OWeakObject * >( this ),
411 : -1 ) ),
412 0 : Environment );
413 : // Unreachable
414 : }
415 :
416 0 : if ( !aProperties.getLength() )
417 : {
418 : ucbhelper::cancelCommandExecution(
419 : uno::makeAny( lang::IllegalArgumentException(
420 : rtl::OUString( "No properties!" ),
421 : static_cast< cppu::OWeakObject * >( this ),
422 : -1 ) ),
423 0 : Environment );
424 : // Unreachable
425 : }
426 :
427 0 : aRet <<= setPropertyValues( aProperties, Environment );
428 : }
429 0 : else if ( aCommand.Name == "getPropertySetInfo" )
430 : {
431 : //////////////////////////////////////////////////////////////////
432 : // getPropertySetInfo
433 : //////////////////////////////////////////////////////////////////
434 :
435 0 : aRet <<= getPropertySetInfo( Environment );
436 : }
437 0 : else if ( aCommand.Name == "getCommandInfo" )
438 : {
439 : //////////////////////////////////////////////////////////////////
440 : // getCommandInfo
441 : //////////////////////////////////////////////////////////////////
442 :
443 0 : aRet <<= getCommandInfo( Environment );
444 : }
445 0 : else if ( aCommand.Name == "open" )
446 : {
447 : //////////////////////////////////////////////////////////////////
448 : // open
449 : //////////////////////////////////////////////////////////////////
450 :
451 0 : ucb::OpenCommandArgument2 aOpenCommand;
452 0 : if ( !( aCommand.Argument >>= aOpenCommand ) )
453 : {
454 : ucbhelper::cancelCommandExecution(
455 : uno::makeAny( lang::IllegalArgumentException(
456 : rtl::OUString( "Wrong argument type!" ),
457 : static_cast< cppu::OWeakObject * >( this ),
458 : -1 ) ),
459 0 : Environment );
460 : // Unreachable
461 : }
462 :
463 0 : aRet = open( aOpenCommand, Environment );
464 : }
465 0 : else if ( aCommand.Name == "insert" )
466 : {
467 : //////////////////////////////////////////////////////////////////
468 : // insert ( Supported by folders and streams only )
469 : //////////////////////////////////////////////////////////////////
470 :
471 0 : ContentType eType = m_aProps.getType();
472 0 : if ( ( eType != FOLDER ) && ( eType != STREAM ) )
473 : {
474 : ucbhelper::cancelCommandExecution(
475 : uno::makeAny( ucb::UnsupportedCommandException(
476 : rtl::OUString( "insert command only supported by "
477 : "folders and streams!" ),
478 : static_cast< cppu::OWeakObject * >( this ) ) ),
479 0 : Environment );
480 : // Unreachable
481 : }
482 :
483 : #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT
484 0 : if ( eType == STREAM )
485 : {
486 0 : Uri aUri( m_xIdentifier->getContentIdentifier() );
487 0 : Uri aParentUri( aUri.getParentUri() );
488 0 : if ( aParentUri.isDocument() )
489 : {
490 : ucbhelper::cancelCommandExecution(
491 : uno::makeAny( ucb::UnsupportedCommandException(
492 : rtl::OUString( "insert command not supported by "
493 : "streams that are direct children "
494 : "of document root!" ),
495 : static_cast< cppu::OWeakObject * >(
496 : this ) ) ),
497 0 : Environment );
498 : // Unreachable
499 0 : }
500 : }
501 : #endif
502 0 : ucb::InsertCommandArgument aArg;
503 0 : if ( !( aCommand.Argument >>= aArg ) )
504 : {
505 : ucbhelper::cancelCommandExecution(
506 : uno::makeAny( lang::IllegalArgumentException(
507 : rtl::OUString( "Wrong argument type!" ),
508 : static_cast< cppu::OWeakObject * >( this ),
509 : -1 ) ),
510 0 : Environment );
511 : // Unreachable
512 : }
513 :
514 : sal_Int32 nNameClash = aArg.ReplaceExisting
515 : ? ucb::NameClash::OVERWRITE
516 0 : : ucb::NameClash::ERROR;
517 0 : insert( aArg.Data, nNameClash, Environment );
518 : }
519 0 : else if ( aCommand.Name == "delete" )
520 : {
521 : //////////////////////////////////////////////////////////////////
522 : // delete ( Supported by folders and streams only )
523 : //////////////////////////////////////////////////////////////////
524 :
525 : {
526 0 : osl::MutexGuard aGuard( m_aMutex );
527 :
528 0 : ContentType eType = m_aProps.getType();
529 0 : if ( ( eType != FOLDER ) && ( eType != STREAM ) )
530 : {
531 : ucbhelper::cancelCommandExecution(
532 : uno::makeAny( ucb::UnsupportedCommandException(
533 : rtl::OUString( "delete command only supported by "
534 : "folders and streams!" ),
535 : static_cast< cppu::OWeakObject * >(
536 : this ) ) ),
537 0 : Environment );
538 : // Unreachable
539 0 : }
540 : }
541 :
542 0 : sal_Bool bDeletePhysical = sal_False;
543 0 : aCommand.Argument >>= bDeletePhysical;
544 0 : destroy( bDeletePhysical, Environment );
545 :
546 : // Remove own and all children's persistent data.
547 0 : if ( !removeData() )
548 : {
549 : uno::Any aProps
550 : = uno::makeAny(
551 : beans::PropertyValue(
552 : rtl::OUString( "Uri"),
553 : -1,
554 0 : uno::makeAny(m_xIdentifier->
555 0 : getContentIdentifier()),
556 0 : beans::PropertyState_DIRECT_VALUE));
557 : ucbhelper::cancelCommandExecution(
558 : ucb::IOErrorCode_CANT_WRITE,
559 : uno::Sequence< uno::Any >(&aProps, 1),
560 : Environment,
561 : rtl::OUString( "Cannot remove persistent data!" ),
562 0 : this );
563 : // Unreachable
564 : }
565 :
566 : // Remove own and all children's Additional Core Properties.
567 0 : removeAdditionalPropertySet( sal_True );
568 : }
569 0 : else if ( aCommand.Name == "transfer" )
570 : {
571 : //////////////////////////////////////////////////////////////////
572 : // transfer ( Supported by document and folders only )
573 : //////////////////////////////////////////////////////////////////
574 :
575 : {
576 0 : osl::MutexGuard aGuard( m_aMutex );
577 :
578 0 : ContentType eType = m_aProps.getType();
579 0 : if ( ( eType != FOLDER ) && ( eType != DOCUMENT ) )
580 : {
581 : ucbhelper::cancelCommandExecution(
582 : uno::makeAny( ucb::UnsupportedCommandException(
583 : rtl::OUString( "transfer command only supported "
584 : "by folders and documents!" ),
585 : static_cast< cppu::OWeakObject * >(
586 : this ) ) ),
587 0 : Environment );
588 : // Unreachable
589 0 : }
590 : }
591 :
592 0 : ucb::TransferInfo aInfo;
593 0 : if ( !( aCommand.Argument >>= aInfo ) )
594 : {
595 : OSL_FAIL( "Wrong argument type!" );
596 : ucbhelper::cancelCommandExecution(
597 : uno::makeAny( lang::IllegalArgumentException(
598 : rtl::OUString( "Wrong argument type!" ),
599 : static_cast< cppu::OWeakObject * >( this ),
600 : -1 ) ),
601 0 : Environment );
602 : // Unreachable
603 : }
604 :
605 0 : transfer( aInfo, Environment );
606 : }
607 0 : else if ( aCommand.Name == "createNewContent" )
608 : {
609 : //////////////////////////////////////////////////////////////////
610 : // createNewContent ( Supported by document and folders only )
611 : //////////////////////////////////////////////////////////////////
612 :
613 : {
614 0 : osl::MutexGuard aGuard( m_aMutex );
615 :
616 0 : ContentType eType = m_aProps.getType();
617 0 : if ( ( eType != FOLDER ) && ( eType != DOCUMENT ) )
618 : {
619 : ucbhelper::cancelCommandExecution(
620 : uno::makeAny( ucb::UnsupportedCommandException(
621 : rtl::OUString( "createNewContent command only "
622 : "supported by folders and "
623 : "documents!" ),
624 : static_cast< cppu::OWeakObject * >(
625 : this ) ) ),
626 0 : Environment );
627 : // Unreachable
628 0 : }
629 : }
630 :
631 0 : ucb::ContentInfo aInfo;
632 0 : if ( !( aCommand.Argument >>= aInfo ) )
633 : {
634 : OSL_FAIL( "Wrong argument type!" );
635 : ucbhelper::cancelCommandExecution(
636 : uno::makeAny( lang::IllegalArgumentException(
637 : rtl::OUString( "Wrong argument type!" ),
638 : static_cast< cppu::OWeakObject * >( this ),
639 : -1 ) ),
640 0 : Environment );
641 : // Unreachable
642 : }
643 :
644 0 : aRet <<= createNewContent( aInfo );
645 : }
646 : else
647 : {
648 : //////////////////////////////////////////////////////////////////
649 : // Unsupported command
650 : //////////////////////////////////////////////////////////////////
651 :
652 : ucbhelper::cancelCommandExecution(
653 : uno::makeAny( ucb::UnsupportedCommandException(
654 : rtl::OUString(),
655 : static_cast< cppu::OWeakObject * >( this ) ) ),
656 0 : Environment );
657 : // Unreachable
658 : }
659 :
660 3 : return aRet;
661 : }
662 :
663 : //=========================================================================
664 : // virtual
665 0 : void SAL_CALL Content::abort( sal_Int32 /*CommandId*/ )
666 : throw( uno::RuntimeException )
667 : {
668 0 : }
669 :
670 : //=========================================================================
671 : //
672 : // XContentCreator methods.
673 : //
674 : //=========================================================================
675 :
676 : // virtual
677 : uno::Sequence< ucb::ContentInfo > SAL_CALL
678 0 : Content::queryCreatableContentsInfo()
679 : throw( uno::RuntimeException )
680 : {
681 0 : return m_aProps.getCreatableContentsInfo();
682 : }
683 :
684 : //=========================================================================
685 : // virtual
686 : uno::Reference< ucb::XContent > SAL_CALL
687 0 : Content::createNewContent( const ucb::ContentInfo& Info )
688 : throw( uno::RuntimeException )
689 : {
690 0 : if ( m_aProps.isContentCreator() )
691 : {
692 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
693 :
694 0 : if ( Info.Type.isEmpty() )
695 0 : return uno::Reference< ucb::XContent >();
696 :
697 0 : sal_Bool bCreateFolder = Info.Type == TDOC_FOLDER_CONTENT_TYPE;
698 :
699 : #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT
700 : // streams cannot be created as direct children of document root
701 0 : if ( !bCreateFolder && ( m_aProps.getType() == DOCUMENT ) )
702 : {
703 : OSL_FAIL( "Content::createNewContent - streams cannot be "
704 : "created as direct children of document root!" );
705 0 : return uno::Reference< ucb::XContent >();
706 : }
707 : #endif
708 0 : if ( !bCreateFolder && Info.Type != TDOC_STREAM_CONTENT_TYPE )
709 : {
710 : OSL_FAIL( "Content::createNewContent - unsupported type!" );
711 0 : return uno::Reference< ucb::XContent >();
712 : }
713 :
714 0 : rtl::OUString aURL = m_xIdentifier->getContentIdentifier();
715 :
716 : OSL_ENSURE( !aURL.isEmpty(),
717 : "Content::createNewContent - empty identifier!" );
718 :
719 0 : if ( ( aURL.lastIndexOf( '/' ) + 1 ) != aURL.getLength() )
720 0 : aURL += rtl::OUString("/");
721 :
722 0 : if ( bCreateFolder )
723 0 : aURL += rtl::OUString("New_Folder");
724 : else
725 0 : aURL += rtl::OUString("New_Stream");
726 :
727 : uno::Reference< ucb::XContentIdentifier > xId
728 0 : = new ::ucbhelper::ContentIdentifier( aURL );
729 :
730 0 : return create( m_xContext, m_pProvider, xId, Info );
731 : }
732 : else
733 : {
734 : OSL_FAIL( "createNewContent called on non-contentcreator object!" );
735 0 : return uno::Reference< ucb::XContent >();
736 : }
737 : }
738 :
739 : //=========================================================================
740 : // virtual
741 0 : rtl::OUString Content::getParentURL()
742 : {
743 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
744 0 : Uri aUri( m_xIdentifier->getContentIdentifier() );
745 0 : return aUri.getParentUri();
746 : }
747 :
748 : //=========================================================================
749 : uno::Reference< ucb::XContentIdentifier >
750 0 : Content::makeNewIdentifier( const rtl::OUString& rTitle )
751 : {
752 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
753 :
754 : // Assemble new content identifier...
755 0 : Uri aUri( m_xIdentifier->getContentIdentifier() );
756 0 : rtl::OUStringBuffer aNewURL = aUri.getParentUri();
757 0 : aNewURL.append( ::ucb_impl::urihelper::encodeSegment( rTitle ) );
758 :
759 : return
760 : uno::Reference< ucb::XContentIdentifier >(
761 0 : new ::ucbhelper::ContentIdentifier( aNewURL.makeStringAndClear() ) );
762 : }
763 :
764 : //=========================================================================
765 0 : void Content::queryChildren( ContentRefList& rChildren )
766 : {
767 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
768 :
769 : // Only folders (root, documents, folders) have children.
770 0 : if ( !m_aProps.getIsFolder() )
771 0 : return;
772 :
773 : // Obtain a list with a snapshot of all currently instanciated contents
774 : // from provider and extract the contents which are direct children
775 : // of this content.
776 :
777 0 : ::ucbhelper::ContentRefList aAllContents;
778 0 : m_xProvider->queryExistingContents( aAllContents );
779 :
780 0 : rtl::OUString aURL = m_xIdentifier->getContentIdentifier();
781 0 : sal_Int32 nURLPos = aURL.lastIndexOf( '/' );
782 :
783 0 : if ( nURLPos != ( aURL.getLength() - 1 ) )
784 : {
785 : // No trailing slash found. Append.
786 0 : aURL += rtl::OUString("/");
787 : }
788 :
789 0 : sal_Int32 nLen = aURL.getLength();
790 :
791 0 : ::ucbhelper::ContentRefList::const_iterator it = aAllContents.begin();
792 0 : ::ucbhelper::ContentRefList::const_iterator end = aAllContents.end();
793 :
794 0 : while ( it != end )
795 : {
796 0 : ::ucbhelper::ContentImplHelperRef xChild = (*it);
797 : rtl::OUString aChildURL
798 0 : = xChild->getIdentifier()->getContentIdentifier();
799 :
800 : // Is aURL a prefix of aChildURL?
801 0 : if ( ( aChildURL.getLength() > nLen ) &&
802 0 : ( aChildURL.compareTo( aURL, nLen ) == 0 ) )
803 : {
804 0 : sal_Int32 nPos = nLen;
805 0 : nPos = aChildURL.indexOf( '/', nPos );
806 :
807 0 : if ( ( nPos == -1 ) ||
808 0 : ( nPos == ( aChildURL.getLength() - 1 ) ) )
809 : {
810 : // No further slashes / only a final slash. It's a child!
811 : rChildren.push_back(
812 : ContentRef(
813 0 : static_cast< Content * >( xChild.get() ) ) );
814 : }
815 : }
816 0 : ++it;
817 0 : }
818 : }
819 :
820 : //=========================================================================
821 0 : sal_Bool Content::exchangeIdentity(
822 : const uno::Reference< ucb::XContentIdentifier >& xNewId )
823 : {
824 0 : if ( !xNewId.is() )
825 0 : return sal_False;
826 :
827 0 : osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
828 :
829 0 : uno::Reference< ucb::XContent > xThis = this;
830 :
831 : // Already persistent?
832 0 : if ( m_eState != PERSISTENT )
833 : {
834 : OSL_FAIL( "Content::exchangeIdentity - Not persistent!" );
835 0 : return sal_False;
836 : }
837 :
838 : // Only folders and streams can be renamed -> exchange identity.
839 0 : ContentType eType = m_aProps.getType();
840 0 : if ( ( eType == ROOT ) || ( eType == DOCUMENT ) )
841 : {
842 : OSL_FAIL( "Content::exchangeIdentity - "
843 : "Not supported by root or document!" );
844 0 : return sal_False;
845 : }
846 :
847 : // Exchange own identitity.
848 :
849 : // Fail, if a content with given id already exists.
850 0 : if ( !hasData( Uri( xNewId->getContentIdentifier() ) ) )
851 : {
852 0 : rtl::OUString aOldURL = m_xIdentifier->getContentIdentifier();
853 :
854 0 : aGuard.clear();
855 0 : if ( exchange( xNewId ) )
856 : {
857 0 : if ( eType == FOLDER )
858 : {
859 : // Process instanciated children...
860 :
861 0 : ContentRefList aChildren;
862 0 : queryChildren( aChildren );
863 :
864 0 : ContentRefList::const_iterator it = aChildren.begin();
865 0 : ContentRefList::const_iterator end = aChildren.end();
866 :
867 0 : while ( it != end )
868 : {
869 0 : ContentRef xChild = (*it);
870 :
871 : // Create new content identifier for the child...
872 : uno::Reference< ucb::XContentIdentifier > xOldChildId
873 0 : = xChild->getIdentifier();
874 : rtl::OUString aOldChildURL
875 0 : = xOldChildId->getContentIdentifier();
876 : rtl::OUString aNewChildURL
877 : = aOldChildURL.replaceAt(
878 : 0,
879 : aOldURL.getLength(),
880 0 : xNewId->getContentIdentifier() );
881 : uno::Reference< ucb::XContentIdentifier > xNewChildId
882 0 : = new ::ucbhelper::ContentIdentifier( aNewChildURL );
883 :
884 0 : if ( !xChild->exchangeIdentity( xNewChildId ) )
885 0 : return sal_False;
886 :
887 0 : ++it;
888 0 : }
889 : }
890 0 : return sal_True;
891 0 : }
892 : }
893 :
894 : OSL_FAIL( "Content::exchangeIdentity - "
895 : "Panic! Cannot exchange identity!" );
896 0 : return sal_False;
897 : }
898 :
899 : //=========================================================================
900 : // static
901 0 : uno::Reference< sdbc::XRow > Content::getPropertyValues(
902 : const uno::Reference< uno::XComponentContext >& rxContext,
903 : const uno::Sequence< beans::Property >& rProperties,
904 : ContentProvider* pProvider,
905 : const rtl::OUString& rContentId )
906 : {
907 0 : ContentProperties aData;
908 0 : if ( loadData( pProvider, rContentId, aData ) )
909 : {
910 : return getPropertyValues(
911 0 : rxContext, rProperties, aData, pProvider, rContentId );
912 : }
913 : else
914 : {
915 : rtl::Reference< ::ucbhelper::PropertyValueSet > xRow
916 0 : = new ::ucbhelper::PropertyValueSet( rxContext );
917 :
918 0 : sal_Int32 nCount = rProperties.getLength();
919 0 : if ( nCount )
920 : {
921 0 : const beans::Property* pProps = rProperties.getConstArray();
922 0 : for ( sal_Int32 n = 0; n < nCount; ++n )
923 0 : xRow->appendVoid( pProps[ n ] );
924 : }
925 :
926 0 : return uno::Reference< sdbc::XRow >( xRow.get() );
927 0 : }
928 : }
929 :
930 : //=========================================================================
931 : // static
932 3 : uno::Reference< sdbc::XRow > Content::getPropertyValues(
933 : const uno::Reference< uno::XComponentContext >& rxContext,
934 : const uno::Sequence< beans::Property >& rProperties,
935 : const ContentProperties& rData,
936 : ContentProvider* pProvider,
937 : const rtl::OUString& rContentId )
938 : {
939 : // Note: Empty sequence means "get values of all supported properties".
940 :
941 : rtl::Reference< ::ucbhelper::PropertyValueSet > xRow
942 3 : = new ::ucbhelper::PropertyValueSet( rxContext );
943 :
944 3 : sal_Int32 nCount = rProperties.getLength();
945 3 : if ( nCount )
946 : {
947 3 : uno::Reference< beans::XPropertySet > xAdditionalPropSet;
948 3 : sal_Bool bTriedToGetAdditonalPropSet = sal_False;
949 :
950 3 : const beans::Property* pProps = rProperties.getConstArray();
951 6 : for ( sal_Int32 n = 0; n < nCount; ++n )
952 : {
953 3 : const beans::Property& rProp = pProps[ n ];
954 :
955 : // Process Core properties.
956 :
957 3 : if ( rProp.Name == "ContentType" )
958 : {
959 0 : xRow->appendString ( rProp, rData.getContentType() );
960 : }
961 3 : else if ( rProp.Name == "Title" )
962 : {
963 0 : xRow->appendString ( rProp, rData.getTitle() );
964 : }
965 3 : else if ( rProp.Name == "IsDocument" )
966 : {
967 0 : xRow->appendBoolean( rProp, rData.getIsDocument() );
968 : }
969 3 : else if ( rProp.Name == "IsFolder" )
970 : {
971 0 : xRow->appendBoolean( rProp, rData.getIsFolder() );
972 : }
973 3 : else if ( rProp.Name == "CreatableContentsInfo" )
974 : {
975 : xRow->appendObject(
976 0 : rProp, uno::makeAny( rData.getCreatableContentsInfo() ) );
977 : }
978 3 : else if ( rProp.Name == "Storage" )
979 : {
980 : // Storage is only supported by folders.
981 0 : ContentType eType = rData.getType();
982 0 : if ( eType == FOLDER )
983 : xRow->appendObject(
984 : rProp,
985 : uno::makeAny(
986 0 : pProvider->queryStorageClone( rContentId ) ) );
987 : else
988 0 : xRow->appendVoid( rProp );
989 : }
990 3 : else if ( rProp.Name == "DocumentModel" )
991 : {
992 : // DocumentModel is only supported by documents.
993 3 : ContentType eType = rData.getType();
994 3 : if ( eType == DOCUMENT )
995 : xRow->appendObject(
996 : rProp,
997 : uno::makeAny(
998 3 : pProvider->queryDocumentModel( rContentId ) ) );
999 : else
1000 0 : xRow->appendVoid( rProp );
1001 : }
1002 : else
1003 : {
1004 : // Not a Core Property! Maybe it's an Additional Core Property?!
1005 :
1006 0 : if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() )
1007 : {
1008 : xAdditionalPropSet
1009 : = uno::Reference< beans::XPropertySet >(
1010 : pProvider->getAdditionalPropertySet( rContentId,
1011 : sal_False ),
1012 0 : uno::UNO_QUERY );
1013 0 : bTriedToGetAdditonalPropSet = sal_True;
1014 : }
1015 :
1016 0 : if ( xAdditionalPropSet.is() )
1017 : {
1018 0 : if ( !xRow->appendPropertySetValue(
1019 : xAdditionalPropSet,
1020 0 : rProp ) )
1021 : {
1022 : // Append empty entry.
1023 0 : xRow->appendVoid( rProp );
1024 : }
1025 : }
1026 : else
1027 : {
1028 : // Append empty entry.
1029 0 : xRow->appendVoid( rProp );
1030 : }
1031 : }
1032 3 : }
1033 : }
1034 : else
1035 : {
1036 : // Append all Core Properties.
1037 : xRow->appendString (
1038 : beans::Property( rtl::OUString("ContentType"),
1039 : -1,
1040 0 : getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
1041 : beans::PropertyAttribute::BOUND
1042 : | beans::PropertyAttribute::READONLY ),
1043 0 : rData.getContentType() );
1044 :
1045 0 : ContentType eType = rData.getType();
1046 :
1047 : xRow->appendString (
1048 : beans::Property( rtl::OUString("Title"),
1049 : -1,
1050 0 : getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
1051 : // Title is read-only for root and documents.
1052 : beans::PropertyAttribute::BOUND ||
1053 : ( ( eType == ROOT ) || ( eType == DOCUMENT ) )
1054 : ? beans::PropertyAttribute::READONLY
1055 : : 0 ),
1056 0 : rData.getTitle() );
1057 : xRow->appendBoolean(
1058 : beans::Property( rtl::OUString("IsDocument"),
1059 : -1,
1060 0 : getCppuBooleanType(),
1061 : beans::PropertyAttribute::BOUND
1062 : | beans::PropertyAttribute::READONLY ),
1063 0 : rData.getIsDocument() );
1064 : xRow->appendBoolean(
1065 : beans::Property( rtl::OUString("IsFolder"),
1066 : -1,
1067 0 : getCppuBooleanType(),
1068 : beans::PropertyAttribute::BOUND
1069 : | beans::PropertyAttribute::READONLY ),
1070 0 : rData.getIsFolder() );
1071 : xRow->appendObject(
1072 : beans::Property(
1073 : rtl::OUString("CreatableContentsInfo"),
1074 : -1,
1075 : getCppuType( static_cast<
1076 0 : const uno::Sequence< ucb::ContentInfo > * >( 0 ) ),
1077 : beans::PropertyAttribute::BOUND
1078 : | beans::PropertyAttribute::READONLY ),
1079 0 : uno::makeAny( rData.getCreatableContentsInfo() ) );
1080 :
1081 : // Storage is only supported by folders.
1082 0 : if ( eType == FOLDER )
1083 : xRow->appendObject(
1084 : beans::Property( rtl::OUString("Storage"),
1085 : -1,
1086 : getCppuType(
1087 : static_cast<
1088 0 : const uno::Reference< embed::XStorage > * >( 0 ) ),
1089 : beans::PropertyAttribute::BOUND
1090 : | beans::PropertyAttribute::READONLY ),
1091 0 : uno::makeAny( pProvider->queryStorageClone( rContentId ) ) );
1092 :
1093 : // DocumentModel is only supported by documents.
1094 0 : if ( eType == DOCUMENT )
1095 : xRow->appendObject(
1096 : beans::Property( rtl::OUString("DocumentModel"),
1097 : -1,
1098 : getCppuType(
1099 : static_cast<
1100 0 : const uno::Reference< frame::XModel > * >( 0 ) ),
1101 : beans::PropertyAttribute::BOUND
1102 : | beans::PropertyAttribute::READONLY ),
1103 : uno::makeAny(
1104 0 : pProvider->queryDocumentModel( rContentId ) ) );
1105 :
1106 : // Append all Additional Core Properties.
1107 :
1108 : uno::Reference< beans::XPropertySet > xSet(
1109 : pProvider->getAdditionalPropertySet( rContentId, sal_False ),
1110 0 : uno::UNO_QUERY );
1111 0 : xRow->appendPropertySet( xSet );
1112 : }
1113 :
1114 3 : return uno::Reference< sdbc::XRow >( xRow.get() );
1115 : }
1116 :
1117 : //=========================================================================
1118 3 : uno::Reference< sdbc::XRow > Content::getPropertyValues(
1119 : const uno::Sequence< beans::Property >& rProperties )
1120 : {
1121 3 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
1122 : return getPropertyValues( m_xContext,
1123 : rProperties,
1124 : m_aProps,
1125 : m_pProvider,
1126 3 : m_xIdentifier->getContentIdentifier() );
1127 : }
1128 :
1129 : //=========================================================================
1130 0 : uno::Sequence< uno::Any > Content::setPropertyValues(
1131 : const uno::Sequence< beans::PropertyValue >& rValues,
1132 : const uno::Reference< ucb::XCommandEnvironment > & xEnv )
1133 : throw( uno::Exception )
1134 : {
1135 0 : osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1136 :
1137 0 : uno::Sequence< uno::Any > aRet( rValues.getLength() );
1138 0 : uno::Sequence< beans::PropertyChangeEvent > aChanges( rValues.getLength() );
1139 0 : sal_Int32 nChanged = 0;
1140 :
1141 0 : beans::PropertyChangeEvent aEvent;
1142 0 : aEvent.Source = static_cast< cppu::OWeakObject * >( this );
1143 0 : aEvent.Further = sal_False;
1144 : // aEvent.PropertyName =
1145 0 : aEvent.PropertyHandle = -1;
1146 : // aEvent.OldValue =
1147 : // aEvent.NewValue =
1148 :
1149 0 : const beans::PropertyValue* pValues = rValues.getConstArray();
1150 0 : sal_Int32 nCount = rValues.getLength();
1151 :
1152 0 : uno::Reference< ucb::XPersistentPropertySet > xAdditionalPropSet;
1153 0 : sal_Bool bTriedToGetAdditonalPropSet = sal_False;
1154 :
1155 0 : sal_Bool bExchange = sal_False;
1156 0 : rtl::OUString aOldTitle;
1157 0 : sal_Int32 nTitlePos = -1;
1158 :
1159 0 : for ( sal_Int32 n = 0; n < nCount; ++n )
1160 : {
1161 0 : const beans::PropertyValue& rValue = pValues[ n ];
1162 :
1163 0 : if ( rValue.Name == "ContentType" )
1164 : {
1165 : // Read-only property!
1166 0 : aRet[ n ] <<= lang::IllegalAccessException(
1167 : rtl::OUString( "Property is read-only!" ),
1168 0 : static_cast< cppu::OWeakObject * >( this ) );
1169 : }
1170 0 : else if ( rValue.Name == "IsDocument" )
1171 : {
1172 : // Read-only property!
1173 0 : aRet[ n ] <<= lang::IllegalAccessException(
1174 : rtl::OUString( "Property is read-only!" ),
1175 0 : static_cast< cppu::OWeakObject * >( this ) );
1176 : }
1177 0 : else if ( rValue.Name == "IsFolder" )
1178 : {
1179 : // Read-only property!
1180 0 : aRet[ n ] <<= lang::IllegalAccessException(
1181 : rtl::OUString( "Property is read-only!" ),
1182 0 : static_cast< cppu::OWeakObject * >( this ) );
1183 : }
1184 0 : else if ( rValue.Name == "CreatableContentsInfo" )
1185 : {
1186 : // Read-only property!
1187 0 : aRet[ n ] <<= lang::IllegalAccessException(
1188 : rtl::OUString( "Property is read-only!" ),
1189 0 : static_cast< cppu::OWeakObject * >( this ) );
1190 : }
1191 0 : else if ( rValue.Name == "Title" )
1192 : {
1193 : // Title is read-only for root and documents.
1194 0 : ContentType eType = m_aProps.getType();
1195 0 : if ( ( eType == ROOT ) || ( eType == DOCUMENT ) )
1196 : {
1197 0 : aRet[ n ] <<= lang::IllegalAccessException(
1198 : rtl::OUString( "Property is read-only!" ),
1199 0 : static_cast< cppu::OWeakObject * >( this ) );
1200 : }
1201 : else
1202 : {
1203 0 : rtl::OUString aNewValue;
1204 0 : if ( rValue.Value >>= aNewValue )
1205 : {
1206 : // No empty titles!
1207 0 : if ( !aNewValue.isEmpty() )
1208 : {
1209 0 : if ( aNewValue != m_aProps.getTitle() )
1210 : {
1211 : // modified title -> modified URL -> exchange !
1212 0 : if ( m_eState == PERSISTENT )
1213 0 : bExchange = sal_True;
1214 :
1215 0 : aOldTitle = m_aProps.getTitle();
1216 0 : m_aProps.setTitle( aNewValue );
1217 :
1218 : // property change event will be sent later...
1219 :
1220 : // remember position within sequence of values
1221 : // (for error handling).
1222 0 : nTitlePos = n;
1223 : }
1224 : }
1225 : else
1226 : {
1227 0 : aRet[ n ] <<= lang::IllegalArgumentException(
1228 : rtl::OUString( "Empty Title not allowed!" ),
1229 : static_cast< cppu::OWeakObject * >( this ),
1230 0 : -1 );
1231 : }
1232 : }
1233 : else
1234 : {
1235 0 : aRet[ n ] <<= beans::IllegalTypeException(
1236 : rtl::OUString( "Title Property value has wrong type!" ),
1237 0 : static_cast< cppu::OWeakObject * >( this ) );
1238 0 : }
1239 : }
1240 : }
1241 0 : else if ( rValue.Name == "Storage" )
1242 : {
1243 0 : ContentType eType = m_aProps.getType();
1244 0 : if ( eType == FOLDER )
1245 : {
1246 0 : aRet[ n ] <<= lang::IllegalAccessException(
1247 : rtl::OUString( "Property is read-only!" ),
1248 0 : static_cast< cppu::OWeakObject * >( this ) );
1249 : }
1250 : else
1251 : {
1252 : // Storage is only supported by folders.
1253 0 : aRet[ n ] <<= beans::UnknownPropertyException(
1254 : rtl::OUString( "Storage property only supported by folders" ),
1255 0 : static_cast< cppu::OWeakObject * >( this ) );
1256 : }
1257 : }
1258 0 : else if ( rValue.Name == "DocumentModel" )
1259 : {
1260 0 : ContentType eType = m_aProps.getType();
1261 0 : if ( eType == DOCUMENT )
1262 : {
1263 0 : aRet[ n ] <<= lang::IllegalAccessException(
1264 : rtl::OUString( "Property is read-only!" ),
1265 0 : static_cast< cppu::OWeakObject * >( this ) );
1266 : }
1267 : else
1268 : {
1269 : // Storage is only supported by folders.
1270 0 : aRet[ n ] <<= beans::UnknownPropertyException(
1271 : rtl::OUString( "DocumentModel property only supported by "
1272 : "documents" ),
1273 0 : static_cast< cppu::OWeakObject * >( this ) );
1274 : }
1275 : }
1276 : else
1277 : {
1278 : // Not a Core Property! Maybe it's an Additional Core Property?!
1279 :
1280 0 : if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() )
1281 : {
1282 0 : xAdditionalPropSet = getAdditionalPropertySet( sal_False );
1283 0 : bTriedToGetAdditonalPropSet = sal_True;
1284 : }
1285 :
1286 0 : if ( xAdditionalPropSet.is() )
1287 : {
1288 : try
1289 : {
1290 0 : uno::Any aOldValue = xAdditionalPropSet->getPropertyValue(
1291 0 : rValue.Name );
1292 0 : if ( aOldValue != rValue.Value )
1293 : {
1294 0 : xAdditionalPropSet->setPropertyValue(
1295 0 : rValue.Name, rValue.Value );
1296 :
1297 0 : aEvent.PropertyName = rValue.Name;
1298 0 : aEvent.OldValue = aOldValue;
1299 0 : aEvent.NewValue = rValue.Value;
1300 :
1301 0 : aChanges.getArray()[ nChanged ] = aEvent;
1302 0 : nChanged++;
1303 0 : }
1304 : }
1305 0 : catch ( beans::UnknownPropertyException const & e )
1306 : {
1307 0 : aRet[ n ] <<= e;
1308 : }
1309 0 : catch ( lang::WrappedTargetException const & e )
1310 : {
1311 0 : aRet[ n ] <<= e;
1312 : }
1313 0 : catch ( beans::PropertyVetoException const & e )
1314 : {
1315 0 : aRet[ n ] <<= e;
1316 : }
1317 0 : catch ( lang::IllegalArgumentException const & e )
1318 : {
1319 0 : aRet[ n ] <<= e;
1320 : }
1321 : }
1322 : else
1323 : {
1324 0 : aRet[ n ] <<= uno::Exception(
1325 : rtl::OUString( "No property set for storing the value!" ),
1326 0 : static_cast< cppu::OWeakObject * >( this ) );
1327 : }
1328 : }
1329 : }
1330 :
1331 0 : if ( bExchange )
1332 : {
1333 : uno::Reference< ucb::XContentIdentifier > xOldId
1334 0 : = m_xIdentifier;
1335 : uno::Reference< ucb::XContentIdentifier > xNewId
1336 0 : = makeNewIdentifier( m_aProps.getTitle() );
1337 :
1338 0 : aGuard.clear();
1339 0 : if ( exchangeIdentity( xNewId ) )
1340 : {
1341 : // Adapt persistent data.
1342 0 : renameData( xOldId, xNewId );
1343 :
1344 : // Adapt Additional Core Properties.
1345 0 : renameAdditionalPropertySet( xOldId->getContentIdentifier(),
1346 0 : xNewId->getContentIdentifier(),
1347 0 : sal_True );
1348 : }
1349 : else
1350 : {
1351 : // Roll-back.
1352 0 : m_aProps.setTitle( aOldTitle );
1353 0 : aOldTitle = rtl::OUString();
1354 :
1355 : // Set error .
1356 0 : aRet[ nTitlePos ] <<= uno::Exception(
1357 : rtl::OUString("Exchange failed!"),
1358 0 : static_cast< cppu::OWeakObject * >( this ) );
1359 0 : }
1360 : }
1361 :
1362 0 : if ( !aOldTitle.isEmpty() )
1363 : {
1364 0 : aEvent.PropertyName = rtl::OUString("Title");
1365 0 : aEvent.OldValue = uno::makeAny( aOldTitle );
1366 0 : aEvent.NewValue = uno::makeAny( m_aProps.getTitle() );
1367 :
1368 0 : aChanges.getArray()[ nChanged ] = aEvent;
1369 0 : nChanged++;
1370 : }
1371 :
1372 0 : if ( nChanged > 0 )
1373 : {
1374 : // Save changes, if content was already made persistent.
1375 0 : if ( !bExchange && ( m_eState == PERSISTENT ) )
1376 : {
1377 0 : if ( !storeData( uno::Reference< io::XInputStream >(), xEnv ) )
1378 : {
1379 : uno::Any aProps
1380 : = uno::makeAny(
1381 : beans::PropertyValue(
1382 : rtl::OUString( "Uri"),
1383 : -1,
1384 0 : uno::makeAny(m_xIdentifier->
1385 0 : getContentIdentifier()),
1386 0 : beans::PropertyState_DIRECT_VALUE));
1387 : ucbhelper::cancelCommandExecution(
1388 : ucb::IOErrorCode_CANT_WRITE,
1389 : uno::Sequence< uno::Any >(&aProps, 1),
1390 : xEnv,
1391 : rtl::OUString( "Cannot store persistent data!" ),
1392 0 : this );
1393 : // Unreachable
1394 : }
1395 : }
1396 :
1397 0 : aChanges.realloc( nChanged );
1398 :
1399 0 : aGuard.clear();
1400 0 : notifyPropertiesChange( aChanges );
1401 : }
1402 :
1403 0 : return aRet;
1404 : }
1405 :
1406 : //=========================================================================
1407 0 : uno::Any Content::open(
1408 : const ucb::OpenCommandArgument2& rArg,
1409 : const uno::Reference< ucb::XCommandEnvironment >& xEnv )
1410 : throw( uno::Exception )
1411 : {
1412 0 : if ( rArg.Mode == ucb::OpenMode::ALL ||
1413 : rArg.Mode == ucb::OpenMode::FOLDERS ||
1414 : rArg.Mode == ucb::OpenMode::DOCUMENTS )
1415 : {
1416 : //////////////////////////////////////////////////////////////////
1417 : // open command for a folder content
1418 : //////////////////////////////////////////////////////////////////
1419 :
1420 : uno::Reference< ucb::XDynamicResultSet > xSet
1421 0 : = new DynamicResultSet( m_xContext, this, rArg );
1422 0 : return uno::makeAny( xSet );
1423 : }
1424 : else
1425 : {
1426 : //////////////////////////////////////////////////////////////////
1427 : // open command for a document content
1428 : //////////////////////////////////////////////////////////////////
1429 :
1430 0 : if ( ( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE ) ||
1431 : ( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE ) )
1432 : {
1433 : // Currently(?) unsupported.
1434 : ucbhelper::cancelCommandExecution(
1435 : uno::makeAny( ucb::UnsupportedOpenModeException(
1436 : rtl::OUString(),
1437 : static_cast< cppu::OWeakObject * >( this ),
1438 : sal_Int16( rArg.Mode ) ) ),
1439 0 : xEnv );
1440 : // Unreachable
1441 : }
1442 :
1443 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
1444 :
1445 0 : rtl::OUString aURL = m_xIdentifier->getContentIdentifier();
1446 :
1447 : uno::Reference< io::XActiveDataStreamer > xDataStreamer(
1448 0 : rArg.Sink, uno::UNO_QUERY );
1449 0 : if ( xDataStreamer.is() )
1450 : {
1451 : // May throw CommandFailedException, DocumentPasswordRequest!
1452 0 : uno::Reference< io::XStream > xStream = getStream( xEnv );
1453 0 : if ( !xStream.is() )
1454 : {
1455 : // No interaction if we are not persistent!
1456 : uno::Any aProps
1457 : = uno::makeAny(
1458 : beans::PropertyValue(
1459 : rtl::OUString( "Uri"),
1460 : -1,
1461 0 : uno::makeAny(m_xIdentifier->
1462 0 : getContentIdentifier()),
1463 0 : beans::PropertyState_DIRECT_VALUE));
1464 : ucbhelper::cancelCommandExecution(
1465 : ucb::IOErrorCode_CANT_READ,
1466 : uno::Sequence< uno::Any >(&aProps, 1),
1467 : m_eState == PERSISTENT
1468 : ? xEnv
1469 : : uno::Reference< ucb::XCommandEnvironment >(),
1470 : rtl::OUString( "Got no data stream!" ),
1471 0 : this );
1472 : // Unreachable
1473 : }
1474 :
1475 : // Done.
1476 0 : xDataStreamer->setStream( xStream );
1477 : }
1478 : else
1479 : {
1480 0 : uno::Reference< io::XOutputStream > xOut( rArg.Sink, uno::UNO_QUERY );
1481 0 : if ( xOut.is() )
1482 : {
1483 : // PUSH: write data into xOut
1484 :
1485 : // May throw CommandFailedException, DocumentPasswordRequest!
1486 0 : uno::Reference< io::XInputStream > xIn = getInputStream( xEnv );
1487 0 : if ( !xIn.is() )
1488 : {
1489 : // No interaction if we are not persistent!
1490 : uno::Any aProps
1491 : = uno::makeAny(
1492 : beans::PropertyValue(
1493 : rtl::OUString( "Uri"),
1494 : -1,
1495 0 : uno::makeAny(m_xIdentifier->
1496 0 : getContentIdentifier()),
1497 0 : beans::PropertyState_DIRECT_VALUE));
1498 : ucbhelper::cancelCommandExecution(
1499 : ucb::IOErrorCode_CANT_READ,
1500 : uno::Sequence< uno::Any >(&aProps, 1),
1501 : m_eState == PERSISTENT
1502 : ? xEnv
1503 : : uno::Reference< ucb::XCommandEnvironment >(),
1504 : rtl::OUString("Got no data stream!"),
1505 0 : this );
1506 : // Unreachable
1507 : }
1508 :
1509 : try
1510 : {
1511 0 : uno::Sequence< sal_Int8 > aBuffer;
1512 0 : sal_Int32 nRead = xIn->readSomeBytes( aBuffer, 65536 );
1513 :
1514 0 : while ( nRead > 0 )
1515 : {
1516 0 : aBuffer.realloc( nRead );
1517 0 : xOut->writeBytes( aBuffer );
1518 0 : aBuffer.realloc( 0 );
1519 0 : nRead = xIn->readSomeBytes( aBuffer, 65536 );
1520 : }
1521 :
1522 0 : xOut->closeOutput();
1523 : }
1524 0 : catch ( io::NotConnectedException const & )
1525 : {
1526 : // closeOutput, readSomeBytes, writeBytes
1527 : }
1528 0 : catch ( io::BufferSizeExceededException const & )
1529 : {
1530 : // closeOutput, readSomeBytes, writeBytes
1531 : }
1532 0 : catch ( io::IOException const & )
1533 : {
1534 : // closeOutput, readSomeBytes, writeBytes
1535 0 : }
1536 : }
1537 : else
1538 : {
1539 : uno::Reference< io::XActiveDataSink > xDataSink(
1540 0 : rArg.Sink, uno::UNO_QUERY );
1541 0 : if ( xDataSink.is() )
1542 : {
1543 : // PULL: wait for client read
1544 :
1545 : // May throw CommandFailedException, DocumentPasswordRequest!
1546 0 : uno::Reference< io::XInputStream > xIn = getInputStream( xEnv );
1547 0 : if ( !xIn.is() )
1548 : {
1549 : // No interaction if we are not persistent!
1550 : uno::Any aProps
1551 : = uno::makeAny(
1552 : beans::PropertyValue(
1553 : rtl::OUString( "Uri"),
1554 : -1,
1555 0 : uno::makeAny(m_xIdentifier->
1556 0 : getContentIdentifier()),
1557 0 : beans::PropertyState_DIRECT_VALUE));
1558 : ucbhelper::cancelCommandExecution(
1559 : ucb::IOErrorCode_CANT_READ,
1560 : uno::Sequence< uno::Any >(&aProps, 1),
1561 : m_eState == PERSISTENT
1562 : ? xEnv
1563 : : uno::Reference<
1564 : ucb::XCommandEnvironment >(),
1565 : rtl::OUString( "Got no data stream!" ),
1566 0 : this );
1567 : // Unreachable
1568 : }
1569 :
1570 : // Done.
1571 0 : xDataSink->setInputStream( xIn );
1572 : }
1573 : else
1574 : {
1575 : ucbhelper::cancelCommandExecution(
1576 : uno::makeAny(
1577 : ucb::UnsupportedDataSinkException(
1578 : rtl::OUString(),
1579 : static_cast< cppu::OWeakObject * >( this ),
1580 : rArg.Sink ) ),
1581 0 : xEnv );
1582 : // Unreachable
1583 0 : }
1584 0 : }
1585 0 : }
1586 : }
1587 :
1588 0 : return uno::Any();
1589 : }
1590 :
1591 : //=========================================================================
1592 0 : void Content::insert( const uno::Reference< io::XInputStream >& xData,
1593 : sal_Int32 nNameClashResolve,
1594 : const uno::Reference<
1595 : ucb::XCommandEnvironment > & xEnv )
1596 : throw( uno::Exception )
1597 : {
1598 0 : osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1599 :
1600 0 : ContentType eType = m_aProps.getType();
1601 :
1602 : OSL_ENSURE( ( eType == FOLDER ) || ( eType == STREAM ),
1603 : "insert command only supported by streams and folders!" );
1604 :
1605 0 : Uri aUri( m_xIdentifier->getContentIdentifier() );
1606 :
1607 : #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT
1608 : #if OSL_DEBUG_LEVEL > 0
1609 : if ( eType == STREAM )
1610 : {
1611 : Uri aParentUri( aUri.getParentUri() );
1612 : OSL_ENSURE( !aParentUri.isDocument(),
1613 : "insert command not supported by streams that are direct "
1614 : "children of document root!" );
1615 : }
1616 : #endif
1617 : #endif
1618 :
1619 : // Check, if all required properties were set.
1620 0 : if ( eType == FOLDER )
1621 : {
1622 : // Required: Title
1623 :
1624 0 : if ( m_aProps.getTitle().isEmpty() )
1625 0 : m_aProps.setTitle( aUri.getDecodedName() );
1626 : }
1627 : else // stream
1628 : {
1629 : // Required: data
1630 :
1631 0 : if ( !xData.is() )
1632 : {
1633 : ucbhelper::cancelCommandExecution(
1634 : uno::makeAny( ucb::MissingInputStreamException(
1635 : rtl::OUString(),
1636 : static_cast< cppu::OWeakObject * >( this ) ) ),
1637 0 : xEnv );
1638 : // Unreachable
1639 : }
1640 :
1641 : // Required: Title
1642 :
1643 0 : if ( m_aProps.getTitle().isEmpty() )
1644 0 : m_aProps.setTitle( aUri.getDecodedName() );
1645 : }
1646 :
1647 0 : rtl::OUStringBuffer aNewURL = aUri.getParentUri();
1648 0 : aNewURL.append( m_aProps.getTitle() );
1649 0 : Uri aNewUri( aNewURL.makeStringAndClear() );
1650 :
1651 : // Handle possible name clash...
1652 0 : switch ( nNameClashResolve )
1653 : {
1654 : // fail.
1655 : case ucb::NameClash::ERROR:
1656 0 : if ( hasData( aNewUri ) )
1657 : {
1658 : ucbhelper::cancelCommandExecution(
1659 : uno::makeAny( ucb::NameClashException(
1660 : rtl::OUString(),
1661 : static_cast< cppu::OWeakObject * >( this ),
1662 : task::InteractionClassification_ERROR,
1663 0 : m_aProps.getTitle() ) ),
1664 0 : xEnv );
1665 : // Unreachable
1666 : }
1667 0 : break;
1668 :
1669 : // replace (possibly) existing object.
1670 : case ucb::NameClash::OVERWRITE:
1671 0 : break;
1672 :
1673 : // "invent" a new valid title.
1674 : case ucb::NameClash::RENAME:
1675 0 : if ( hasData( aNewUri ) )
1676 : {
1677 0 : sal_Int32 nTry = 0;
1678 :
1679 0 : do
1680 : {
1681 0 : rtl::OUStringBuffer aNew = aNewUri.getUri();
1682 0 : aNew.appendAscii( "_" );
1683 0 : aNew.append( rtl::OUString::valueOf( ++nTry ) );
1684 0 : aNewUri.setUri( aNew.makeStringAndClear() );
1685 : }
1686 0 : while ( hasData( aNewUri ) && ( nTry < 1000 ) );
1687 :
1688 0 : if ( nTry == 1000 )
1689 : {
1690 : ucbhelper::cancelCommandExecution(
1691 : uno::makeAny(
1692 : ucb::UnsupportedNameClashException(
1693 : rtl::OUString( "Unable to resolve name clash!" ),
1694 : static_cast< cppu::OWeakObject * >( this ),
1695 : nNameClashResolve ) ),
1696 0 : xEnv );
1697 : // Unreachable
1698 : }
1699 : else
1700 : {
1701 0 : rtl::OUStringBuffer aNewTitle = m_aProps.getTitle();
1702 0 : aNewTitle.appendAscii( "_" );
1703 0 : aNewTitle.append( rtl::OUString::valueOf( ++nTry ) );
1704 0 : m_aProps.setTitle( aNewTitle.makeStringAndClear() );
1705 : }
1706 : }
1707 0 : break;
1708 :
1709 : case ucb::NameClash::KEEP: // deprecated
1710 : case ucb::NameClash::ASK:
1711 : default:
1712 0 : if ( hasData( aNewUri ) )
1713 : {
1714 : ucbhelper::cancelCommandExecution(
1715 : uno::makeAny(
1716 : ucb::UnsupportedNameClashException(
1717 : rtl::OUString(),
1718 : static_cast< cppu::OWeakObject * >( this ),
1719 : nNameClashResolve ) ),
1720 0 : xEnv );
1721 : // Unreachable
1722 : }
1723 0 : break;
1724 : }
1725 :
1726 : // Identifier changed?
1727 0 : sal_Bool bNewId = ( aUri != aNewUri );
1728 :
1729 0 : if ( bNewId )
1730 : {
1731 : m_xIdentifier
1732 0 : = new ::ucbhelper::ContentIdentifier( aNewUri.getUri() );
1733 : }
1734 :
1735 0 : if ( !storeData( xData, xEnv ) )
1736 : {
1737 : uno::Any aProps
1738 : = uno::makeAny(beans::PropertyValue(
1739 : rtl::OUString( "Uri"),
1740 : -1,
1741 0 : uno::makeAny(m_xIdentifier->
1742 0 : getContentIdentifier()),
1743 0 : beans::PropertyState_DIRECT_VALUE));
1744 : ucbhelper::cancelCommandExecution(
1745 : ucb::IOErrorCode_CANT_WRITE,
1746 : uno::Sequence< uno::Any >(&aProps, 1),
1747 : xEnv,
1748 : rtl::OUString("Cannot store persistent data!"),
1749 0 : this );
1750 : // Unreachable
1751 : }
1752 :
1753 0 : m_eState = PERSISTENT;
1754 :
1755 0 : if ( bNewId )
1756 : {
1757 : //loadData( m_pProvider, m_aUri, m_aProps );
1758 :
1759 0 : aGuard.clear();
1760 0 : inserted();
1761 0 : }
1762 0 : }
1763 :
1764 : //=========================================================================
1765 0 : void Content::destroy( sal_Bool bDeletePhysical,
1766 : const uno::Reference<
1767 : ucb::XCommandEnvironment > & xEnv )
1768 : throw( uno::Exception )
1769 : {
1770 : // @@@ take care about bDeletePhysical -> trashcan support
1771 :
1772 0 : osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1773 :
1774 0 : ContentType eType = m_aProps.getType();
1775 :
1776 : OSL_ENSURE( ( eType == FOLDER ) || ( eType == STREAM ),
1777 : "delete command only supported by streams and folders!" );
1778 :
1779 0 : uno::Reference< ucb::XContent > xThis = this;
1780 :
1781 : // Persistent?
1782 0 : if ( m_eState != PERSISTENT )
1783 : {
1784 : ucbhelper::cancelCommandExecution(
1785 : uno::makeAny( ucb::UnsupportedCommandException(
1786 : rtl::OUString( "Not persistent!" ),
1787 : static_cast< cppu::OWeakObject * >( this ) ) ),
1788 0 : xEnv );
1789 : // Unreachable
1790 : }
1791 :
1792 0 : m_eState = DEAD;
1793 :
1794 0 : aGuard.clear();
1795 0 : deleted();
1796 :
1797 0 : if ( eType == FOLDER )
1798 : {
1799 : // Process instanciated children...
1800 :
1801 0 : ContentRefList aChildren;
1802 0 : queryChildren( aChildren );
1803 :
1804 0 : ContentRefList::const_iterator it = aChildren.begin();
1805 0 : ContentRefList::const_iterator end = aChildren.end();
1806 :
1807 0 : while ( it != end )
1808 : {
1809 0 : (*it)->destroy( bDeletePhysical, xEnv );
1810 0 : ++it;
1811 0 : }
1812 0 : }
1813 0 : }
1814 :
1815 : //=========================================================================
1816 0 : void Content::notifyDocumentClosed()
1817 : {
1818 0 : osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1819 :
1820 0 : m_eState = DEAD;
1821 :
1822 : // @@@ anything else to reset or such?
1823 :
1824 : // callback follows!
1825 0 : aGuard.clear();
1826 :
1827 : // Propagate destruction to content event listeners
1828 : // Remove this from provider's content list.
1829 0 : deleted();
1830 0 : }
1831 :
1832 : //=========================================================================
1833 : uno::Reference< ucb::XContent >
1834 0 : Content::queryChildContent( const rtl::OUString & rRelativeChildUri )
1835 : {
1836 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
1837 :
1838 0 : const rtl::OUString aMyId = getIdentifier()->getContentIdentifier();
1839 0 : rtl::OUStringBuffer aBuf( aMyId );
1840 0 : if ( aMyId.getStr()[ aMyId.getLength() - 1 ] != sal_Unicode( '/' ) )
1841 0 : aBuf.appendAscii( "/" );
1842 0 : if ( rRelativeChildUri.getStr()[ 0 ] != sal_Unicode( '/' ) )
1843 0 : aBuf.append( rRelativeChildUri );
1844 : else
1845 0 : aBuf.append( rRelativeChildUri.copy( 1 ) );
1846 :
1847 : uno::Reference< ucb::XContentIdentifier > xChildId
1848 0 : = new ::ucbhelper::ContentIdentifier( aBuf.makeStringAndClear() );
1849 :
1850 0 : uno::Reference< ucb::XContent > xChild;
1851 : try
1852 : {
1853 0 : xChild = m_pProvider->queryContent( xChildId );
1854 : }
1855 0 : catch ( ucb::IllegalIdentifierException const & )
1856 : {
1857 : // handled below.
1858 : }
1859 :
1860 : OSL_ENSURE( xChild.is(),
1861 : "Content::queryChildContent - unable to create child content!" );
1862 0 : return xChild;
1863 : }
1864 :
1865 : //=========================================================================
1866 0 : void Content::notifyChildRemoved( const rtl::OUString & rRelativeChildUri )
1867 : {
1868 0 : osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1869 :
1870 : // Ugly! Need to create child content object, just to fill event properly.
1871 : uno::Reference< ucb::XContent > xChild
1872 0 : = queryChildContent( rRelativeChildUri );
1873 :
1874 0 : if ( xChild.is() )
1875 : {
1876 : // callback follows!
1877 0 : aGuard.clear();
1878 :
1879 : // Notify "REMOVED" event.
1880 : ucb::ContentEvent aEvt(
1881 : static_cast< cppu::OWeakObject * >( this ),
1882 : ucb::ContentAction::REMOVED,
1883 : xChild,
1884 0 : getIdentifier() );
1885 0 : notifyContentEvent( aEvt );
1886 0 : }
1887 0 : }
1888 :
1889 : //=========================================================================
1890 0 : void Content::notifyChildInserted( const rtl::OUString & rRelativeChildUri )
1891 : {
1892 0 : osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1893 :
1894 : // Ugly! Need to create child content object, just to fill event properly.
1895 : uno::Reference< ucb::XContent > xChild
1896 0 : = queryChildContent( rRelativeChildUri );
1897 :
1898 0 : if ( xChild.is() )
1899 : {
1900 : // callback follows!
1901 0 : aGuard.clear();
1902 :
1903 : // Notify "INSERTED" event.
1904 : ucb::ContentEvent aEvt(
1905 : static_cast< cppu::OWeakObject * >( this ),
1906 : ucb::ContentAction::INSERTED,
1907 : xChild,
1908 0 : getIdentifier() );
1909 0 : notifyContentEvent( aEvt );
1910 0 : }
1911 0 : }
1912 :
1913 : //=========================================================================
1914 0 : void Content::transfer(
1915 : const ucb::TransferInfo& rInfo,
1916 : const uno::Reference< ucb::XCommandEnvironment > & xEnv )
1917 : throw( uno::Exception )
1918 : {
1919 0 : osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1920 :
1921 : // Persistent?
1922 0 : if ( m_eState != PERSISTENT )
1923 : {
1924 : ucbhelper::cancelCommandExecution(
1925 : uno::makeAny( ucb::UnsupportedCommandException(
1926 : rtl::OUString( "Not persistent!" ),
1927 : static_cast< cppu::OWeakObject * >( this ) ) ),
1928 0 : xEnv );
1929 : // Unreachable
1930 : }
1931 :
1932 : // Does source URI scheme match? Only vnd.sun.star.tdoc is supported.
1933 :
1934 0 : if ( ( rInfo.SourceURL.getLength() < TDOC_URL_SCHEME_LENGTH + 2 ) )
1935 : {
1936 : // Invaild length (to short).
1937 : ucbhelper::cancelCommandExecution(
1938 : uno::makeAny( ucb::InteractiveBadTransferURLException(
1939 : rtl::OUString(),
1940 : static_cast< cppu::OWeakObject * >( this ) ) ),
1941 0 : xEnv );
1942 : // Unreachable
1943 : }
1944 :
1945 : rtl::OUString aScheme
1946 : = rInfo.SourceURL.copy( 0, TDOC_URL_SCHEME_LENGTH + 2 )
1947 0 : .toAsciiLowerCase();
1948 0 : if ( aScheme != TDOC_URL_SCHEME ":/" )
1949 : {
1950 : // Invalid scheme.
1951 : ucbhelper::cancelCommandExecution(
1952 : uno::makeAny( ucb::InteractiveBadTransferURLException(
1953 : rtl::OUString(),
1954 : static_cast< cppu::OWeakObject * >( this ) ) ),
1955 0 : xEnv );
1956 : // Unreachable
1957 : }
1958 :
1959 : // Does source URI describe a tdoc folder or stream?
1960 0 : Uri aSourceUri( rInfo.SourceURL );
1961 0 : if ( !aSourceUri.isValid() )
1962 : {
1963 : ucbhelper::cancelCommandExecution(
1964 : uno::makeAny( lang::IllegalArgumentException(
1965 : rtl::OUString( "Invalid source URI! Syntax!" ),
1966 : static_cast< cppu::OWeakObject * >( this ),
1967 : -1 ) ),
1968 0 : xEnv );
1969 : // Unreachable
1970 : }
1971 :
1972 0 : if ( aSourceUri.isRoot() || aSourceUri.isDocument() )
1973 : {
1974 : ucbhelper::cancelCommandExecution(
1975 : uno::makeAny( lang::IllegalArgumentException(
1976 : rtl::OUString( "Invalid source URI! "
1977 : "Must describe a folder or stream!" ),
1978 : static_cast< cppu::OWeakObject * >( this ),
1979 : -1 ) ),
1980 0 : xEnv );
1981 : // Unreachable
1982 : }
1983 :
1984 : // Is source not a parent of me / not me?
1985 0 : rtl::OUString aId = m_xIdentifier->getContentIdentifier();
1986 0 : sal_Int32 nPos = aId.lastIndexOf( '/' );
1987 0 : if ( nPos != ( aId.getLength() - 1 ) )
1988 : {
1989 : // No trailing slash found. Append.
1990 0 : aId += rtl::OUString("/");
1991 : }
1992 :
1993 0 : if ( rInfo.SourceURL.getLength() <= aId.getLength() )
1994 : {
1995 0 : if ( aId.compareTo(
1996 0 : rInfo.SourceURL, rInfo.SourceURL.getLength() ) == 0 )
1997 : {
1998 : uno::Any aProps
1999 : = uno::makeAny(beans::PropertyValue(
2000 : rtl::OUString( "Uri"),
2001 : -1,
2002 : uno::makeAny( rInfo.SourceURL ),
2003 0 : beans::PropertyState_DIRECT_VALUE));
2004 : ucbhelper::cancelCommandExecution(
2005 : ucb::IOErrorCode_RECURSIVE,
2006 : uno::Sequence< uno::Any >(&aProps, 1),
2007 : xEnv,
2008 : rtl::OUString( "Target is equal to or is a child of source!" ),
2009 0 : this );
2010 : // Unreachable
2011 : }
2012 : }
2013 :
2014 : #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT
2015 0 : if ( m_aProps.getType() == DOCUMENT )
2016 : {
2017 0 : bool bOK = false;
2018 :
2019 : uno::Reference< embed::XStorage > xStorage
2020 : = m_pProvider->queryStorage(
2021 0 : aSourceUri.getParentUri(), READ_WRITE_NOCREATE );
2022 0 : if ( xStorage.is() )
2023 : {
2024 : try
2025 : {
2026 0 : if ( xStorage->isStreamElement( aSourceUri.getDecodedName() ) )
2027 : {
2028 : ucbhelper::cancelCommandExecution(
2029 : uno::makeAny( lang::IllegalArgumentException(
2030 : rtl::OUString( "Invalid source URI! "
2031 : "Streams cannot be created as "
2032 : "children of document root!" ),
2033 : static_cast< cppu::OWeakObject * >(
2034 : this ),
2035 : -1 ) ),
2036 0 : xEnv );
2037 : // Unreachable
2038 : }
2039 0 : bOK = true;
2040 : }
2041 0 : catch ( container::NoSuchElementException const & )
2042 : {
2043 : // handled below.
2044 : }
2045 0 : catch ( lang::IllegalArgumentException const & )
2046 : {
2047 : // handled below.
2048 : }
2049 0 : catch ( embed::InvalidStorageException const & )
2050 : {
2051 : // handled below.
2052 : }
2053 : }
2054 :
2055 0 : if ( !bOK )
2056 : {
2057 : ucbhelper::cancelCommandExecution(
2058 : uno::makeAny( lang::IllegalArgumentException(
2059 : rtl::OUString( "Invalid source URI! "
2060 : "Unabale to determine source type!" ),
2061 : static_cast< cppu::OWeakObject * >( this ),
2062 : -1 ) ),
2063 0 : xEnv );
2064 : // Unreachable
2065 0 : }
2066 : }
2067 : #endif
2068 :
2069 : /////////////////////////////////////////////////////////////////////////
2070 : // Copy data.
2071 : /////////////////////////////////////////////////////////////////////////
2072 :
2073 0 : rtl::OUString aNewName( !rInfo.NewTitle.isEmpty()
2074 : ? rInfo.NewTitle
2075 0 : : aSourceUri.getDecodedName() );
2076 :
2077 0 : if ( !copyData( aSourceUri, aNewName ) )
2078 : {
2079 : uno::Any aProps
2080 : = uno::makeAny(
2081 : beans::PropertyValue(
2082 : rtl::OUString( "Uri"),
2083 : -1,
2084 : uno::makeAny( rInfo.SourceURL ),
2085 0 : beans::PropertyState_DIRECT_VALUE));
2086 : ucbhelper::cancelCommandExecution(
2087 : ucb::IOErrorCode_CANT_WRITE,
2088 : uno::Sequence< uno::Any >(&aProps, 1),
2089 : xEnv,
2090 : rtl::OUString( "Cannot copy data!" ),
2091 0 : this );
2092 : // Unreachable
2093 : }
2094 :
2095 : /////////////////////////////////////////////////////////////////////////
2096 : // Copy own and all children's Additional Core Properties.
2097 : /////////////////////////////////////////////////////////////////////////
2098 :
2099 0 : rtl::OUString aTargetUri = m_xIdentifier->getContentIdentifier();
2100 0 : if ( ( aTargetUri.lastIndexOf( '/' ) + 1 ) != aTargetUri.getLength() )
2101 0 : aTargetUri += rtl::OUString("/");
2102 :
2103 0 : if ( !rInfo.NewTitle.isEmpty() )
2104 0 : aTargetUri += ::ucb_impl::urihelper::encodeSegment( rInfo.NewTitle );
2105 : else
2106 0 : aTargetUri += aSourceUri.getName();
2107 :
2108 0 : if ( !copyAdditionalPropertySet(
2109 0 : aSourceUri.getUri(), aTargetUri, sal_True ) )
2110 : {
2111 : uno::Any aProps
2112 : = uno::makeAny(
2113 : beans::PropertyValue(
2114 : rtl::OUString( "Uri"),
2115 : -1,
2116 : uno::makeAny( rInfo.SourceURL ),
2117 0 : beans::PropertyState_DIRECT_VALUE));
2118 : ucbhelper::cancelCommandExecution(
2119 : ucb::IOErrorCode_CANT_WRITE,
2120 : uno::Sequence< uno::Any >(&aProps, 1),
2121 : xEnv,
2122 : rtl::OUString( "Cannot copy additional properties!" ),
2123 0 : this );
2124 : // Unreachable
2125 : }
2126 :
2127 : /////////////////////////////////////////////////////////////////////////
2128 : // Propagate new content.
2129 : /////////////////////////////////////////////////////////////////////////
2130 :
2131 0 : rtl::Reference< Content > xTarget;
2132 : try
2133 : {
2134 : uno::Reference< ucb::XContentIdentifier > xTargetId
2135 0 : = new ::ucbhelper::ContentIdentifier( aTargetUri );
2136 :
2137 : // Note: The static cast is okay here, because its sure that
2138 : // m_xProvider is always the WebDAVContentProvider.
2139 : xTarget = static_cast< Content * >(
2140 0 : m_pProvider->queryContent( xTargetId ).get() );
2141 :
2142 : }
2143 0 : catch ( ucb::IllegalIdentifierException const & )
2144 : {
2145 : // queryContent
2146 : }
2147 :
2148 0 : if ( !xTarget.is() )
2149 : {
2150 : uno::Any aProps
2151 : = uno::makeAny(beans::PropertyValue(
2152 : rtl::OUString( "Uri"),
2153 : -1,
2154 : uno::makeAny( aTargetUri ),
2155 0 : beans::PropertyState_DIRECT_VALUE));
2156 : ucbhelper::cancelCommandExecution(
2157 : ucb::IOErrorCode_CANT_READ,
2158 : uno::Sequence< uno::Any >(&aProps, 1),
2159 : xEnv,
2160 : rtl::OUString( "Cannot instanciate target object!" ),
2161 0 : this );
2162 : // Unreachable
2163 : }
2164 :
2165 : // Announce transfered content in its new folder.
2166 0 : xTarget->inserted();
2167 :
2168 : /////////////////////////////////////////////////////////////////////////
2169 : // Remove source, if requested
2170 : /////////////////////////////////////////////////////////////////////////
2171 :
2172 0 : if ( rInfo.MoveData )
2173 : {
2174 0 : rtl::Reference< Content > xSource;
2175 : try
2176 : {
2177 : uno::Reference< ucb::XContentIdentifier >
2178 0 : xSourceId = new ::ucbhelper::ContentIdentifier( rInfo.SourceURL );
2179 :
2180 : // Note: The static cast is okay here, because its sure
2181 : // that m_xProvider is always the ContentProvider.
2182 : xSource = static_cast< Content * >(
2183 0 : m_xProvider->queryContent( xSourceId ).get() );
2184 : }
2185 0 : catch ( ucb::IllegalIdentifierException const & )
2186 : {
2187 : // queryContent
2188 : }
2189 :
2190 0 : if ( !xSource.is() )
2191 : {
2192 : uno::Any aProps
2193 : = uno::makeAny(beans::PropertyValue(
2194 : rtl::OUString( "Uri"),
2195 : -1,
2196 : uno::makeAny( rInfo.SourceURL ),
2197 0 : beans::PropertyState_DIRECT_VALUE));
2198 : ucbhelper::cancelCommandExecution(
2199 : ucb::IOErrorCode_CANT_READ,
2200 : uno::Sequence< uno::Any >(&aProps, 1),
2201 : xEnv,
2202 : rtl::OUString( "Cannot instanciate target object!" ),
2203 0 : this );
2204 : // Unreachable
2205 : }
2206 :
2207 : // Propagate destruction (recursively).
2208 0 : xSource->destroy( sal_True, xEnv );
2209 :
2210 : // Remove all persistent data of source and its children.
2211 0 : if ( !xSource->removeData() )
2212 : {
2213 : uno::Any aProps
2214 : = uno::makeAny(
2215 : beans::PropertyValue(
2216 : rtl::OUString( "Uri"),
2217 : -1,
2218 : uno::makeAny( rInfo.SourceURL ),
2219 0 : beans::PropertyState_DIRECT_VALUE));
2220 : ucbhelper::cancelCommandExecution(
2221 : ucb::IOErrorCode_CANT_WRITE,
2222 : uno::Sequence< uno::Any >(&aProps, 1),
2223 : xEnv,
2224 : rtl::OUString( "Cannot remove persistent data of source object!" ),
2225 0 : this );
2226 : // Unreachable
2227 : }
2228 :
2229 : // Remove own and all children's Additional Core Properties.
2230 0 : if ( !xSource->removeAdditionalPropertySet( sal_True ) )
2231 : {
2232 : uno::Any aProps
2233 : = uno::makeAny(
2234 : beans::PropertyValue(
2235 : rtl::OUString( "Uri"),
2236 : -1,
2237 : uno::makeAny( rInfo.SourceURL ),
2238 0 : beans::PropertyState_DIRECT_VALUE));
2239 : ucbhelper::cancelCommandExecution(
2240 : ucb::IOErrorCode_CANT_WRITE,
2241 : uno::Sequence< uno::Any >(&aProps, 1),
2242 : xEnv,
2243 : rtl::OUString( "Cannot remove additional properties of source object!" ),
2244 0 : this );
2245 : // Unreachable
2246 0 : }
2247 :
2248 0 : } // rInfo.MoveData
2249 0 : }
2250 :
2251 : //=========================================================================
2252 : //static
2253 0 : bool Content::hasData( ContentProvider* pProvider, const Uri & rUri )
2254 : {
2255 0 : if ( rUri.isRoot() )
2256 : {
2257 0 : return true; // root has no storage
2258 : }
2259 0 : else if ( rUri.isDocument() )
2260 : {
2261 : uno::Reference< embed::XStorage > xStorage
2262 0 : = pProvider->queryStorage( rUri.getUri(), READ );
2263 0 : return xStorage.is();
2264 : }
2265 : else
2266 : {
2267 : // folder or stream
2268 :
2269 : // Ask parent storage. In case that rUri describes a stream,
2270 : // ContentProvider::queryStorage( rUri ) would return null.
2271 :
2272 : uno::Reference< embed::XStorage > xStorage
2273 0 : = pProvider->queryStorage( rUri.getParentUri(), READ );
2274 :
2275 0 : if ( !xStorage.is() )
2276 0 : return false;
2277 :
2278 : uno::Reference< container::XNameAccess > xParentNA(
2279 0 : xStorage, uno::UNO_QUERY );
2280 :
2281 : OSL_ENSURE( xParentNA.is(), "Got no css.container.XNameAccess!" );
2282 :
2283 0 : return xParentNA->hasByName( rUri.getDecodedName() );
2284 : }
2285 : }
2286 :
2287 : //=========================================================================
2288 : //static
2289 5 : bool Content::loadData( ContentProvider* pProvider,
2290 : const Uri & rUri,
2291 : ContentProperties& rProps )
2292 : {
2293 5 : if ( rUri.isRoot() ) // root has no storage, but can always be created
2294 : {
2295 : rProps
2296 : = ContentProperties(
2297 0 : ROOT, pProvider->queryStorageTitle( rUri.getUri() ) );
2298 : }
2299 5 : else if ( rUri.isDocument() ) // document must have storage
2300 : {
2301 : uno::Reference< embed::XStorage > xStorage
2302 5 : = pProvider->queryStorage( rUri.getUri(), READ );
2303 :
2304 5 : if ( !xStorage.is() )
2305 0 : return false;
2306 :
2307 : rProps
2308 : = ContentProperties(
2309 5 : DOCUMENT, pProvider->queryStorageTitle( rUri.getUri() ) );
2310 : }
2311 : else // stream or folder; stream has no storage; folder has storage
2312 : {
2313 : uno::Reference< embed::XStorage > xStorage
2314 0 : = pProvider->queryStorage( rUri.getParentUri(), READ );
2315 :
2316 0 : if ( !xStorage.is() )
2317 0 : return false;
2318 :
2319 : // Check whether exists at all, is stream or folder
2320 : try
2321 : {
2322 : // return: true -> folder
2323 : // return: false -> stream
2324 : // NoSuchElementException -> neither folder nor stream
2325 : bool bIsFolder
2326 0 : = xStorage->isStorageElement( rUri.getDecodedName() );
2327 :
2328 : rProps
2329 : = ContentProperties(
2330 : bIsFolder ? FOLDER : STREAM,
2331 0 : pProvider->queryStorageTitle( rUri.getUri() ) );
2332 : }
2333 0 : catch ( container::NoSuchElementException const & )
2334 : {
2335 : // there is no element with such name
2336 : //OSL_ENSURE( false, "Caught NoSuchElementException!" );
2337 0 : return false;
2338 : }
2339 0 : catch ( lang::IllegalArgumentException const & )
2340 : {
2341 : // an illegal argument is provided
2342 : OSL_FAIL( "Caught IllegalArgumentException!" );
2343 0 : return false;
2344 : }
2345 0 : catch ( embed::InvalidStorageException const & )
2346 : {
2347 : // this storage is in invalid state for any reason
2348 : OSL_FAIL( "Caught InvalidStorageException!" );
2349 0 : return false;
2350 0 : }
2351 : }
2352 5 : return true;
2353 : }
2354 :
2355 : //=========================================================================
2356 0 : bool Content::storeData( const uno::Reference< io::XInputStream >& xData,
2357 : const uno::Reference<
2358 : ucb::XCommandEnvironment >& xEnv )
2359 : throw ( ucb::CommandFailedException,
2360 : task::DocumentPasswordRequest )
2361 : {
2362 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
2363 :
2364 0 : ContentType eType = m_aProps.getType();
2365 0 : if ( ( eType == ROOT ) || ( eType == DOCUMENT ) )
2366 : {
2367 : OSL_FAIL( "storeData not supported by root and documents!" );
2368 0 : return false;
2369 : }
2370 :
2371 0 : Uri aUri( m_xIdentifier->getContentIdentifier() );
2372 :
2373 0 : if ( eType == FOLDER )
2374 : {
2375 : uno::Reference< embed::XStorage > xStorage
2376 0 : = m_pProvider->queryStorage( aUri.getUri(), READ_WRITE_CREATE );
2377 :
2378 0 : if ( !xStorage.is() )
2379 0 : return false;
2380 :
2381 : uno::Reference< beans::XPropertySet > xPropSet(
2382 0 : xStorage, uno::UNO_QUERY );
2383 : OSL_ENSURE( xPropSet.is(),
2384 : "Content::storeData - Got no XPropertySet interface!" );
2385 0 : if ( !xPropSet.is() )
2386 0 : return false;
2387 :
2388 : try
2389 : {
2390 : // According to MBA, if no mediatype is set, folder and all
2391 : // its contents will be lost on save of the document!!!
2392 0 : xPropSet->setPropertyValue(
2393 : rtl::OUString( "MediaType" ),
2394 : uno::makeAny(
2395 : rtl::OUString( // @@@ better mediatype
2396 0 : "application/binary" ) ) );
2397 : }
2398 0 : catch ( beans::UnknownPropertyException const & )
2399 : {
2400 : OSL_FAIL( "Property MediaType not supported!" );
2401 0 : return false;
2402 : }
2403 0 : catch ( beans::PropertyVetoException const & )
2404 : {
2405 : OSL_FAIL( "Caught PropertyVetoException!" );
2406 0 : return false;
2407 : }
2408 0 : catch ( lang::IllegalArgumentException const & )
2409 : {
2410 : OSL_FAIL( "Caught IllegalArgumentException!" );
2411 0 : return false;
2412 : }
2413 0 : catch ( lang::WrappedTargetException const & )
2414 : {
2415 : OSL_FAIL( "Caught WrappedTargetException!" );
2416 0 : return false;
2417 : }
2418 :
2419 0 : if ( !commitStorage( xStorage ) )
2420 0 : return false;
2421 : }
2422 0 : else if ( eType == STREAM )
2423 : {
2424 : // stream
2425 :
2426 : // Important: Parent storage and output stream must be kept alive until
2427 : // changes have been committed!
2428 : uno::Reference< embed::XStorage > xStorage
2429 : = m_pProvider->queryStorage(
2430 0 : aUri.getParentUri(), READ_WRITE_CREATE );
2431 0 : uno::Reference< io::XOutputStream > xOut;
2432 :
2433 0 : if ( !xStorage.is() )
2434 0 : return false;
2435 :
2436 0 : if ( xData.is() )
2437 : {
2438 : // May throw CommandFailedException, DocumentPasswordRequest!
2439 0 : xOut = getTruncatedOutputStream( xEnv );
2440 :
2441 : OSL_ENSURE( xOut.is(), "No target data stream!" );
2442 :
2443 : try
2444 : {
2445 0 : uno::Sequence< sal_Int8 > aBuffer;
2446 0 : sal_Int32 nRead = xData->readSomeBytes( aBuffer, 65536 );
2447 :
2448 0 : while ( nRead > 0 )
2449 : {
2450 0 : aBuffer.realloc( nRead );
2451 0 : xOut->writeBytes( aBuffer );
2452 0 : aBuffer.realloc( 0 );
2453 0 : nRead = xData->readSomeBytes( aBuffer, 65536 );
2454 : }
2455 :
2456 0 : closeOutputStream( xOut );
2457 : }
2458 0 : catch ( io::NotConnectedException const & )
2459 : {
2460 : // readSomeBytes, writeBytes
2461 : OSL_FAIL( "Caught NotConnectedException!" );
2462 0 : closeOutputStream( xOut );
2463 0 : return false;
2464 : }
2465 0 : catch ( io::BufferSizeExceededException const & )
2466 : {
2467 : // readSomeBytes, writeBytes
2468 : OSL_FAIL( "Caught BufferSizeExceededException!" );
2469 0 : closeOutputStream( xOut );
2470 0 : return false;
2471 : }
2472 0 : catch ( io::IOException const & )
2473 : {
2474 : // readSomeBytes, writeBytes
2475 : OSL_FAIL( "Caught IOException!" );
2476 0 : closeOutputStream( xOut );
2477 0 : return false;
2478 : }
2479 0 : catch ( ... )
2480 : {
2481 0 : closeOutputStream( xOut );
2482 0 : throw;
2483 : }
2484 : }
2485 :
2486 : // Commit changes.
2487 0 : if ( !commitStorage( xStorage ) )
2488 0 : return false;
2489 : }
2490 : else
2491 : {
2492 : OSL_FAIL( "Unknown content type!" );
2493 0 : return false;
2494 : }
2495 0 : return true;
2496 : }
2497 :
2498 : //=========================================================================
2499 0 : bool Content::renameData(
2500 : const uno::Reference< ucb::XContentIdentifier >& xOldId,
2501 : const uno::Reference< ucb::XContentIdentifier >& xNewId )
2502 : {
2503 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
2504 :
2505 0 : ContentType eType = m_aProps.getType();
2506 0 : if ( ( eType == ROOT ) || ( eType == DOCUMENT ) )
2507 : {
2508 : OSL_FAIL( "renameData not supported by root and documents!" );
2509 0 : return false;
2510 : }
2511 :
2512 0 : Uri aOldUri( xOldId->getContentIdentifier() );
2513 : uno::Reference< embed::XStorage > xStorage
2514 : = m_pProvider->queryStorage(
2515 0 : aOldUri.getParentUri(), READ_WRITE_NOCREATE );
2516 :
2517 0 : if ( !xStorage.is() )
2518 0 : return false;
2519 :
2520 : try
2521 : {
2522 0 : Uri aNewUri( xNewId->getContentIdentifier() );
2523 0 : xStorage->renameElement(
2524 0 : aOldUri.getDecodedName(), aNewUri.getDecodedName() );
2525 : }
2526 0 : catch ( embed::InvalidStorageException const & )
2527 : {
2528 : // this storage is in invalid state for eny reason
2529 : OSL_FAIL( "Caught InvalidStorageException!" );
2530 0 : return false;
2531 : }
2532 0 : catch ( lang::IllegalArgumentException const & )
2533 : {
2534 : // an illegal argument is provided
2535 : OSL_FAIL( "Caught IllegalArgumentException!" );
2536 0 : return false;
2537 : }
2538 0 : catch ( container::NoSuchElementException const & )
2539 : {
2540 : // there is no element with old name in this storage
2541 : OSL_FAIL( "Caught NoSuchElementException!" );
2542 0 : return false;
2543 : }
2544 0 : catch ( container::ElementExistException const & )
2545 : {
2546 : // an element with new name already exists in this storage
2547 : OSL_FAIL( "Caught ElementExistException!" );
2548 0 : return false;
2549 : }
2550 0 : catch ( io::IOException const & )
2551 : {
2552 : // in case of io errors during renaming
2553 : OSL_FAIL( "Caught IOException!" );
2554 0 : return false;
2555 : }
2556 0 : catch ( embed::StorageWrappedTargetException const & )
2557 : {
2558 : // wraps other exceptions
2559 : OSL_FAIL( "Caught StorageWrappedTargetException!" );
2560 0 : return false;
2561 : }
2562 :
2563 0 : return commitStorage( xStorage );
2564 : }
2565 :
2566 : //=========================================================================
2567 0 : bool Content::removeData()
2568 : {
2569 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
2570 :
2571 0 : ContentType eType = m_aProps.getType();
2572 0 : if ( ( eType == ROOT ) || ( eType == DOCUMENT ) )
2573 : {
2574 : OSL_FAIL( "removeData not supported by root and documents!" );
2575 0 : return false;
2576 : }
2577 :
2578 0 : Uri aUri( m_xIdentifier->getContentIdentifier() );
2579 : uno::Reference< embed::XStorage > xStorage
2580 : = m_pProvider->queryStorage(
2581 0 : aUri.getParentUri(), READ_WRITE_NOCREATE );
2582 :
2583 0 : if ( !xStorage.is() )
2584 0 : return false;
2585 :
2586 : try
2587 : {
2588 0 : xStorage->removeElement( aUri.getDecodedName() );
2589 : }
2590 0 : catch ( embed::InvalidStorageException const & )
2591 : {
2592 : // this storage is in invalid state for eny reason
2593 : OSL_FAIL( "Caught InvalidStorageException!" );
2594 0 : return false;
2595 : }
2596 0 : catch ( lang::IllegalArgumentException const & )
2597 : {
2598 : // an illegal argument is provided
2599 : OSL_FAIL( "Caught IllegalArgumentException!" );
2600 0 : return false;
2601 : }
2602 0 : catch ( container::NoSuchElementException const & )
2603 : {
2604 : // there is no element with this name in this storage
2605 : OSL_FAIL( "Caught NoSuchElementException!" );
2606 0 : return false;
2607 : }
2608 0 : catch ( io::IOException const & )
2609 : {
2610 : // in case of io errors during renaming
2611 : OSL_FAIL( "Caught IOException!" );
2612 0 : return false;
2613 : }
2614 0 : catch ( embed::StorageWrappedTargetException const & )
2615 : {
2616 : // wraps other exceptions
2617 : OSL_FAIL( "Caught StorageWrappedTargetException!" );
2618 0 : return false;
2619 : }
2620 :
2621 0 : return commitStorage( xStorage );
2622 : }
2623 :
2624 : //=========================================================================
2625 0 : bool Content::copyData( const Uri & rSourceUri, const rtl::OUString & rNewName )
2626 : {
2627 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
2628 :
2629 0 : ContentType eType = m_aProps.getType();
2630 0 : if ( ( eType == ROOT ) || ( eType == STREAM ) )
2631 : {
2632 : OSL_FAIL( "copyData not supported by root and streams!" );
2633 0 : return false;
2634 : }
2635 :
2636 0 : Uri aDestUri( m_xIdentifier->getContentIdentifier() );
2637 : uno::Reference< embed::XStorage > xDestStorage
2638 0 : = m_pProvider->queryStorage( aDestUri.getUri(), READ_WRITE_NOCREATE );
2639 :
2640 0 : if ( !xDestStorage.is() )
2641 0 : return false;
2642 :
2643 : uno::Reference< embed::XStorage > xSourceStorage
2644 0 : = m_pProvider->queryStorage( rSourceUri.getParentUri(), READ );
2645 :
2646 0 : if ( !xSourceStorage.is() )
2647 0 : return false;
2648 :
2649 : try
2650 : {
2651 0 : xSourceStorage->copyElementTo( rSourceUri.getDecodedName(),
2652 : xDestStorage,
2653 0 : rNewName );
2654 : }
2655 0 : catch ( embed::InvalidStorageException const & )
2656 : {
2657 : // this storage is in invalid state for eny reason
2658 : OSL_FAIL( "Caught InvalidStorageException!" );
2659 0 : return false;
2660 : }
2661 0 : catch ( lang::IllegalArgumentException const & )
2662 : {
2663 : // an illegal argument is provided
2664 : OSL_FAIL( "Caught IllegalArgumentException!" );
2665 0 : return false;
2666 : }
2667 0 : catch ( container::NoSuchElementException const & )
2668 : {
2669 : // there is no element with this name in this storage
2670 : OSL_FAIL( "Caught NoSuchElementException!" );
2671 0 : return false;
2672 : }
2673 0 : catch ( container::ElementExistException const & )
2674 : {
2675 : // there is no element with this name in this storage
2676 : OSL_FAIL( "Caught ElementExistException!" );
2677 0 : return false;
2678 : }
2679 0 : catch ( io::IOException const & )
2680 : {
2681 : // in case of io errors during renaming
2682 : OSL_FAIL( "Caught IOException!" );
2683 0 : return false;
2684 : }
2685 0 : catch ( embed::StorageWrappedTargetException const & )
2686 : {
2687 : // wraps other exceptions
2688 : OSL_FAIL( "Caught StorageWrappedTargetException!" );
2689 0 : return false;
2690 : }
2691 :
2692 0 : return commitStorage( xDestStorage );
2693 : }
2694 :
2695 : //=========================================================================
2696 : // static
2697 0 : bool Content::commitStorage( const uno::Reference< embed::XStorage > & xStorage )
2698 : {
2699 : // Commit changes
2700 0 : uno::Reference< embed::XTransactedObject > xTO( xStorage, uno::UNO_QUERY );
2701 :
2702 : OSL_ENSURE( xTO.is(),
2703 : "Required interface css.embed.XTransactedObject missing!" );
2704 : try
2705 : {
2706 0 : xTO->commit();
2707 : }
2708 0 : catch ( io::IOException const & )
2709 : {
2710 : OSL_FAIL( "Caught IOException!" );
2711 0 : return false;
2712 : }
2713 0 : catch ( lang::WrappedTargetException const & )
2714 : {
2715 : OSL_FAIL( "Caught WrappedTargetException!" );
2716 0 : return false;
2717 : }
2718 :
2719 0 : return true;
2720 : }
2721 :
2722 : //=========================================================================
2723 : // static
2724 0 : bool Content::closeOutputStream(
2725 : const uno::Reference< io::XOutputStream > & xOut )
2726 : {
2727 0 : if ( xOut.is() )
2728 : {
2729 : try
2730 : {
2731 0 : xOut->closeOutput();
2732 0 : return true;
2733 : }
2734 0 : catch ( io::NotConnectedException const & )
2735 : {
2736 : OSL_FAIL( "Caught NotConnectedException!" );
2737 : }
2738 0 : catch ( io::BufferSizeExceededException const & )
2739 : {
2740 : OSL_FAIL( "Caught BufferSizeExceededException!" );
2741 : }
2742 0 : catch ( io::IOException const & )
2743 : {
2744 : OSL_FAIL( "Caught IOException!" );
2745 : }
2746 : }
2747 0 : return false;
2748 : }
2749 :
2750 : //=========================================================================
2751 0 : static rtl::OUString obtainPassword(
2752 : const rtl::OUString & rName,
2753 : task::PasswordRequestMode eMode,
2754 : const uno::Reference< ucb::XCommandEnvironment > & xEnv )
2755 : throw ( ucb::CommandFailedException,
2756 : task::DocumentPasswordRequest )
2757 : {
2758 : rtl::Reference< DocumentPasswordRequest > xRequest
2759 0 : = new DocumentPasswordRequest( eMode, rName );
2760 :
2761 0 : if ( xEnv.is() )
2762 : {
2763 : uno::Reference< task::XInteractionHandler > xIH
2764 0 : = xEnv->getInteractionHandler();
2765 0 : if ( xIH.is() )
2766 : {
2767 0 : xIH->handle( xRequest.get() );
2768 :
2769 : rtl::Reference< ucbhelper::InteractionContinuation > xSelection
2770 0 : = xRequest->getSelection();
2771 :
2772 0 : if ( xSelection.is() )
2773 : {
2774 : // Handler handled the request.
2775 : uno::Reference< task::XInteractionAbort > xAbort(
2776 0 : xSelection.get(), uno::UNO_QUERY );
2777 0 : if ( xAbort.is() )
2778 : {
2779 : throw ucb::CommandFailedException(
2780 : rtl::OUString( "Abort requested by Interaction Handler." ),
2781 : uno::Reference< uno::XInterface >(),
2782 0 : xRequest->getRequest() );
2783 : }
2784 :
2785 : uno::Reference< task::XInteractionPassword > xPassword(
2786 0 : xSelection.get(), uno::UNO_QUERY );
2787 0 : if ( xPassword.is() )
2788 : {
2789 0 : return xPassword->getPassword();
2790 : }
2791 :
2792 : // Unknown selection. Should never happen.
2793 : throw ucb::CommandFailedException(
2794 : rtl::OUString( "Interaction Handler selected unknown continuation!" ),
2795 : uno::Reference< uno::XInterface >(),
2796 0 : xRequest->getRequest() );
2797 0 : }
2798 0 : }
2799 : }
2800 :
2801 : // No IH or IH did not handle exception.
2802 0 : task::DocumentPasswordRequest aRequest;
2803 0 : xRequest->getRequest() >>= aRequest;
2804 0 : throw aRequest;
2805 : }
2806 :
2807 : //=========================================================================
2808 0 : uno::Reference< io::XInputStream > Content::getInputStream(
2809 : const uno::Reference< ucb::XCommandEnvironment > & xEnv )
2810 : throw ( ucb::CommandFailedException,
2811 : task::DocumentPasswordRequest )
2812 : {
2813 0 : rtl::OUString aUri;
2814 0 : rtl::OUString aPassword;
2815 0 : bool bPasswordRequested = false;
2816 :
2817 : {
2818 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
2819 :
2820 : OSL_ENSURE( m_aProps.getType() == STREAM,
2821 : "Content::getInputStream - content is no stream!" );
2822 :
2823 0 : aUri = Uri( m_xIdentifier->getContentIdentifier() ).getUri();
2824 : }
2825 :
2826 0 : for ( ;; )
2827 : {
2828 : try
2829 : {
2830 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
2831 : return uno::Reference< io::XInputStream >(
2832 0 : m_pProvider->queryInputStream( aUri, aPassword ) );
2833 : }
2834 0 : catch ( packages::WrongPasswordException const & )
2835 : {
2836 : // Obtain (new) password.
2837 : aPassword
2838 : = obtainPassword( aUri, /* @@@ find better title */
2839 : bPasswordRequested
2840 : ? task::PasswordRequestMode_PASSWORD_REENTER
2841 : : task::PasswordRequestMode_PASSWORD_ENTER,
2842 0 : xEnv );
2843 0 : bPasswordRequested = true;
2844 : }
2845 0 : }
2846 : }
2847 :
2848 : //=========================================================================
2849 0 : static uno::Reference< io::XOutputStream > lcl_getTruncatedOutputStream(
2850 : const rtl::OUString & rUri,
2851 : ContentProvider * pProvider,
2852 : const uno::Reference< ucb::XCommandEnvironment > & xEnv )
2853 : throw ( ucb::CommandFailedException,
2854 : task::DocumentPasswordRequest )
2855 : {
2856 0 : rtl::OUString aPassword;
2857 0 : bool bPasswordRequested = false;
2858 0 : for ( ;; )
2859 : {
2860 : try
2861 : {
2862 : return uno::Reference< io::XOutputStream >(
2863 : pProvider->queryOutputStream(
2864 0 : rUri, aPassword, true /* truncate */ ) );
2865 : }
2866 0 : catch ( packages::WrongPasswordException const & )
2867 : {
2868 : // Obtain (new) password.
2869 : aPassword
2870 : = obtainPassword( rUri, /* @@@ find better title */
2871 : bPasswordRequested
2872 : ? task::PasswordRequestMode_PASSWORD_REENTER
2873 : : task::PasswordRequestMode_PASSWORD_ENTER,
2874 0 : xEnv );
2875 0 : bPasswordRequested = true;
2876 : }
2877 0 : }
2878 : }
2879 :
2880 : //=========================================================================
2881 0 : uno::Reference< io::XOutputStream > Content::getTruncatedOutputStream(
2882 : const uno::Reference< ucb::XCommandEnvironment > & xEnv )
2883 : throw ( ucb::CommandFailedException,
2884 : task::DocumentPasswordRequest )
2885 : {
2886 : OSL_ENSURE( m_aProps.getType() == STREAM,
2887 : "Content::getTruncatedOutputStream - content is no stream!" );
2888 :
2889 : return lcl_getTruncatedOutputStream(
2890 0 : Uri( m_xIdentifier->getContentIdentifier() ).getUri(),
2891 : m_pProvider,
2892 0 : xEnv );
2893 : }
2894 :
2895 : //=========================================================================
2896 0 : uno::Reference< io::XStream > Content::getStream(
2897 : const uno::Reference< ucb::XCommandEnvironment > & xEnv )
2898 : throw ( ucb::CommandFailedException,
2899 : task::DocumentPasswordRequest )
2900 : {
2901 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
2902 :
2903 : OSL_ENSURE( m_aProps.getType() == STREAM,
2904 : "Content::getStream - content is no stream!" );
2905 :
2906 0 : rtl::OUString aUri( Uri( m_xIdentifier->getContentIdentifier() ).getUri() );
2907 0 : rtl::OUString aPassword;
2908 0 : bool bPasswordRequested = false;
2909 0 : for ( ;; )
2910 : {
2911 : try
2912 : {
2913 : return uno::Reference< io::XStream >(
2914 : m_pProvider->queryStream(
2915 0 : aUri, aPassword, false /* no truncate */ ) );
2916 : }
2917 0 : catch ( packages::WrongPasswordException const & )
2918 : {
2919 : // Obtain (new) password.
2920 : aPassword
2921 : = obtainPassword( aUri, /* @@@ find better title */
2922 : bPasswordRequested
2923 : ? task::PasswordRequestMode_PASSWORD_REENTER
2924 : : task::PasswordRequestMode_PASSWORD_ENTER,
2925 0 : xEnv );
2926 0 : bPasswordRequested = true;
2927 : }
2928 0 : }
2929 : }
2930 :
2931 : //=========================================================================
2932 : //=========================================================================
2933 : //
2934 : // ContentProperties Implementation.
2935 : //
2936 : //=========================================================================
2937 : //=========================================================================
2938 :
2939 : uno::Sequence< ucb::ContentInfo >
2940 0 : ContentProperties::getCreatableContentsInfo() const
2941 : {
2942 0 : if ( isContentCreator() )
2943 : {
2944 0 : uno::Sequence< beans::Property > aProps( 1 );
2945 : aProps.getArray()[ 0 ] = beans::Property(
2946 : rtl::OUString("Title"),
2947 : -1,
2948 0 : getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
2949 0 : beans::PropertyAttribute::BOUND );
2950 :
2951 : #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT
2952 0 : if ( getType() == DOCUMENT )
2953 : {
2954 : // streams cannot be created as direct children of document root
2955 0 : uno::Sequence< ucb::ContentInfo > aSeq( 1 );
2956 :
2957 : // Folder.
2958 0 : aSeq.getArray()[ 0 ].Type
2959 0 : = rtl::OUString( TDOC_FOLDER_CONTENT_TYPE );
2960 0 : aSeq.getArray()[ 0 ].Attributes
2961 0 : = ucb::ContentInfoAttribute::KIND_FOLDER;
2962 0 : aSeq.getArray()[ 0 ].Properties = aProps;
2963 :
2964 0 : return aSeq;
2965 : }
2966 : else
2967 : {
2968 : #endif
2969 0 : uno::Sequence< ucb::ContentInfo > aSeq( 2 );
2970 :
2971 : // Folder.
2972 0 : aSeq.getArray()[ 0 ].Type
2973 0 : = rtl::OUString( TDOC_FOLDER_CONTENT_TYPE );
2974 0 : aSeq.getArray()[ 0 ].Attributes
2975 0 : = ucb::ContentInfoAttribute::KIND_FOLDER;
2976 0 : aSeq.getArray()[ 0 ].Properties = aProps;
2977 :
2978 : // Stream.
2979 0 : aSeq.getArray()[ 1 ].Type
2980 0 : = rtl::OUString( TDOC_STREAM_CONTENT_TYPE );
2981 0 : aSeq.getArray()[ 1 ].Attributes
2982 : = ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM
2983 0 : | ucb::ContentInfoAttribute::KIND_DOCUMENT;
2984 0 : aSeq.getArray()[ 1 ].Properties = aProps;
2985 :
2986 0 : return aSeq;
2987 : #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT
2988 0 : }
2989 : #endif
2990 : }
2991 : else
2992 : {
2993 : OSL_FAIL( "getCreatableContentsInfo called on non-contentcreator "
2994 : "object!" );
2995 :
2996 0 : return uno::Sequence< ucb::ContentInfo >( 0 );
2997 : }
2998 : }
2999 :
3000 : //=========================================================================
3001 0 : bool ContentProperties::isContentCreator() const
3002 : {
3003 0 : return ( getType() == FOLDER ) || ( getType() == DOCUMENT );
3004 : }
3005 :
3006 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|