1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 /**************************************************************************
23 **************************************************************************
25 *************************************************************************/
27 #include "rtl/ustrbuf.hxx"
29 #include "com/sun/star/container/XNameAccess.hpp"
30 #include "com/sun/star/embed/XStorage.hpp"
32 #include "comphelper/processfactory.hxx"
33 #include "ucbhelper/contentidentifier.hxx"
35 #include "tdoc_provider.hxx"
36 #include "tdoc_content.hxx"
37 #include "tdoc_uri.hxx"
38 #include "tdoc_docmgr.hxx"
39 #include "tdoc_storage.hxx"
41 using namespace com::sun::star
;
42 using namespace tdoc_ucp
;
44 //=========================================================================
45 //=========================================================================
47 // ContentProvider Implementation.
49 //=========================================================================
50 //=========================================================================
52 ContentProvider::ContentProvider(
53 const uno::Reference
< lang::XMultiServiceFactory
>& xSMgr
)
54 : ::ucbhelper::ContentProviderImplHelper( comphelper::getComponentContext(xSMgr
) ),
55 m_xDocsMgr( new OfficeDocumentsManager( comphelper::getComponentContext(xSMgr
), this ) ),
56 m_xStgElemFac( new StorageElementFactory( xSMgr
, m_xDocsMgr
) )
60 //=========================================================================
62 ContentProvider::~ContentProvider()
64 if ( m_xDocsMgr
.is() )
65 m_xDocsMgr
->destroy();
68 //=========================================================================
70 // XInterface methods.
72 //=========================================================================
74 XINTERFACE_IMPL_4( ContentProvider
,
77 ucb::XContentProvider
,
78 frame::XTransientDocumentsDocumentContentFactory
);
80 //=========================================================================
82 // XTypeProvider methods.
84 //=========================================================================
86 XTYPEPROVIDER_IMPL_4( ContentProvider
,
89 ucb::XContentProvider
,
90 frame::XTransientDocumentsDocumentContentFactory
);
92 //=========================================================================
94 // XServiceInfo methods.
96 //=========================================================================
100 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
101 "com.sun.star.comp.ucb.TransientDocumentsContentProvider" ) ),
102 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
103 TDOC_CONTENT_PROVIDER_SERVICE_NAME
) ) );
105 //=========================================================================
107 // Service factory implementation.
109 //=========================================================================
111 ONE_INSTANCE_SERVICE_FACTORY_IMPL( ContentProvider
);
113 //=========================================================================
115 // XContentProvider methods.
117 //=========================================================================
120 uno::Reference
< ucb::XContent
> SAL_CALL
121 ContentProvider::queryContent(
122 const uno::Reference
< ucb::XContentIdentifier
>& Identifier
)
123 throw( ucb::IllegalIdentifierException
, uno::RuntimeException
)
125 Uri
aUri( Identifier
->getContentIdentifier() );
126 if ( !aUri
.isValid() )
127 throw ucb::IllegalIdentifierException(
128 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid URL!" ) ),
132 uno::Reference
< ucb::XContentIdentifier
> xCanonicId
133 = new ::ucbhelper::ContentIdentifier( aUri
.getUri() );
135 osl::MutexGuard
aGuard( m_aMutex
);
137 // Check, if a content with given id already exists...
138 uno::Reference
< ucb::XContent
> xContent
139 = queryExistingContent( xCanonicId
).get();
141 if ( !xContent
.is() )
143 // Create a new content.
144 xContent
= Content::create( m_xContext
, this, xCanonicId
);
145 registerNewContent( xContent
);
151 //=========================================================================
153 // XTransientDocumentsDocumentContentFactory methods.
155 //=========================================================================
158 uno::Reference
< ucb::XContent
> SAL_CALL
159 ContentProvider::createDocumentContent(
160 const uno::Reference
< frame::XModel
>& Model
)
161 throw ( lang::IllegalArgumentException
, uno::RuntimeException
)
163 // model -> id -> content identifier -> queryContent
164 if ( m_xDocsMgr
.is() )
166 rtl::OUString aDocId
= m_xDocsMgr
->queryDocumentId( Model
);
167 if ( !aDocId
.isEmpty() )
169 rtl::OUStringBuffer aBuffer
;
170 aBuffer
.appendAscii( TDOC_URL_SCHEME
":/" );
171 aBuffer
.append( aDocId
);
173 uno::Reference
< ucb::XContentIdentifier
> xId
174 = new ::ucbhelper::ContentIdentifier( aBuffer
.makeStringAndClear() );
176 osl::MutexGuard
aGuard( m_aMutex
);
178 // Check, if a content with given id already exists...
179 uno::Reference
< ucb::XContent
> xContent
180 = queryExistingContent( xId
).get();
182 if ( !xContent
.is() )
184 // Create a new content.
185 xContent
= Content::create( m_xContext
, this, xId
);
192 throw lang::IllegalArgumentException(
193 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
194 "Illegal Content Identifier!" ) ),
195 static_cast< cppu::OWeakObject
* >( this ),
200 throw lang::IllegalArgumentException(
201 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
202 "Unable to obtain document id from model!" ) ),
203 static_cast< cppu::OWeakObject
* >( this ),
209 throw lang::IllegalArgumentException(
210 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
211 "No Document Manager!" ) ),
212 static_cast< cppu::OWeakObject
* >( this ),
217 //=========================================================================
219 // interface OfficeDocumentsEventListener
221 //=========================================================================
224 void ContentProvider::notifyDocumentClosed( const rtl::OUString
& rDocId
)
226 osl::MutexGuard
aGuard( getContentListMutex() );
228 ::ucbhelper::ContentRefList aAllContents
;
229 queryExistingContents( aAllContents
);
231 ::ucbhelper::ContentRefList::const_iterator it
= aAllContents
.begin();
232 ::ucbhelper::ContentRefList::const_iterator end
= aAllContents
.end();
234 // Notify all content objects related to the closed doc.
236 bool bFoundDocumentContent
= false;
237 rtl::Reference
< Content
> xRoot
;
241 Uri
aUri( (*it
)->getIdentifier()->getContentIdentifier() );
242 OSL_ENSURE( aUri
.isValid(),
243 "ContentProvider::notifyDocumentClosed - Invalid URI!" );
245 if ( !bFoundDocumentContent
)
249 xRoot
= static_cast< Content
* >( (*it
).get() );
251 else if ( aUri
.isDocument() )
253 if ( aUri
.getDocumentId() == rDocId
)
255 bFoundDocumentContent
= true;
257 // document content will notify removal of child itself;
258 // no need for the root to propagate this.
264 if ( aUri
.getDocumentId() == rDocId
)
267 rtl::Reference
< Content
> xContent
268 = static_cast< Content
* >( (*it
).get() );
270 xContent
->notifyDocumentClosed();
278 // No document content found for rDocId but root content
279 // instanciated. Root content must announce document removal
280 // to content event listeners.
281 xRoot
->notifyChildRemoved( rDocId
);
285 //=========================================================================
287 void ContentProvider::notifyDocumentOpened( const rtl::OUString
& rDocId
)
289 osl::MutexGuard
aGuard( getContentListMutex() );
291 ::ucbhelper::ContentRefList aAllContents
;
292 queryExistingContents( aAllContents
);
294 ::ucbhelper::ContentRefList::const_iterator it
= aAllContents
.begin();
295 ::ucbhelper::ContentRefList::const_iterator end
= aAllContents
.end();
297 // Find root content. If instanciated let it propagate document insertion.
301 Uri
aUri( (*it
)->getIdentifier()->getContentIdentifier() );
302 OSL_ENSURE( aUri
.isValid(),
303 "ContentProvider::notifyDocumentOpened - Invalid URI!" );
307 rtl::Reference
< Content
> xRoot
308 = static_cast< Content
* >( (*it
).get() );
309 xRoot
->notifyChildInserted( rDocId
);
319 //=========================================================================
323 //=========================================================================
325 uno::Reference
< embed::XStorage
>
326 ContentProvider::queryStorage( const rtl::OUString
& rUri
,
327 StorageAccessMode eMode
) const
329 if ( m_xStgElemFac
.is() )
333 return m_xStgElemFac
->createStorage( rUri
, eMode
);
335 catch ( embed::InvalidStorageException
const & )
337 OSL_FAIL( "Caught InvalidStorageException!" );
339 catch ( lang::IllegalArgumentException
const & )
341 OSL_FAIL( "Caught IllegalArgumentException!" );
343 catch ( io::IOException
const & )
345 // Okay to happen, for instance when the storage does not exist.
346 //OSL_ENSURE( false, "Caught IOException!" );
348 catch ( embed::StorageWrappedTargetException
const & )
350 OSL_FAIL( "Caught embed::StorageWrappedTargetException!" );
353 return uno::Reference
< embed::XStorage
>();
356 //=========================================================================
357 uno::Reference
< embed::XStorage
>
358 ContentProvider::queryStorageClone( const rtl::OUString
& rUri
) const
360 if ( m_xStgElemFac
.is() )
365 uno::Reference
< embed::XStorage
> xParentStorage
366 = m_xStgElemFac
->createStorage( aUri
.getParentUri(), READ
);
367 uno::Reference
< embed::XStorage
> xStorage
368 = m_xStgElemFac
->createTemporaryStorage();
370 xParentStorage
->copyStorageElementLastCommitTo(
371 aUri
.getDecodedName(), xStorage
);
374 catch ( embed::InvalidStorageException
const & )
376 OSL_FAIL( "Caught InvalidStorageException!" );
378 catch ( lang::IllegalArgumentException
const & )
380 OSL_FAIL( "Caught IllegalArgumentException!" );
382 catch ( io::IOException
const & )
384 // Okay to happen, for instance when the storage does not exist.
385 //OSL_ENSURE( false, "Caught IOException!" );
387 catch ( embed::StorageWrappedTargetException
const & )
389 OSL_FAIL( "Caught embed::StorageWrappedTargetException!" );
393 return uno::Reference
< embed::XStorage
>();
396 //=========================================================================
397 uno::Reference
< io::XInputStream
>
398 ContentProvider::queryInputStream( const rtl::OUString
& rUri
,
399 const rtl::OUString
& rPassword
) const
400 throw ( packages::WrongPasswordException
)
402 if ( m_xStgElemFac
.is() )
406 return m_xStgElemFac
->createInputStream( rUri
, rPassword
);
408 catch ( embed::InvalidStorageException
const & )
410 OSL_FAIL( "Caught InvalidStorageException!" );
412 catch ( lang::IllegalArgumentException
const & )
414 OSL_FAIL( "Caught IllegalArgumentException!" );
416 catch ( io::IOException
const & )
418 OSL_FAIL( "Caught IOException!" );
420 catch ( embed::StorageWrappedTargetException
const & )
422 OSL_FAIL( "Caught embed::StorageWrappedTargetException!" );
424 // catch ( packages::WrongPasswordException const & )
426 // // the key provided is wrong; rethrow; to be handled by caller.
430 return uno::Reference
< io::XInputStream
>();
433 //=========================================================================
434 uno::Reference
< io::XOutputStream
>
435 ContentProvider::queryOutputStream( const rtl::OUString
& rUri
,
436 const rtl::OUString
& rPassword
,
437 bool bTruncate
) const
438 throw ( packages::WrongPasswordException
)
440 if ( m_xStgElemFac
.is() )
445 m_xStgElemFac
->createOutputStream( rUri
, rPassword
, bTruncate
);
447 catch ( embed::InvalidStorageException
const & )
449 OSL_FAIL( "Caught InvalidStorageException!" );
451 catch ( lang::IllegalArgumentException
const & )
453 OSL_FAIL( "Caught IllegalArgumentException!" );
455 catch ( io::IOException
const & )
457 // Okay to happen, for instance when the storage does not exist.
458 //OSL_ENSURE( false, "Caught IOException!" );
460 catch ( embed::StorageWrappedTargetException
const & )
462 OSL_FAIL( "Caught embed::StorageWrappedTargetException!" );
464 // catch ( packages::WrongPasswordException const & )
466 // // the key provided is wrong; rethrow; to be handled by caller.
470 return uno::Reference
< io::XOutputStream
>();
473 //=========================================================================
474 uno::Reference
< io::XStream
>
475 ContentProvider::queryStream( const rtl::OUString
& rUri
,
476 const rtl::OUString
& rPassword
,
477 bool bTruncate
) const
478 throw ( packages::WrongPasswordException
)
480 if ( m_xStgElemFac
.is() )
484 return m_xStgElemFac
->createStream( rUri
, rPassword
, bTruncate
);
486 catch ( embed::InvalidStorageException
const & )
488 OSL_FAIL( "Caught InvalidStorageException!" );
490 catch ( lang::IllegalArgumentException
const & )
492 OSL_FAIL( "Caught IllegalArgumentException!" );
494 catch ( io::IOException
const & )
496 // Okay to happen, for instance when the storage does not exist.
497 //OSL_ENSURE( false, "Caught IOException!" );
499 catch ( embed::StorageWrappedTargetException
const & )
501 OSL_FAIL( "Caught embed::StorageWrappedTargetException!" );
503 // catch ( packages::WrongPasswordException const & )
505 // // the key provided is wrong; rethrow; to be handled by caller.
509 return uno::Reference
< io::XStream
>();
512 //=========================================================================
513 bool ContentProvider::queryNamesOfChildren(
514 const rtl::OUString
& rUri
, uno::Sequence
< rtl::OUString
> & rNames
) const
519 // special handling for root, which has no storage, but children.
520 if ( m_xDocsMgr
.is() )
522 rNames
= m_xDocsMgr
->queryDocuments();
528 if ( m_xStgElemFac
.is() )
532 uno::Reference
< embed::XStorage
> xStorage
533 = m_xStgElemFac
->createStorage( rUri
, READ
);
535 OSL_ENSURE( xStorage
.is(), "Got no Storage!" );
539 uno::Reference
< container::XNameAccess
> xNA(
540 xStorage
, uno::UNO_QUERY
);
542 OSL_ENSURE( xNA
.is(), "Got no css.container.XNameAccess!" );
545 rNames
= xNA
->getElementNames();
550 catch ( embed::InvalidStorageException
const & )
552 OSL_FAIL( "Caught InvalidStorageException!" );
554 catch ( lang::IllegalArgumentException
const & )
556 OSL_FAIL( "Caught IllegalArgumentException!" );
558 catch ( io::IOException
const & )
560 // Okay to happen, for instance if the storage does not exist.
561 //OSL_ENSURE( false, "Caught IOException!" );
563 catch ( embed::StorageWrappedTargetException
const & )
565 OSL_FAIL( "Caught embed::StorageWrappedTargetException!" );
572 //=========================================================================
574 ContentProvider::queryStorageTitle( const rtl::OUString
& rUri
) const
576 rtl::OUString aTitle
;
582 aTitle
= rtl::OUString();
584 else if ( aUri
.isDocument() )
586 // for documents, title shall not be derived from URL. It shall
587 // be somethimg more 'speaking' than just the document UID.
588 if ( m_xDocsMgr
.is() )
589 aTitle
= m_xDocsMgr
->queryStorageTitle( aUri
.getDocumentId() );
593 // derive title from URL
594 aTitle
= aUri
.getDecodedName();
597 OSL_ENSURE( !aTitle
.isEmpty() || aUri
.isRoot(),
598 "ContentProvider::queryStorageTitle - empty title!" );
602 //=========================================================================
603 uno::Reference
< frame::XModel
>
604 ContentProvider::queryDocumentModel( const rtl::OUString
& rUri
) const
606 uno::Reference
< frame::XModel
> xModel
;
608 if ( m_xDocsMgr
.is() )
611 xModel
= m_xDocsMgr
->queryDocumentModel( aUri
.getDocumentId() );
614 OSL_ENSURE( xModel
.is(),
615 "ContentProvider::queryDocumentModel - no model!" );
619 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */