Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / ucb / source / ucp / tdoc / tdoc_provider.cxx
blob5e036e0d76c447204da6f44c2a00bd5beac49f62
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 <comphelper/diagnose_ex.hxx>
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 : ContentProvider_Base( 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 // XServiceInfo methods.
68 OUString SAL_CALL ContentProvider::getImplementationName()
70 return "com.sun.star.comp.ucb.TransientDocumentsContentProvider";
73 sal_Bool SAL_CALL ContentProvider::supportsService( const OUString& ServiceName )
75 return cppu::supportsService( this, ServiceName );
78 css::uno::Sequence< OUString > SAL_CALL ContentProvider::getSupportedServiceNames()
80 return { "com.sun.star.ucb.TransientDocumentsContentProvider" };
84 // Service factory implementation.
87 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
88 ucb_tdoc_ContentProvider_get_implementation(
89 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
91 return cppu::acquire(new ContentProvider(context));
94 // XContentProvider methods.
97 // virtual
98 uno::Reference< ucb::XContent > SAL_CALL
99 ContentProvider::queryContent(
100 const uno::Reference< ucb::XContentIdentifier >& Identifier )
102 Uri aUri( Identifier->getContentIdentifier() );
103 if ( !aUri.isValid() )
104 throw ucb::IllegalIdentifierException(
105 "Invalid URL!",
106 Identifier );
108 // Normalize URI.
109 uno::Reference< ucb::XContentIdentifier > xCanonicId
110 = new ::ucbhelper::ContentIdentifier( aUri.getUri() );
112 osl::MutexGuard aGuard( m_aMutex );
114 // Check, if a content with given id already exists...
115 uno::Reference< ucb::XContent > xContent
116 = queryExistingContent( xCanonicId );
118 if ( !xContent.is() )
120 // Create a new content.
121 xContent = Content::create( m_xContext, this, xCanonicId );
122 registerNewContent( xContent );
125 return xContent;
129 // XTransientDocumentsDocumentContentIdentifierFactory methods.
131 uno::Reference<ucb::XContentIdentifier> SAL_CALL
132 ContentProvider::createDocumentContentIdentifier(
133 uno::Reference<frame::XModel> const& xModel)
135 // model -> id -> content identifier -> queryContent
136 if ( !m_xDocsMgr.is() )
138 throw lang::IllegalArgumentException(
139 "No Document Manager!",
140 static_cast< cppu::OWeakObject * >( this ),
141 1 );
144 OUString aDocId = tdoc_ucp::OfficeDocumentsManager::queryDocumentId(xModel);
145 if ( aDocId.isEmpty() )
147 throw lang::IllegalArgumentException(
148 "Unable to obtain document id from model!",
149 static_cast< cppu::OWeakObject * >( this ),
150 1 );
153 OUString aBuffer = TDOC_URL_SCHEME ":/" + aDocId;
155 uno::Reference< ucb::XContentIdentifier > xId
156 = new ::ucbhelper::ContentIdentifier( aBuffer );
157 return xId;
160 // XTransientDocumentsDocumentContentFactory methods.
162 uno::Reference< ucb::XContent > SAL_CALL
163 ContentProvider::createDocumentContent(
164 uno::Reference<frame::XModel> const& xModel)
166 uno::Reference<ucb::XContentIdentifier> const xId(
167 createDocumentContentIdentifier(xModel));
169 osl::MutexGuard aGuard( m_aMutex );
171 // Check, if a content with given id already exists...
172 uno::Reference< ucb::XContent > xContent
173 = queryExistingContent( xId );
175 if ( !xContent.is() )
177 // Create a new content.
178 xContent = Content::create( m_xContext, this, xId );
181 if ( xContent.is() )
182 return xContent;
184 // no content.
185 throw lang::IllegalArgumentException(
186 "Illegal Content Identifier!",
187 static_cast< cppu::OWeakObject * >( this ),
188 1 );
192 // interface OfficeDocumentsEventListener
195 // virtual
196 void ContentProvider::notifyDocumentClosed( std::u16string_view rDocId )
198 osl::MutexGuard aGuard( getContentListMutex() );
200 ::ucbhelper::ContentRefList aAllContents;
201 queryExistingContents( aAllContents );
203 // Notify all content objects related to the closed doc.
205 bool bFoundDocumentContent = false;
206 rtl::Reference< Content > xRoot;
208 for ( const auto& rContent : aAllContents )
210 Uri aUri( rContent->getIdentifier()->getContentIdentifier() );
211 OSL_ENSURE( aUri.isValid(),
212 "ContentProvider::notifyDocumentClosed - Invalid URI!" );
214 if ( !bFoundDocumentContent )
216 if ( aUri.isRoot() )
218 xRoot = static_cast< Content * >( rContent.get() );
220 else if ( aUri.isDocument() )
222 if ( aUri.getDocumentId() == rDocId )
224 bFoundDocumentContent = true;
226 // document content will notify removal of child itself;
227 // no need for the root to propagate this.
228 xRoot.clear();
233 if ( aUri.getDocumentId() == rDocId )
235 // Inform content.
236 rtl::Reference< Content > xContent
237 = static_cast< Content * >( rContent.get() );
239 xContent->notifyDocumentClosed();
243 if ( xRoot.is() )
245 // No document content found for rDocId but root content
246 // instantiated. Root content must announce document removal
247 // to content event listeners.
248 xRoot->notifyChildRemoved( rDocId );
253 // virtual
254 void ContentProvider::notifyDocumentOpened( std::u16string_view rDocId )
256 osl::MutexGuard aGuard( getContentListMutex() );
258 ::ucbhelper::ContentRefList aAllContents;
259 queryExistingContents( aAllContents );
261 // Find root content. If instantiated let it propagate document insertion.
263 for ( const auto& rContent : aAllContents )
265 Uri aUri( rContent->getIdentifier()->getContentIdentifier() );
266 OSL_ENSURE( aUri.isValid(),
267 "ContentProvider::notifyDocumentOpened - Invalid URI!" );
269 if ( aUri.isRoot() )
271 rtl::Reference< Content > xRoot
272 = static_cast< Content * >( rContent.get() );
273 xRoot->notifyChildInserted( rDocId );
275 // Done.
276 break;
282 // Non-UNO
285 uno::Reference< embed::XStorage >
286 ContentProvider::queryStorage( const OUString & rUri,
287 StorageAccessMode eMode ) const
289 if ( m_xStgElemFac.is() )
293 return m_xStgElemFac->createStorage( rUri, eMode );
295 catch ( embed::InvalidStorageException const & )
297 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
299 catch ( lang::IllegalArgumentException const & )
301 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
303 catch ( io::IOException const & )
305 // Okay to happen, for instance when the storage does not exist.
306 //OSL_ENSURE( false, "Caught IOException!" );
308 catch ( embed::StorageWrappedTargetException const & )
310 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
313 return uno::Reference< embed::XStorage >();
317 uno::Reference< embed::XStorage >
318 ContentProvider::queryStorageClone( const OUString & rUri ) const
320 if ( m_xStgElemFac.is() )
324 Uri aUri( rUri );
325 uno::Reference< embed::XStorage > xParentStorage
326 = m_xStgElemFac->createStorage( aUri.getParentUri(), READ );
327 uno::Reference< embed::XStorage > xStorage
328 = m_xStgElemFac->createTemporaryStorage();
330 xParentStorage->copyStorageElementLastCommitTo(
331 aUri.getDecodedName(), xStorage );
332 return xStorage;
334 catch ( embed::InvalidStorageException const & )
336 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
338 catch ( lang::IllegalArgumentException const & )
340 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
342 catch ( io::IOException const & )
344 // Okay to happen, for instance when the storage does not exist.
345 //OSL_ENSURE( false, "Caught IOException!" );
347 catch ( embed::StorageWrappedTargetException const & )
349 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
353 return uno::Reference< embed::XStorage >();
357 uno::Reference< io::XInputStream >
358 ContentProvider::queryInputStream( const OUString & rUri,
359 const OUString & rPassword ) const
361 if ( m_xStgElemFac.is() )
365 return m_xStgElemFac->createInputStream( rUri, rPassword );
367 catch ( embed::InvalidStorageException const & )
369 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
371 catch ( lang::IllegalArgumentException const & )
373 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
375 catch ( io::IOException const & )
377 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
379 catch ( embed::StorageWrappedTargetException const & )
381 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
383 // catch ( packages::WrongPasswordException const & )
384 // {
385 // // the key provided is wrong; rethrow; to be handled by caller.
386 // throw;
387 // }
389 return uno::Reference< io::XInputStream >();
393 uno::Reference< io::XOutputStream >
394 ContentProvider::queryOutputStream( const OUString & rUri,
395 const OUString & rPassword,
396 bool bTruncate ) const
398 if ( m_xStgElemFac.is() )
402 return
403 m_xStgElemFac->createOutputStream( rUri, rPassword, bTruncate );
405 catch ( embed::InvalidStorageException const & )
407 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
409 catch ( lang::IllegalArgumentException const & )
411 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
413 catch ( io::IOException const & )
415 // Okay to happen, for instance when the storage does not exist.
416 //OSL_ENSURE( false, "Caught IOException!" );
418 catch ( embed::StorageWrappedTargetException const & )
420 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
422 // catch ( packages::WrongPasswordException const & )
423 // {
424 // // the key provided is wrong; rethrow; to be handled by caller.
425 // throw;
426 // }
428 return uno::Reference< io::XOutputStream >();
432 uno::Reference< io::XStream >
433 ContentProvider::queryStream( const OUString & rUri,
434 const OUString & rPassword,
435 bool bTruncate ) const
437 if ( m_xStgElemFac.is() )
441 return m_xStgElemFac->createStream( rUri, rPassword, bTruncate );
443 catch ( embed::InvalidStorageException const & )
445 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
447 catch ( lang::IllegalArgumentException const & )
449 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
451 catch ( io::IOException const & )
453 // Okay to happen, for instance when the storage does not exist.
454 //OSL_ENSURE( false, "Caught IOException!" );
456 catch ( embed::StorageWrappedTargetException const & )
458 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
460 // catch ( packages::WrongPasswordException const & )
461 // {
462 // // the key provided is wrong; rethrow; to be handled by caller.
463 // throw;
464 // }
466 return uno::Reference< io::XStream >();
470 bool ContentProvider::queryNamesOfChildren(
471 const OUString & rUri, uno::Sequence< OUString > & rNames ) const
473 Uri aUri( rUri );
474 if ( aUri.isRoot() )
476 // special handling for root, which has no storage, but children.
477 if ( m_xDocsMgr.is() )
479 rNames = m_xDocsMgr->queryDocuments();
480 return true;
483 else
485 if ( m_xStgElemFac.is() )
489 uno::Reference< embed::XStorage > xStorage
490 = m_xStgElemFac->createStorage( rUri, READ );
492 OSL_ENSURE( xStorage.is(), "Got no Storage!" );
494 if ( xStorage.is() )
496 rNames = xStorage->getElementNames();
497 return true;
500 catch ( embed::InvalidStorageException const & )
502 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
504 catch ( lang::IllegalArgumentException const & )
506 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
508 catch ( io::IOException const & )
510 // Okay to happen, for instance if the storage does not exist.
511 //OSL_ENSURE( false, "Caught IOException!" );
513 catch ( embed::StorageWrappedTargetException const & )
515 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
519 return false;
523 OUString
524 ContentProvider::queryStorageTitle( const OUString & rUri ) const
526 OUString aTitle;
528 Uri aUri( rUri );
529 if ( aUri.isRoot() )
531 // always empty.
532 aTitle.clear();
534 else if ( aUri.isDocument() )
536 // for documents, title shall not be derived from URL. It shall
537 // be something more 'speaking' than just the document UID.
538 if ( m_xDocsMgr.is() )
539 aTitle = m_xDocsMgr->queryStorageTitle( aUri.getDocumentId() );
541 else
543 // derive title from URL
544 aTitle = aUri.getDecodedName();
547 OSL_ENSURE( !aTitle.isEmpty() || aUri.isRoot(),
548 "ContentProvider::queryStorageTitle - empty title!" );
549 return aTitle;
553 uno::Reference< frame::XModel >
554 ContentProvider::queryDocumentModel( const OUString & rUri ) const
556 uno::Reference< frame::XModel > xModel;
558 if ( m_xDocsMgr.is() )
560 Uri aUri( rUri );
561 xModel = m_xDocsMgr->queryDocumentModel( aUri.getDocumentId() );
564 OSL_ENSURE( xModel.is(),
565 "ContentProvider::queryDocumentModel - no model!" );
566 return xModel;
570 css::util::DateTime ContentProvider::queryStreamDateModified(OUString const & uri) const {
571 return m_xDocsMgr->queryStreamDateModified(uri);
574 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */