1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 /**************************************************************************
32 **************************************************************************
34 *************************************************************************/
36 #include "rtl/ustrbuf.hxx"
38 #include "com/sun/star/container/XNameAccess.hpp"
39 #include "com/sun/star/embed/XStorage.hpp"
41 #include "ucbhelper/contentidentifier.hxx"
43 #include "tdoc_provider.hxx"
44 #include "tdoc_content.hxx"
45 #include "tdoc_uri.hxx"
46 #include "tdoc_docmgr.hxx"
47 #include "tdoc_storage.hxx"
49 using namespace com::sun::star
;
50 using namespace tdoc_ucp
;
52 //=========================================================================
53 //=========================================================================
55 // ContentProvider Implementation.
57 //=========================================================================
58 //=========================================================================
60 ContentProvider::ContentProvider(
61 const uno::Reference
< lang::XMultiServiceFactory
>& xSMgr
)
62 : ::ucbhelper::ContentProviderImplHelper( xSMgr
),
63 m_xDocsMgr( new OfficeDocumentsManager( xSMgr
, this ) ),
64 m_xStgElemFac( new StorageElementFactory( xSMgr
, m_xDocsMgr
) )
68 //=========================================================================
70 ContentProvider::~ContentProvider()
72 if ( m_xDocsMgr
.is() )
73 m_xDocsMgr
->destroy();
76 //=========================================================================
78 // XInterface methods.
80 //=========================================================================
82 XINTERFACE_IMPL_4( ContentProvider
,
85 ucb::XContentProvider
,
86 frame::XTransientDocumentsDocumentContentFactory
);
88 //=========================================================================
90 // XTypeProvider methods.
92 //=========================================================================
94 XTYPEPROVIDER_IMPL_4( ContentProvider
,
97 ucb::XContentProvider
,
98 frame::XTransientDocumentsDocumentContentFactory
);
100 //=========================================================================
102 // XServiceInfo methods.
104 //=========================================================================
108 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
109 "com.sun.star.comp.ucb.TransientDocumentsContentProvider" ) ),
110 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
111 TDOC_CONTENT_PROVIDER_SERVICE_NAME
) ) );
113 //=========================================================================
115 // Service factory implementation.
117 //=========================================================================
119 ONE_INSTANCE_SERVICE_FACTORY_IMPL( ContentProvider
);
121 //=========================================================================
123 // XContentProvider methods.
125 //=========================================================================
128 uno::Reference
< ucb::XContent
> SAL_CALL
129 ContentProvider::queryContent(
130 const uno::Reference
< ucb::XContentIdentifier
>& Identifier
)
131 throw( ucb::IllegalIdentifierException
, uno::RuntimeException
)
133 Uri
aUri( Identifier
->getContentIdentifier() );
134 if ( !aUri
.isValid() )
135 throw ucb::IllegalIdentifierException(
136 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid URL!" ) ),
140 uno::Reference
< ucb::XContentIdentifier
> xCanonicId
141 = new ::ucbhelper::ContentIdentifier( m_xSMgr
, aUri
.getUri() );
143 osl::MutexGuard
aGuard( m_aMutex
);
145 // Check, if a content with given id already exists...
146 uno::Reference
< ucb::XContent
> xContent
147 = queryExistingContent( xCanonicId
).get();
149 if ( !xContent
.is() )
151 // Create a new content.
152 xContent
= Content::create( m_xSMgr
, this, xCanonicId
);
153 registerNewContent( xContent
);
159 //=========================================================================
161 // XTransientDocumentsDocumentContentFactory methods.
163 //=========================================================================
166 uno::Reference
< ucb::XContent
> SAL_CALL
167 ContentProvider::createDocumentContent(
168 const uno::Reference
< frame::XModel
>& Model
)
169 throw ( lang::IllegalArgumentException
, uno::RuntimeException
)
171 // model -> id -> content identifier -> queryContent
172 if ( m_xDocsMgr
.is() )
174 rtl::OUString aDocId
= m_xDocsMgr
->queryDocumentId( Model
);
175 if ( !aDocId
.isEmpty() )
177 rtl::OUStringBuffer aBuffer
;
178 aBuffer
.appendAscii( TDOC_URL_SCHEME
":/" );
179 aBuffer
.append( aDocId
);
181 uno::Reference
< ucb::XContentIdentifier
> xId
182 = new ::ucbhelper::ContentIdentifier(
183 m_xSMgr
, aBuffer
.makeStringAndClear() );
185 osl::MutexGuard
aGuard( m_aMutex
);
187 // Check, if a content with given id already exists...
188 uno::Reference
< ucb::XContent
> xContent
189 = queryExistingContent( xId
).get();
191 if ( !xContent
.is() )
193 // Create a new content.
194 xContent
= Content::create( m_xSMgr
, this, xId
);
201 throw lang::IllegalArgumentException(
202 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
203 "Illegal Content Identifier!" ) ),
204 static_cast< cppu::OWeakObject
* >( this ),
209 throw lang::IllegalArgumentException(
210 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
211 "Unable to obtain document id from model!" ) ),
212 static_cast< cppu::OWeakObject
* >( this ),
218 throw lang::IllegalArgumentException(
219 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
220 "No Document Manager!" ) ),
221 static_cast< cppu::OWeakObject
* >( this ),
226 //=========================================================================
228 // interface OfficeDocumentsEventListener
230 //=========================================================================
233 void ContentProvider::notifyDocumentClosed( const rtl::OUString
& rDocId
)
235 osl::MutexGuard
aGuard( getContentListMutex() );
237 ::ucbhelper::ContentRefList aAllContents
;
238 queryExistingContents( aAllContents
);
240 ::ucbhelper::ContentRefList::const_iterator it
= aAllContents
.begin();
241 ::ucbhelper::ContentRefList::const_iterator end
= aAllContents
.end();
243 // Notify all content objects related to the closed doc.
245 bool bFoundDocumentContent
= false;
246 rtl::Reference
< Content
> xRoot
;
250 Uri
aUri( (*it
)->getIdentifier()->getContentIdentifier() );
251 OSL_ENSURE( aUri
.isValid(),
252 "ContentProvider::notifyDocumentClosed - Invalid URI!" );
254 if ( !bFoundDocumentContent
)
258 xRoot
= static_cast< Content
* >( (*it
).get() );
260 else if ( aUri
.isDocument() )
262 if ( aUri
.getDocumentId() == rDocId
)
264 bFoundDocumentContent
= true;
266 // document content will notify removal of child itself;
267 // no need for the root to propagate this.
273 if ( aUri
.getDocumentId() == rDocId
)
276 rtl::Reference
< Content
> xContent
277 = static_cast< Content
* >( (*it
).get() );
279 xContent
->notifyDocumentClosed();
287 // No document content found for rDocId but root content
288 // instanciated. Root content must announce document removal
289 // to content event listeners.
290 xRoot
->notifyChildRemoved( rDocId
);
294 //=========================================================================
296 void ContentProvider::notifyDocumentOpened( const rtl::OUString
& rDocId
)
298 osl::MutexGuard
aGuard( getContentListMutex() );
300 ::ucbhelper::ContentRefList aAllContents
;
301 queryExistingContents( aAllContents
);
303 ::ucbhelper::ContentRefList::const_iterator it
= aAllContents
.begin();
304 ::ucbhelper::ContentRefList::const_iterator end
= aAllContents
.end();
306 // Find root content. If instanciated let it propagate document insertion.
310 Uri
aUri( (*it
)->getIdentifier()->getContentIdentifier() );
311 OSL_ENSURE( aUri
.isValid(),
312 "ContentProvider::notifyDocumentOpened - Invalid URI!" );
316 rtl::Reference
< Content
> xRoot
317 = static_cast< Content
* >( (*it
).get() );
318 xRoot
->notifyChildInserted( rDocId
);
328 //=========================================================================
332 //=========================================================================
334 uno::Reference
< embed::XStorage
>
335 ContentProvider::queryStorage( const rtl::OUString
& rUri
,
336 StorageAccessMode eMode
) const
338 if ( m_xStgElemFac
.is() )
342 return m_xStgElemFac
->createStorage( rUri
, eMode
);
344 catch ( embed::InvalidStorageException
const & )
346 OSL_FAIL( "Caught InvalidStorageException!" );
348 catch ( lang::IllegalArgumentException
const & )
350 OSL_FAIL( "Caught IllegalArgumentException!" );
352 catch ( io::IOException
const & )
354 // Okay to happen, for instance when the storage does not exist.
355 //OSL_ENSURE( false, "Caught IOException!" );
357 catch ( embed::StorageWrappedTargetException
const & )
359 OSL_FAIL( "Caught embed::StorageWrappedTargetException!" );
362 return uno::Reference
< embed::XStorage
>();
365 //=========================================================================
366 uno::Reference
< embed::XStorage
>
367 ContentProvider::queryStorageClone( const rtl::OUString
& rUri
) const
369 if ( m_xStgElemFac
.is() )
374 uno::Reference
< embed::XStorage
> xParentStorage
375 = m_xStgElemFac
->createStorage( aUri
.getParentUri(), READ
);
376 uno::Reference
< embed::XStorage
> xStorage
377 = m_xStgElemFac
->createTemporaryStorage();
379 xParentStorage
->copyStorageElementLastCommitTo(
380 aUri
.getDecodedName(), xStorage
);
383 catch ( embed::InvalidStorageException
const & )
385 OSL_FAIL( "Caught InvalidStorageException!" );
387 catch ( lang::IllegalArgumentException
const & )
389 OSL_FAIL( "Caught IllegalArgumentException!" );
391 catch ( io::IOException
const & )
393 // Okay to happen, for instance when the storage does not exist.
394 //OSL_ENSURE( false, "Caught IOException!" );
396 catch ( embed::StorageWrappedTargetException
const & )
398 OSL_FAIL( "Caught embed::StorageWrappedTargetException!" );
402 return uno::Reference
< embed::XStorage
>();
405 //=========================================================================
406 uno::Reference
< io::XInputStream
>
407 ContentProvider::queryInputStream( const rtl::OUString
& rUri
,
408 const rtl::OUString
& rPassword
) const
409 throw ( packages::WrongPasswordException
)
411 if ( m_xStgElemFac
.is() )
415 return m_xStgElemFac
->createInputStream( rUri
, rPassword
);
417 catch ( embed::InvalidStorageException
const & )
419 OSL_FAIL( "Caught InvalidStorageException!" );
421 catch ( lang::IllegalArgumentException
const & )
423 OSL_FAIL( "Caught IllegalArgumentException!" );
425 catch ( io::IOException
const & )
427 OSL_FAIL( "Caught IOException!" );
429 catch ( embed::StorageWrappedTargetException
const & )
431 OSL_FAIL( "Caught embed::StorageWrappedTargetException!" );
433 // catch ( packages::WrongPasswordException const & )
435 // // the key provided is wrong; rethrow; to be handled by caller.
439 return uno::Reference
< io::XInputStream
>();
442 //=========================================================================
443 uno::Reference
< io::XOutputStream
>
444 ContentProvider::queryOutputStream( const rtl::OUString
& rUri
,
445 const rtl::OUString
& rPassword
,
446 bool bTruncate
) const
447 throw ( packages::WrongPasswordException
)
449 if ( m_xStgElemFac
.is() )
454 m_xStgElemFac
->createOutputStream( rUri
, rPassword
, bTruncate
);
456 catch ( embed::InvalidStorageException
const & )
458 OSL_FAIL( "Caught InvalidStorageException!" );
460 catch ( lang::IllegalArgumentException
const & )
462 OSL_FAIL( "Caught IllegalArgumentException!" );
464 catch ( io::IOException
const & )
466 // Okay to happen, for instance when the storage does not exist.
467 //OSL_ENSURE( false, "Caught IOException!" );
469 catch ( embed::StorageWrappedTargetException
const & )
471 OSL_FAIL( "Caught embed::StorageWrappedTargetException!" );
473 // catch ( packages::WrongPasswordException const & )
475 // // the key provided is wrong; rethrow; to be handled by caller.
479 return uno::Reference
< io::XOutputStream
>();
482 //=========================================================================
483 uno::Reference
< io::XStream
>
484 ContentProvider::queryStream( const rtl::OUString
& rUri
,
485 const rtl::OUString
& rPassword
,
486 bool bTruncate
) const
487 throw ( packages::WrongPasswordException
)
489 if ( m_xStgElemFac
.is() )
493 return m_xStgElemFac
->createStream( rUri
, rPassword
, bTruncate
);
495 catch ( embed::InvalidStorageException
const & )
497 OSL_FAIL( "Caught InvalidStorageException!" );
499 catch ( lang::IllegalArgumentException
const & )
501 OSL_FAIL( "Caught IllegalArgumentException!" );
503 catch ( io::IOException
const & )
505 // Okay to happen, for instance when the storage does not exist.
506 //OSL_ENSURE( false, "Caught IOException!" );
508 catch ( embed::StorageWrappedTargetException
const & )
510 OSL_FAIL( "Caught embed::StorageWrappedTargetException!" );
512 // catch ( packages::WrongPasswordException const & )
514 // // the key provided is wrong; rethrow; to be handled by caller.
518 return uno::Reference
< io::XStream
>();
521 //=========================================================================
522 bool ContentProvider::queryNamesOfChildren(
523 const rtl::OUString
& rUri
, uno::Sequence
< rtl::OUString
> & rNames
) const
528 // special handling for root, which has no storage, but children.
529 if ( m_xDocsMgr
.is() )
531 rNames
= m_xDocsMgr
->queryDocuments();
537 if ( m_xStgElemFac
.is() )
541 uno::Reference
< embed::XStorage
> xStorage
542 = m_xStgElemFac
->createStorage( rUri
, READ
);
544 OSL_ENSURE( xStorage
.is(), "Got no Storage!" );
548 uno::Reference
< container::XNameAccess
> xNA(
549 xStorage
, uno::UNO_QUERY
);
551 OSL_ENSURE( xNA
.is(), "Got no css.container.XNameAccess!" );
554 rNames
= xNA
->getElementNames();
559 catch ( embed::InvalidStorageException
const & )
561 OSL_FAIL( "Caught InvalidStorageException!" );
563 catch ( lang::IllegalArgumentException
const & )
565 OSL_FAIL( "Caught IllegalArgumentException!" );
567 catch ( io::IOException
const & )
569 // Okay to happen, for instance if the storage does not exist.
570 //OSL_ENSURE( false, "Caught IOException!" );
572 catch ( embed::StorageWrappedTargetException
const & )
574 OSL_FAIL( "Caught embed::StorageWrappedTargetException!" );
581 //=========================================================================
583 ContentProvider::queryStorageTitle( const rtl::OUString
& rUri
) const
585 rtl::OUString aTitle
;
591 aTitle
= rtl::OUString();
593 else if ( aUri
.isDocument() )
595 // for documents, title shall not be derived from URL. It shall
596 // be somethimg more 'speaking' than just the document UID.
597 if ( m_xDocsMgr
.is() )
598 aTitle
= m_xDocsMgr
->queryStorageTitle( aUri
.getDocumentId() );
602 // derive title from URL
603 aTitle
= aUri
.getDecodedName();
606 OSL_ENSURE( !aTitle
.isEmpty() || aUri
.isRoot(),
607 "ContentProvider::queryStorageTitle - empty title!" );
611 //=========================================================================
612 uno::Reference
< frame::XModel
>
613 ContentProvider::queryDocumentModel( const rtl::OUString
& rUri
) const
615 uno::Reference
< frame::XModel
> xModel
;
617 if ( m_xDocsMgr
.is() )
620 xModel
= m_xDocsMgr
->queryDocumentModel( aUri
.getDocumentId() );
623 OSL_ENSURE( xModel
.is(),
624 "ContentProvider::queryDocumentModel - no model!" );
628 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */