bump product version to 7.2.5.1
[LibreOffice.git] / ucb / source / ucp / tdoc / tdoc_provider.cxx
blobf6b187cca1a875da67838c12e69acbefd0eb1032
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 /**************************************************************************
22 TODO
23 **************************************************************************
25 *************************************************************************/
27 #include <tools/diagnose_ex.h>
29 #include <com/sun/star/embed/InvalidStorageException.hpp>
30 #include <com/sun/star/embed/StorageWrappedTargetException.hpp>
31 #include <com/sun/star/io/IOException.hpp>
32 #include <com/sun/star/ucb/IllegalIdentifierException.hpp>
33 #include <cppuhelper/queryinterface.hxx>
34 #include <ucbhelper/contentidentifier.hxx>
35 #include <ucbhelper/macros.hxx>
37 #include "tdoc_provider.hxx"
38 #include "tdoc_content.hxx"
39 #include "tdoc_uri.hxx"
40 #include "tdoc_docmgr.hxx"
41 #include "tdoc_storage.hxx"
43 using namespace com::sun::star;
44 using namespace tdoc_ucp;
47 // ContentProvider Implementation.
50 ContentProvider::ContentProvider(
51 const uno::Reference< uno::XComponentContext >& rxContext )
52 : ::ucbhelper::ContentProviderImplHelper( rxContext ),
53 m_xDocsMgr( new OfficeDocumentsManager( rxContext, this ) ),
54 m_xStgElemFac( new StorageElementFactory( rxContext, m_xDocsMgr ) )
59 // virtual
60 ContentProvider::~ContentProvider()
62 if ( m_xDocsMgr.is() )
63 m_xDocsMgr->destroy();
67 // XInterface methods.
68 void SAL_CALL ContentProvider::acquire()
69 noexcept
71 OWeakObject::acquire();
74 void SAL_CALL ContentProvider::release()
75 noexcept
77 OWeakObject::release();
80 css::uno::Any SAL_CALL ContentProvider::queryInterface( const css::uno::Type & rType )
82 css::uno::Any aRet = cppu::queryInterface( rType,
83 static_cast< lang::XTypeProvider* >(this),
84 static_cast< lang::XServiceInfo* >(this),
85 static_cast< ucb::XContentProvider* >(this),
86 static_cast< frame::XTransientDocumentsDocumentContentIdentifierFactory* >(this),
87 static_cast< frame::XTransientDocumentsDocumentContentFactory* >(this)
89 return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
92 // XTypeProvider methods.
95 XTYPEPROVIDER_IMPL_5( ContentProvider,
96 lang::XTypeProvider,
97 lang::XServiceInfo,
98 ucb::XContentProvider,
99 frame::XTransientDocumentsDocumentContentIdentifierFactory,
100 frame::XTransientDocumentsDocumentContentFactory );
103 // XServiceInfo methods.
104 OUString SAL_CALL ContentProvider::getImplementationName()
106 return "com.sun.star.comp.ucb.TransientDocumentsContentProvider";
109 sal_Bool SAL_CALL ContentProvider::supportsService( const OUString& ServiceName )
111 return cppu::supportsService( this, ServiceName );
114 css::uno::Sequence< OUString > SAL_CALL ContentProvider::getSupportedServiceNames()
116 return { "com.sun.star.ucb.TransientDocumentsContentProvider" };
120 // Service factory implementation.
123 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
124 ucb_tdoc_ContentProvider_get_implementation(
125 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
127 return cppu::acquire(new ContentProvider(context));
130 // XContentProvider methods.
133 // virtual
134 uno::Reference< ucb::XContent > SAL_CALL
135 ContentProvider::queryContent(
136 const uno::Reference< ucb::XContentIdentifier >& Identifier )
138 Uri aUri( Identifier->getContentIdentifier() );
139 if ( !aUri.isValid() )
140 throw ucb::IllegalIdentifierException(
141 "Invalid URL!",
142 Identifier );
144 // Normalize URI.
145 uno::Reference< ucb::XContentIdentifier > xCanonicId
146 = new ::ucbhelper::ContentIdentifier( aUri.getUri() );
148 osl::MutexGuard aGuard( m_aMutex );
150 // Check, if a content with given id already exists...
151 uno::Reference< ucb::XContent > xContent
152 = queryExistingContent( xCanonicId );
154 if ( !xContent.is() )
156 // Create a new content.
157 xContent = Content::create( m_xContext, this, xCanonicId );
158 registerNewContent( xContent );
161 return xContent;
165 // XTransientDocumentsDocumentContentIdentifierFactory methods.
167 uno::Reference<ucb::XContentIdentifier> SAL_CALL
168 ContentProvider::createDocumentContentIdentifier(
169 uno::Reference<frame::XModel> const& xModel)
171 // model -> id -> content identifier -> queryContent
172 if ( !m_xDocsMgr.is() )
174 throw lang::IllegalArgumentException(
175 "No Document Manager!",
176 static_cast< cppu::OWeakObject * >( this ),
177 1 );
180 OUString aDocId = tdoc_ucp::OfficeDocumentsManager::queryDocumentId(xModel);
181 if ( aDocId.isEmpty() )
183 throw lang::IllegalArgumentException(
184 "Unable to obtain document id from model!",
185 static_cast< cppu::OWeakObject * >( this ),
186 1 );
189 OUString aBuffer = TDOC_URL_SCHEME ":/" + aDocId;
191 uno::Reference< ucb::XContentIdentifier > xId
192 = new ::ucbhelper::ContentIdentifier( aBuffer );
193 return xId;
196 // XTransientDocumentsDocumentContentFactory methods.
198 uno::Reference< ucb::XContent > SAL_CALL
199 ContentProvider::createDocumentContent(
200 uno::Reference<frame::XModel> const& xModel)
202 uno::Reference<ucb::XContentIdentifier> const xId(
203 createDocumentContentIdentifier(xModel));
205 osl::MutexGuard aGuard( m_aMutex );
207 // Check, if a content with given id already exists...
208 uno::Reference< ucb::XContent > xContent
209 = queryExistingContent( xId );
211 if ( !xContent.is() )
213 // Create a new content.
214 xContent = Content::create( m_xContext, this, xId );
217 if ( xContent.is() )
218 return xContent;
220 // no content.
221 throw lang::IllegalArgumentException(
222 "Illegal Content Identifier!",
223 static_cast< cppu::OWeakObject * >( this ),
224 1 );
228 // interface OfficeDocumentsEventListener
231 // virtual
232 void ContentProvider::notifyDocumentClosed( const OUString & rDocId )
234 osl::MutexGuard aGuard( getContentListMutex() );
236 ::ucbhelper::ContentRefList aAllContents;
237 queryExistingContents( aAllContents );
239 // Notify all content objects related to the closed doc.
241 bool bFoundDocumentContent = false;
242 rtl::Reference< Content > xRoot;
244 for ( const auto& rContent : aAllContents )
246 Uri aUri( rContent->getIdentifier()->getContentIdentifier() );
247 OSL_ENSURE( aUri.isValid(),
248 "ContentProvider::notifyDocumentClosed - Invalid URI!" );
250 if ( !bFoundDocumentContent )
252 if ( aUri.isRoot() )
254 xRoot = static_cast< Content * >( rContent.get() );
256 else if ( aUri.isDocument() )
258 if ( aUri.getDocumentId() == rDocId )
260 bFoundDocumentContent = true;
262 // document content will notify removal of child itself;
263 // no need for the root to propagate this.
264 xRoot.clear();
269 if ( aUri.getDocumentId() == rDocId )
271 // Inform content.
272 rtl::Reference< Content > xContent
273 = static_cast< Content * >( rContent.get() );
275 xContent->notifyDocumentClosed();
279 if ( xRoot.is() )
281 // No document content found for rDocId but root content
282 // instantiated. Root content must announce document removal
283 // to content event listeners.
284 xRoot->notifyChildRemoved( rDocId );
289 // virtual
290 void ContentProvider::notifyDocumentOpened( const OUString & rDocId )
292 osl::MutexGuard aGuard( getContentListMutex() );
294 ::ucbhelper::ContentRefList aAllContents;
295 queryExistingContents( aAllContents );
297 // Find root content. If instantiated let it propagate document insertion.
299 for ( const auto& rContent : aAllContents )
301 Uri aUri( rContent->getIdentifier()->getContentIdentifier() );
302 OSL_ENSURE( aUri.isValid(),
303 "ContentProvider::notifyDocumentOpened - Invalid URI!" );
305 if ( aUri.isRoot() )
307 rtl::Reference< Content > xRoot
308 = static_cast< Content * >( rContent.get() );
309 xRoot->notifyChildInserted( rDocId );
311 // Done.
312 break;
318 // Non-UNO
321 uno::Reference< embed::XStorage >
322 ContentProvider::queryStorage( const OUString & rUri,
323 StorageAccessMode eMode ) const
325 if ( m_xStgElemFac.is() )
329 return m_xStgElemFac->createStorage( rUri, eMode );
331 catch ( embed::InvalidStorageException const & )
333 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
335 catch ( lang::IllegalArgumentException const & )
337 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
339 catch ( io::IOException const & )
341 // Okay to happen, for instance when the storage does not exist.
342 //OSL_ENSURE( false, "Caught IOException!" );
344 catch ( embed::StorageWrappedTargetException const & )
346 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
349 return uno::Reference< embed::XStorage >();
353 uno::Reference< embed::XStorage >
354 ContentProvider::queryStorageClone( const OUString & rUri ) const
356 if ( m_xStgElemFac.is() )
360 Uri aUri( rUri );
361 uno::Reference< embed::XStorage > xParentStorage
362 = m_xStgElemFac->createStorage( aUri.getParentUri(), READ );
363 uno::Reference< embed::XStorage > xStorage
364 = m_xStgElemFac->createTemporaryStorage();
366 xParentStorage->copyStorageElementLastCommitTo(
367 aUri.getDecodedName(), xStorage );
368 return xStorage;
370 catch ( embed::InvalidStorageException const & )
372 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
374 catch ( lang::IllegalArgumentException const & )
376 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
378 catch ( io::IOException const & )
380 // Okay to happen, for instance when the storage does not exist.
381 //OSL_ENSURE( false, "Caught IOException!" );
383 catch ( embed::StorageWrappedTargetException const & )
385 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
389 return uno::Reference< embed::XStorage >();
393 uno::Reference< io::XInputStream >
394 ContentProvider::queryInputStream( const OUString & rUri,
395 const OUString & rPassword ) const
397 if ( m_xStgElemFac.is() )
401 return m_xStgElemFac->createInputStream( rUri, rPassword );
403 catch ( embed::InvalidStorageException const & )
405 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
407 catch ( lang::IllegalArgumentException const & )
409 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
411 catch ( io::IOException const & )
413 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
415 catch ( embed::StorageWrappedTargetException const & )
417 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
419 // catch ( packages::WrongPasswordException const & )
420 // {
421 // // the key provided is wrong; rethrow; to be handled by caller.
422 // throw;
423 // }
425 return uno::Reference< io::XInputStream >();
429 uno::Reference< io::XOutputStream >
430 ContentProvider::queryOutputStream( const OUString & rUri,
431 const OUString & rPassword,
432 bool bTruncate ) const
434 if ( m_xStgElemFac.is() )
438 return
439 m_xStgElemFac->createOutputStream( rUri, rPassword, bTruncate );
441 catch ( embed::InvalidStorageException const & )
443 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
445 catch ( lang::IllegalArgumentException const & )
447 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
449 catch ( io::IOException const & )
451 // Okay to happen, for instance when the storage does not exist.
452 //OSL_ENSURE( false, "Caught IOException!" );
454 catch ( embed::StorageWrappedTargetException const & )
456 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
458 // catch ( packages::WrongPasswordException const & )
459 // {
460 // // the key provided is wrong; rethrow; to be handled by caller.
461 // throw;
462 // }
464 return uno::Reference< io::XOutputStream >();
468 uno::Reference< io::XStream >
469 ContentProvider::queryStream( const OUString & rUri,
470 const OUString & rPassword,
471 bool bTruncate ) const
473 if ( m_xStgElemFac.is() )
477 return m_xStgElemFac->createStream( rUri, rPassword, bTruncate );
479 catch ( embed::InvalidStorageException const & )
481 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
483 catch ( lang::IllegalArgumentException const & )
485 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
487 catch ( io::IOException const & )
489 // Okay to happen, for instance when the storage does not exist.
490 //OSL_ENSURE( false, "Caught IOException!" );
492 catch ( embed::StorageWrappedTargetException const & )
494 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
496 // catch ( packages::WrongPasswordException const & )
497 // {
498 // // the key provided is wrong; rethrow; to be handled by caller.
499 // throw;
500 // }
502 return uno::Reference< io::XStream >();
506 bool ContentProvider::queryNamesOfChildren(
507 const OUString & rUri, uno::Sequence< OUString > & rNames ) const
509 Uri aUri( rUri );
510 if ( aUri.isRoot() )
512 // special handling for root, which has no storage, but children.
513 if ( m_xDocsMgr.is() )
515 rNames = m_xDocsMgr->queryDocuments();
516 return true;
519 else
521 if ( m_xStgElemFac.is() )
525 uno::Reference< embed::XStorage > xStorage
526 = m_xStgElemFac->createStorage( rUri, READ );
528 OSL_ENSURE( xStorage.is(), "Got no Storage!" );
530 if ( xStorage.is() )
532 rNames = xStorage->getElementNames();
533 return true;
536 catch ( embed::InvalidStorageException const & )
538 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
540 catch ( lang::IllegalArgumentException const & )
542 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
544 catch ( io::IOException const & )
546 // Okay to happen, for instance if the storage does not exist.
547 //OSL_ENSURE( false, "Caught IOException!" );
549 catch ( embed::StorageWrappedTargetException const & )
551 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
555 return false;
559 OUString
560 ContentProvider::queryStorageTitle( const OUString & rUri ) const
562 OUString aTitle;
564 Uri aUri( rUri );
565 if ( aUri.isRoot() )
567 // always empty.
568 aTitle.clear();
570 else if ( aUri.isDocument() )
572 // for documents, title shall not be derived from URL. It shall
573 // be something more 'speaking' than just the document UID.
574 if ( m_xDocsMgr.is() )
575 aTitle = m_xDocsMgr->queryStorageTitle( aUri.getDocumentId() );
577 else
579 // derive title from URL
580 aTitle = aUri.getDecodedName();
583 OSL_ENSURE( !aTitle.isEmpty() || aUri.isRoot(),
584 "ContentProvider::queryStorageTitle - empty title!" );
585 return aTitle;
589 uno::Reference< frame::XModel >
590 ContentProvider::queryDocumentModel( const OUString & rUri ) const
592 uno::Reference< frame::XModel > xModel;
594 if ( m_xDocsMgr.is() )
596 Uri aUri( rUri );
597 xModel = m_xDocsMgr->queryDocumentModel( aUri.getDocumentId() );
600 OSL_ENSURE( xModel.is(),
601 "ContentProvider::queryDocumentModel - no model!" );
602 return xModel;
605 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */