1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: tdoc_provider.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_ucb.hxx"
34 /**************************************************************************
36 **************************************************************************
38 *************************************************************************/
40 #include "rtl/ustrbuf.hxx"
42 #include "com/sun/star/container/XNameAccess.hpp"
43 #include "com/sun/star/embed/XStorage.hpp"
45 #include "ucbhelper/contentidentifier.hxx"
47 #include "tdoc_provider.hxx"
48 #include "tdoc_content.hxx"
49 #include "tdoc_uri.hxx"
50 #include "tdoc_docmgr.hxx"
51 #include "tdoc_storage.hxx"
53 using namespace com::sun::star
;
54 using namespace tdoc_ucp
;
56 //=========================================================================
57 //=========================================================================
59 // ContentProvider Implementation.
61 //=========================================================================
62 //=========================================================================
64 ContentProvider::ContentProvider(
65 const uno::Reference
< lang::XMultiServiceFactory
>& xSMgr
)
66 : ::ucbhelper::ContentProviderImplHelper( xSMgr
),
67 m_xDocsMgr( new OfficeDocumentsManager( xSMgr
, this ) ),
68 m_xStgElemFac( new StorageElementFactory( xSMgr
, m_xDocsMgr
) )
72 //=========================================================================
74 ContentProvider::~ContentProvider()
76 if ( m_xDocsMgr
.is() )
77 m_xDocsMgr
->destroy();
80 //=========================================================================
82 // XInterface methods.
84 //=========================================================================
86 XINTERFACE_IMPL_4( ContentProvider
,
89 ucb::XContentProvider
,
90 frame::XTransientDocumentsDocumentContentFactory
);
92 //=========================================================================
94 // XTypeProvider methods.
96 //=========================================================================
98 XTYPEPROVIDER_IMPL_4( ContentProvider
,
101 ucb::XContentProvider
,
102 frame::XTransientDocumentsDocumentContentFactory
);
104 //=========================================================================
106 // XServiceInfo methods.
108 //=========================================================================
112 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
113 "com.sun.star.comp.ucb.TransientDocumentsContentProvider" ) ),
114 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
115 TDOC_CONTENT_PROVIDER_SERVICE_NAME
) ) );
117 //=========================================================================
119 // Service factory implementation.
121 //=========================================================================
123 ONE_INSTANCE_SERVICE_FACTORY_IMPL( ContentProvider
);
125 //=========================================================================
127 // XContentProvider methods.
129 //=========================================================================
132 uno::Reference
< ucb::XContent
> SAL_CALL
133 ContentProvider::queryContent(
134 const uno::Reference
< ucb::XContentIdentifier
>& Identifier
)
135 throw( ucb::IllegalIdentifierException
, uno::RuntimeException
)
137 Uri
aUri( Identifier
->getContentIdentifier() );
138 if ( !aUri
.isValid() )
139 throw ucb::IllegalIdentifierException(
140 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid URL!" ) ),
144 uno::Reference
< ucb::XContentIdentifier
> xCanonicId
145 = new ::ucbhelper::ContentIdentifier( m_xSMgr
, aUri
.getUri() );
147 osl::MutexGuard
aGuard( m_aMutex
);
149 // Check, if a content with given id already exists...
150 uno::Reference
< ucb::XContent
> xContent
151 = queryExistingContent( xCanonicId
).get();
153 if ( !xContent
.is() )
155 // Create a new content.
156 xContent
= Content::create( m_xSMgr
, this, xCanonicId
);
157 registerNewContent( xContent
);
163 //=========================================================================
165 // XTransientDocumentsDocumentContentFactory methods.
167 //=========================================================================
170 uno::Reference
< ucb::XContent
> SAL_CALL
171 ContentProvider::createDocumentContent(
172 const uno::Reference
< frame::XModel
>& Model
)
173 throw ( lang::IllegalArgumentException
, uno::RuntimeException
)
175 // model -> id -> content identifier -> queryContent
176 if ( m_xDocsMgr
.is() )
178 rtl::OUString aDocId
= m_xDocsMgr
->queryDocumentId( Model
);
179 if ( aDocId
.getLength() > 0 )
181 rtl::OUStringBuffer aBuffer
;
182 aBuffer
.appendAscii( TDOC_URL_SCHEME
":/" );
183 aBuffer
.append( aDocId
);
185 uno::Reference
< ucb::XContentIdentifier
> xId
186 = new ::ucbhelper::ContentIdentifier(
187 m_xSMgr
, aBuffer
.makeStringAndClear() );
189 osl::MutexGuard
aGuard( m_aMutex
);
191 // Check, if a content with given id already exists...
192 uno::Reference
< ucb::XContent
> xContent
193 = queryExistingContent( xId
).get();
195 if ( !xContent
.is() )
197 // Create a new content.
198 xContent
= Content::create( m_xSMgr
, this, xId
);
205 throw lang::IllegalArgumentException(
206 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
207 "Illegal Content Identifier!" ) ),
208 static_cast< cppu::OWeakObject
* >( this ),
213 throw lang::IllegalArgumentException(
214 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
215 "Unable to obtain document id from model!" ) ),
216 static_cast< cppu::OWeakObject
* >( this ),
222 throw lang::IllegalArgumentException(
223 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
224 "No Document Manager!" ) ),
225 static_cast< cppu::OWeakObject
* >( this ),
230 //=========================================================================
232 // interface OfficeDocumentsEventListener
234 //=========================================================================
237 void ContentProvider::notifyDocumentClosed( const rtl::OUString
& rDocId
)
239 osl::MutexGuard
aGuard( getContentListMutex() );
241 ::ucbhelper::ContentRefList aAllContents
;
242 queryExistingContents( aAllContents
);
244 ::ucbhelper::ContentRefList::const_iterator it
= aAllContents
.begin();
245 ::ucbhelper::ContentRefList::const_iterator end
= aAllContents
.end();
247 // Notify all content objects related to the closed doc.
249 bool bFoundDocumentContent
= false;
250 rtl::Reference
< Content
> xRoot
;
254 Uri
aUri( (*it
)->getIdentifier()->getContentIdentifier() );
255 OSL_ENSURE( aUri
.isValid(),
256 "ContentProvider::notifyDocumentClosed - Invalid URI!" );
258 if ( !bFoundDocumentContent
)
262 xRoot
= static_cast< Content
* >( (*it
).get() );
264 else if ( aUri
.isDocument() )
266 if ( aUri
.getDocumentId() == rDocId
)
268 bFoundDocumentContent
= true;
270 // document content will notify removal of child itself;
271 // no need for the root to propagate this.
277 if ( aUri
.getDocumentId() == rDocId
)
280 rtl::Reference
< Content
> xContent
281 = static_cast< Content
* >( (*it
).get() );
283 xContent
->notifyDocumentClosed();
291 // No document content found for rDocId but root content
292 // instanciated. Root content must announce document removal
293 // to content event listeners.
294 xRoot
->notifyChildRemoved( rDocId
);
298 //=========================================================================
300 void ContentProvider::notifyDocumentOpened( const rtl::OUString
& rDocId
)
302 osl::MutexGuard
aGuard( getContentListMutex() );
304 ::ucbhelper::ContentRefList aAllContents
;
305 queryExistingContents( aAllContents
);
307 ::ucbhelper::ContentRefList::const_iterator it
= aAllContents
.begin();
308 ::ucbhelper::ContentRefList::const_iterator end
= aAllContents
.end();
310 // Find root content. If instanciated let it propagate document insertion.
314 Uri
aUri( (*it
)->getIdentifier()->getContentIdentifier() );
315 OSL_ENSURE( aUri
.isValid(),
316 "ContentProvider::notifyDocumentOpened - Invalid URI!" );
320 rtl::Reference
< Content
> xRoot
321 = static_cast< Content
* >( (*it
).get() );
322 xRoot
->notifyChildInserted( rDocId
);
332 //=========================================================================
336 //=========================================================================
338 uno::Reference
< embed::XStorage
>
339 ContentProvider::queryStorage( const rtl::OUString
& rUri
,
340 StorageAccessMode eMode
) const
342 if ( m_xStgElemFac
.is() )
346 return m_xStgElemFac
->createStorage( rUri
, eMode
);
348 catch ( embed::InvalidStorageException
const & )
350 OSL_ENSURE( false, "Caught InvalidStorageException!" );
352 catch ( lang::IllegalArgumentException
const & )
354 OSL_ENSURE( false, "Caught IllegalArgumentException!" );
356 catch ( io::IOException
const & )
358 // Okay to happen, for instance when the storage does not exist.
359 //OSL_ENSURE( false, "Caught IOException!" );
361 catch ( embed::StorageWrappedTargetException
const & )
363 OSL_ENSURE( false, "Caught embed::StorageWrappedTargetException!" );
366 return uno::Reference
< embed::XStorage
>();
369 //=========================================================================
370 uno::Reference
< embed::XStorage
>
371 ContentProvider::queryStorageClone( const rtl::OUString
& rUri
) const
373 if ( m_xStgElemFac
.is() )
378 uno::Reference
< embed::XStorage
> xParentStorage
379 = m_xStgElemFac
->createStorage( aUri
.getParentUri(), READ
);
380 uno::Reference
< embed::XStorage
> xStorage
381 = m_xStgElemFac
->createTemporaryStorage();
383 xParentStorage
->copyStorageElementLastCommitTo(
384 aUri
.getDecodedName(), xStorage
);
387 catch ( embed::InvalidStorageException
const & )
389 OSL_ENSURE( false, "Caught InvalidStorageException!" );
391 catch ( lang::IllegalArgumentException
const & )
393 OSL_ENSURE( false, "Caught IllegalArgumentException!" );
395 catch ( io::IOException
const & )
397 // Okay to happen, for instance when the storage does not exist.
398 //OSL_ENSURE( false, "Caught IOException!" );
400 catch ( embed::StorageWrappedTargetException
const & )
402 OSL_ENSURE( false, "Caught embed::StorageWrappedTargetException!" );
406 return uno::Reference
< embed::XStorage
>();
409 //=========================================================================
410 uno::Reference
< io::XInputStream
>
411 ContentProvider::queryInputStream( const rtl::OUString
& rUri
,
412 const rtl::OUString
& rPassword
) const
413 throw ( packages::WrongPasswordException
)
415 if ( m_xStgElemFac
.is() )
419 return m_xStgElemFac
->createInputStream( rUri
, rPassword
);
421 catch ( embed::InvalidStorageException
const & )
423 OSL_ENSURE( false, "Caught InvalidStorageException!" );
425 catch ( lang::IllegalArgumentException
const & )
427 OSL_ENSURE( false, "Caught IllegalArgumentException!" );
429 catch ( io::IOException
const & )
431 OSL_ENSURE( false, "Caught IOException!" );
433 catch ( embed::StorageWrappedTargetException
const & )
435 OSL_ENSURE( false, "Caught embed::StorageWrappedTargetException!" );
437 // catch ( packages::WrongPasswordException const & )
439 // // the key provided is wrong; rethrow; to be handled by caller.
443 return uno::Reference
< io::XInputStream
>();
446 //=========================================================================
447 uno::Reference
< io::XOutputStream
>
448 ContentProvider::queryOutputStream( const rtl::OUString
& rUri
,
449 const rtl::OUString
& rPassword
,
450 bool bTruncate
) const
451 throw ( packages::WrongPasswordException
)
453 if ( m_xStgElemFac
.is() )
458 m_xStgElemFac
->createOutputStream( rUri
, rPassword
, bTruncate
);
460 catch ( embed::InvalidStorageException
const & )
462 OSL_ENSURE( false, "Caught InvalidStorageException!" );
464 catch ( lang::IllegalArgumentException
const & )
466 OSL_ENSURE( false, "Caught IllegalArgumentException!" );
468 catch ( io::IOException
const & )
470 // Okay to happen, for instance when the storage does not exist.
471 //OSL_ENSURE( false, "Caught IOException!" );
473 catch ( embed::StorageWrappedTargetException
const & )
475 OSL_ENSURE( false, "Caught embed::StorageWrappedTargetException!" );
477 // catch ( packages::WrongPasswordException const & )
479 // // the key provided is wrong; rethrow; to be handled by caller.
483 return uno::Reference
< io::XOutputStream
>();
486 //=========================================================================
487 uno::Reference
< io::XStream
>
488 ContentProvider::queryStream( const rtl::OUString
& rUri
,
489 const rtl::OUString
& rPassword
,
490 bool bTruncate
) const
491 throw ( packages::WrongPasswordException
)
493 if ( m_xStgElemFac
.is() )
497 return m_xStgElemFac
->createStream( rUri
, rPassword
, bTruncate
);
499 catch ( embed::InvalidStorageException
const & )
501 OSL_ENSURE( false, "Caught InvalidStorageException!" );
503 catch ( lang::IllegalArgumentException
const & )
505 OSL_ENSURE( false, "Caught IllegalArgumentException!" );
507 catch ( io::IOException
const & )
509 // Okay to happen, for instance when the storage does not exist.
510 //OSL_ENSURE( false, "Caught IOException!" );
512 catch ( embed::StorageWrappedTargetException
const & )
514 OSL_ENSURE( false, "Caught embed::StorageWrappedTargetException!" );
516 // catch ( packages::WrongPasswordException const & )
518 // // the key provided is wrong; rethrow; to be handled by caller.
522 return uno::Reference
< io::XStream
>();
525 //=========================================================================
526 bool ContentProvider::queryNamesOfChildren(
527 const rtl::OUString
& rUri
, uno::Sequence
< rtl::OUString
> & rNames
) const
532 // special handling for root, which has no storage, but children.
533 if ( m_xDocsMgr
.is() )
535 rNames
= m_xDocsMgr
->queryDocuments();
541 if ( m_xStgElemFac
.is() )
545 uno::Reference
< embed::XStorage
> xStorage
546 = m_xStgElemFac
->createStorage( rUri
, READ
);
548 OSL_ENSURE( xStorage
.is(), "Got no Storage!" );
552 uno::Reference
< container::XNameAccess
> xNA(
553 xStorage
, uno::UNO_QUERY
);
555 OSL_ENSURE( xNA
.is(), "Got no css.container.XNameAccess!" );
558 rNames
= xNA
->getElementNames();
563 catch ( embed::InvalidStorageException
const & )
565 OSL_ENSURE( false, "Caught InvalidStorageException!" );
567 catch ( lang::IllegalArgumentException
const & )
569 OSL_ENSURE( false, "Caught IllegalArgumentException!" );
571 catch ( io::IOException
const & )
573 // Okay to happen, for instance if the storage does not exist.
574 //OSL_ENSURE( false, "Caught IOException!" );
576 catch ( embed::StorageWrappedTargetException
const & )
579 "Caught embed::StorageWrappedTargetException!" );
586 //=========================================================================
588 ContentProvider::queryStorageTitle( const rtl::OUString
& rUri
) const
590 rtl::OUString aTitle
;
596 aTitle
= rtl::OUString();
598 else if ( aUri
.isDocument() )
600 // for documents, title shall not be derived from URL. It shall
601 // be somethimg more 'speaking' than just the document UID.
602 if ( m_xDocsMgr
.is() )
603 aTitle
= m_xDocsMgr
->queryStorageTitle( aUri
.getDocumentId() );
607 // derive title from URL
608 aTitle
= aUri
.getDecodedName();
611 OSL_ENSURE( ( aTitle
.getLength() > 0 ) || aUri
.isRoot(),
612 "ContentProvider::queryStorageTitle - empty title!" );
616 //=========================================================================
617 uno::Reference
< frame::XModel
>
618 ContentProvider::queryDocumentModel( const rtl::OUString
& rUri
) const
620 uno::Reference
< frame::XModel
> xModel
;
622 if ( m_xDocsMgr
.is() )
625 xModel
= m_xDocsMgr
->queryDocumentModel( aUri
.getDocumentId() );
628 OSL_ENSURE( xModel
.is(),
629 "ContentProvider::queryDocumentModel - no model!" );