Version 4.0.2.1, tag libreoffice-4.0.2.1
[LibreOffice.git] / ucb / source / ucp / tdoc / tdoc_provider.cxx
blobd5fbb0b6ea2a07bd02ab52add7e0b57a11b73209
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 "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 //=========================================================================
61 // virtual
62 ContentProvider::~ContentProvider()
64 if ( m_xDocsMgr.is() )
65 m_xDocsMgr->destroy();
68 //=========================================================================
70 // XInterface methods.
72 //=========================================================================
74 XINTERFACE_IMPL_4( ContentProvider,
75 lang::XTypeProvider,
76 lang::XServiceInfo,
77 ucb::XContentProvider,
78 frame::XTransientDocumentsDocumentContentFactory );
80 //=========================================================================
82 // XTypeProvider methods.
84 //=========================================================================
86 XTYPEPROVIDER_IMPL_4( ContentProvider,
87 lang::XTypeProvider,
88 lang::XServiceInfo,
89 ucb::XContentProvider,
90 frame::XTransientDocumentsDocumentContentFactory );
92 //=========================================================================
94 // XServiceInfo methods.
96 //=========================================================================
98 XSERVICEINFO_IMPL_1(
99 ContentProvider,
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 //=========================================================================
119 // virtual
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!" ) ),
129 Identifier );
131 // Normalize URI.
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 );
148 return xContent;
151 //=========================================================================
153 // XTransientDocumentsDocumentContentFactory methods.
155 //=========================================================================
157 // virtual
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 );
188 if ( xContent.is() )
189 return xContent;
191 // no content.
192 throw lang::IllegalArgumentException(
193 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
194 "Illegal Content Identifier!" ) ),
195 static_cast< cppu::OWeakObject * >( this ),
196 1 );
198 else
200 throw lang::IllegalArgumentException(
201 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
202 "Unable to obtain document id from model!" ) ),
203 static_cast< cppu::OWeakObject * >( this ),
204 1 );
207 else
209 throw lang::IllegalArgumentException(
210 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
211 "No Document Manager!" ) ),
212 static_cast< cppu::OWeakObject * >( this ),
213 1 );
217 //=========================================================================
219 // interface OfficeDocumentsEventListener
221 //=========================================================================
223 // virtual
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;
239 while ( it != end )
241 Uri aUri( (*it)->getIdentifier()->getContentIdentifier() );
242 OSL_ENSURE( aUri.isValid(),
243 "ContentProvider::notifyDocumentClosed - Invalid URI!" );
245 if ( !bFoundDocumentContent )
247 if ( aUri.isRoot() )
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.
259 xRoot.clear();
264 if ( aUri.getDocumentId() == rDocId )
266 // Inform content.
267 rtl::Reference< Content > xContent
268 = static_cast< Content * >( (*it).get() );
270 xContent->notifyDocumentClosed();
273 ++it;
276 if ( xRoot.is() )
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 //=========================================================================
286 // virtual
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.
299 while ( it != end )
301 Uri aUri( (*it)->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 * >( (*it).get() );
309 xRoot->notifyChildInserted( rDocId );
311 // Done.
312 break;
315 ++it;
319 //=========================================================================
321 // Non-UNO
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() )
364 Uri aUri( rUri );
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 );
372 return 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 & )
425 // {
426 // // the key provided is wrong; rethrow; to be handled by caller.
427 // throw;
428 // }
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() )
444 return
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 & )
465 // {
466 // // the key provided is wrong; rethrow; to be handled by caller.
467 // throw;
468 // }
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 & )
504 // {
505 // // the key provided is wrong; rethrow; to be handled by caller.
506 // throw;
507 // }
509 return uno::Reference< io::XStream >();
512 //=========================================================================
513 bool ContentProvider::queryNamesOfChildren(
514 const rtl::OUString & rUri, uno::Sequence< rtl::OUString > & rNames ) const
516 Uri aUri( rUri );
517 if ( aUri.isRoot() )
519 // special handling for root, which has no storage, but children.
520 if ( m_xDocsMgr.is() )
522 rNames = m_xDocsMgr->queryDocuments();
523 return true;
526 else
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!" );
537 if ( xStorage.is() )
539 uno::Reference< container::XNameAccess > xNA(
540 xStorage, uno::UNO_QUERY );
542 OSL_ENSURE( xNA.is(), "Got no css.container.XNameAccess!" );
543 if ( xNA.is() )
545 rNames = xNA->getElementNames();
546 return true;
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!" );
569 return false;
572 //=========================================================================
573 rtl::OUString
574 ContentProvider::queryStorageTitle( const rtl::OUString & rUri ) const
576 rtl::OUString aTitle;
578 Uri aUri( rUri );
579 if ( aUri.isRoot() )
581 // always empty.
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() );
591 else
593 // derive title from URL
594 aTitle = aUri.getDecodedName();
597 OSL_ENSURE( !aTitle.isEmpty() || aUri.isRoot(),
598 "ContentProvider::queryStorageTitle - empty title!" );
599 return aTitle;
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() )
610 Uri aUri( rUri );
611 xModel = m_xDocsMgr->queryDocumentModel( aUri.getDocumentId() );
614 OSL_ENSURE( xModel.is(),
615 "ContentProvider::queryDocumentModel - no model!" );
616 return xModel;
619 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */