Bump for 3.6-28
[LibreOffice.git] / ucb / source / ucp / tdoc / tdoc_provider.cxx
blobbe5a4f1920fbb3f037ed90eea63fea916ea3808d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 /**************************************************************************
31 TODO
32 **************************************************************************
34 *************************************************************************/
36 #include "rtl/ustrbuf.hxx"
38 #include "com/sun/star/container/XNameAccess.hpp"
39 #include "com/sun/star/embed/XStorage.hpp"
41 #include "ucbhelper/contentidentifier.hxx"
43 #include "tdoc_provider.hxx"
44 #include "tdoc_content.hxx"
45 #include "tdoc_uri.hxx"
46 #include "tdoc_docmgr.hxx"
47 #include "tdoc_storage.hxx"
49 using namespace com::sun::star;
50 using namespace tdoc_ucp;
52 //=========================================================================
53 //=========================================================================
55 // ContentProvider Implementation.
57 //=========================================================================
58 //=========================================================================
60 ContentProvider::ContentProvider(
61 const uno::Reference< lang::XMultiServiceFactory >& xSMgr )
62 : ::ucbhelper::ContentProviderImplHelper( xSMgr ),
63 m_xDocsMgr( new OfficeDocumentsManager( xSMgr, this ) ),
64 m_xStgElemFac( new StorageElementFactory( xSMgr, m_xDocsMgr ) )
68 //=========================================================================
69 // virtual
70 ContentProvider::~ContentProvider()
72 if ( m_xDocsMgr.is() )
73 m_xDocsMgr->destroy();
76 //=========================================================================
78 // XInterface methods.
80 //=========================================================================
82 XINTERFACE_IMPL_4( ContentProvider,
83 lang::XTypeProvider,
84 lang::XServiceInfo,
85 ucb::XContentProvider,
86 frame::XTransientDocumentsDocumentContentFactory );
88 //=========================================================================
90 // XTypeProvider methods.
92 //=========================================================================
94 XTYPEPROVIDER_IMPL_4( ContentProvider,
95 lang::XTypeProvider,
96 lang::XServiceInfo,
97 ucb::XContentProvider,
98 frame::XTransientDocumentsDocumentContentFactory );
100 //=========================================================================
102 // XServiceInfo methods.
104 //=========================================================================
106 XSERVICEINFO_IMPL_1(
107 ContentProvider,
108 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
109 "com.sun.star.comp.ucb.TransientDocumentsContentProvider" ) ),
110 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
111 TDOC_CONTENT_PROVIDER_SERVICE_NAME ) ) );
113 //=========================================================================
115 // Service factory implementation.
117 //=========================================================================
119 ONE_INSTANCE_SERVICE_FACTORY_IMPL( ContentProvider );
121 //=========================================================================
123 // XContentProvider methods.
125 //=========================================================================
127 // virtual
128 uno::Reference< ucb::XContent > SAL_CALL
129 ContentProvider::queryContent(
130 const uno::Reference< ucb::XContentIdentifier >& Identifier )
131 throw( ucb::IllegalIdentifierException, uno::RuntimeException )
133 Uri aUri( Identifier->getContentIdentifier() );
134 if ( !aUri.isValid() )
135 throw ucb::IllegalIdentifierException(
136 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid URL!" ) ),
137 Identifier );
139 // Normalize URI.
140 uno::Reference< ucb::XContentIdentifier > xCanonicId
141 = new ::ucbhelper::ContentIdentifier( m_xSMgr, aUri.getUri() );
143 osl::MutexGuard aGuard( m_aMutex );
145 // Check, if a content with given id already exists...
146 uno::Reference< ucb::XContent > xContent
147 = queryExistingContent( xCanonicId ).get();
149 if ( !xContent.is() )
151 // Create a new content.
152 xContent = Content::create( m_xSMgr, this, xCanonicId );
153 registerNewContent( xContent );
156 return xContent;
159 //=========================================================================
161 // XTransientDocumentsDocumentContentFactory methods.
163 //=========================================================================
165 // virtual
166 uno::Reference< ucb::XContent > SAL_CALL
167 ContentProvider::createDocumentContent(
168 const uno::Reference< frame::XModel >& Model )
169 throw ( lang::IllegalArgumentException, uno::RuntimeException )
171 // model -> id -> content identifier -> queryContent
172 if ( m_xDocsMgr.is() )
174 rtl::OUString aDocId = m_xDocsMgr->queryDocumentId( Model );
175 if ( !aDocId.isEmpty() )
177 rtl::OUStringBuffer aBuffer;
178 aBuffer.appendAscii( TDOC_URL_SCHEME ":/" );
179 aBuffer.append( aDocId );
181 uno::Reference< ucb::XContentIdentifier > xId
182 = new ::ucbhelper::ContentIdentifier(
183 m_xSMgr, aBuffer.makeStringAndClear() );
185 osl::MutexGuard aGuard( m_aMutex );
187 // Check, if a content with given id already exists...
188 uno::Reference< ucb::XContent > xContent
189 = queryExistingContent( xId ).get();
191 if ( !xContent.is() )
193 // Create a new content.
194 xContent = Content::create( m_xSMgr, this, xId );
197 if ( xContent.is() )
198 return xContent;
200 // no content.
201 throw lang::IllegalArgumentException(
202 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
203 "Illegal Content Identifier!" ) ),
204 static_cast< cppu::OWeakObject * >( this ),
205 1 );
207 else
209 throw lang::IllegalArgumentException(
210 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
211 "Unable to obtain document id from model!" ) ),
212 static_cast< cppu::OWeakObject * >( this ),
213 1 );
216 else
218 throw lang::IllegalArgumentException(
219 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
220 "No Document Manager!" ) ),
221 static_cast< cppu::OWeakObject * >( this ),
222 1 );
226 //=========================================================================
228 // interface OfficeDocumentsEventListener
230 //=========================================================================
232 // virtual
233 void ContentProvider::notifyDocumentClosed( const rtl::OUString & rDocId )
235 osl::MutexGuard aGuard( getContentListMutex() );
237 ::ucbhelper::ContentRefList aAllContents;
238 queryExistingContents( aAllContents );
240 ::ucbhelper::ContentRefList::const_iterator it = aAllContents.begin();
241 ::ucbhelper::ContentRefList::const_iterator end = aAllContents.end();
243 // Notify all content objects related to the closed doc.
245 bool bFoundDocumentContent = false;
246 rtl::Reference< Content > xRoot;
248 while ( it != end )
250 Uri aUri( (*it)->getIdentifier()->getContentIdentifier() );
251 OSL_ENSURE( aUri.isValid(),
252 "ContentProvider::notifyDocumentClosed - Invalid URI!" );
254 if ( !bFoundDocumentContent )
256 if ( aUri.isRoot() )
258 xRoot = static_cast< Content * >( (*it).get() );
260 else if ( aUri.isDocument() )
262 if ( aUri.getDocumentId() == rDocId )
264 bFoundDocumentContent = true;
266 // document content will notify removal of child itself;
267 // no need for the root to propagate this.
268 xRoot.clear();
273 if ( aUri.getDocumentId() == rDocId )
275 // Inform content.
276 rtl::Reference< Content > xContent
277 = static_cast< Content * >( (*it).get() );
279 xContent->notifyDocumentClosed();
282 ++it;
285 if ( xRoot.is() )
287 // No document content found for rDocId but root content
288 // instanciated. Root content must announce document removal
289 // to content event listeners.
290 xRoot->notifyChildRemoved( rDocId );
294 //=========================================================================
295 // virtual
296 void ContentProvider::notifyDocumentOpened( const rtl::OUString & rDocId )
298 osl::MutexGuard aGuard( getContentListMutex() );
300 ::ucbhelper::ContentRefList aAllContents;
301 queryExistingContents( aAllContents );
303 ::ucbhelper::ContentRefList::const_iterator it = aAllContents.begin();
304 ::ucbhelper::ContentRefList::const_iterator end = aAllContents.end();
306 // Find root content. If instanciated let it propagate document insertion.
308 while ( it != end )
310 Uri aUri( (*it)->getIdentifier()->getContentIdentifier() );
311 OSL_ENSURE( aUri.isValid(),
312 "ContentProvider::notifyDocumentOpened - Invalid URI!" );
314 if ( aUri.isRoot() )
316 rtl::Reference< Content > xRoot
317 = static_cast< Content * >( (*it).get() );
318 xRoot->notifyChildInserted( rDocId );
320 // Done.
321 break;
324 ++it;
328 //=========================================================================
330 // Non-UNO
332 //=========================================================================
334 uno::Reference< embed::XStorage >
335 ContentProvider::queryStorage( const rtl::OUString & rUri,
336 StorageAccessMode eMode ) const
338 if ( m_xStgElemFac.is() )
342 return m_xStgElemFac->createStorage( rUri, eMode );
344 catch ( embed::InvalidStorageException const & )
346 OSL_FAIL( "Caught InvalidStorageException!" );
348 catch ( lang::IllegalArgumentException const & )
350 OSL_FAIL( "Caught IllegalArgumentException!" );
352 catch ( io::IOException const & )
354 // Okay to happen, for instance when the storage does not exist.
355 //OSL_ENSURE( false, "Caught IOException!" );
357 catch ( embed::StorageWrappedTargetException const & )
359 OSL_FAIL( "Caught embed::StorageWrappedTargetException!" );
362 return uno::Reference< embed::XStorage >();
365 //=========================================================================
366 uno::Reference< embed::XStorage >
367 ContentProvider::queryStorageClone( const rtl::OUString & rUri ) const
369 if ( m_xStgElemFac.is() )
373 Uri aUri( rUri );
374 uno::Reference< embed::XStorage > xParentStorage
375 = m_xStgElemFac->createStorage( aUri.getParentUri(), READ );
376 uno::Reference< embed::XStorage > xStorage
377 = m_xStgElemFac->createTemporaryStorage();
379 xParentStorage->copyStorageElementLastCommitTo(
380 aUri.getDecodedName(), xStorage );
381 return xStorage;
383 catch ( embed::InvalidStorageException const & )
385 OSL_FAIL( "Caught InvalidStorageException!" );
387 catch ( lang::IllegalArgumentException const & )
389 OSL_FAIL( "Caught IllegalArgumentException!" );
391 catch ( io::IOException const & )
393 // Okay to happen, for instance when the storage does not exist.
394 //OSL_ENSURE( false, "Caught IOException!" );
396 catch ( embed::StorageWrappedTargetException const & )
398 OSL_FAIL( "Caught embed::StorageWrappedTargetException!" );
402 return uno::Reference< embed::XStorage >();
405 //=========================================================================
406 uno::Reference< io::XInputStream >
407 ContentProvider::queryInputStream( const rtl::OUString & rUri,
408 const rtl::OUString & rPassword ) const
409 throw ( packages::WrongPasswordException )
411 if ( m_xStgElemFac.is() )
415 return m_xStgElemFac->createInputStream( rUri, rPassword );
417 catch ( embed::InvalidStorageException const & )
419 OSL_FAIL( "Caught InvalidStorageException!" );
421 catch ( lang::IllegalArgumentException const & )
423 OSL_FAIL( "Caught IllegalArgumentException!" );
425 catch ( io::IOException const & )
427 OSL_FAIL( "Caught IOException!" );
429 catch ( embed::StorageWrappedTargetException const & )
431 OSL_FAIL( "Caught embed::StorageWrappedTargetException!" );
433 // catch ( packages::WrongPasswordException const & )
434 // {
435 // // the key provided is wrong; rethrow; to be handled by caller.
436 // throw;
437 // }
439 return uno::Reference< io::XInputStream >();
442 //=========================================================================
443 uno::Reference< io::XOutputStream >
444 ContentProvider::queryOutputStream( const rtl::OUString & rUri,
445 const rtl::OUString & rPassword,
446 bool bTruncate ) const
447 throw ( packages::WrongPasswordException )
449 if ( m_xStgElemFac.is() )
453 return
454 m_xStgElemFac->createOutputStream( rUri, rPassword, bTruncate );
456 catch ( embed::InvalidStorageException const & )
458 OSL_FAIL( "Caught InvalidStorageException!" );
460 catch ( lang::IllegalArgumentException const & )
462 OSL_FAIL( "Caught IllegalArgumentException!" );
464 catch ( io::IOException const & )
466 // Okay to happen, for instance when the storage does not exist.
467 //OSL_ENSURE( false, "Caught IOException!" );
469 catch ( embed::StorageWrappedTargetException const & )
471 OSL_FAIL( "Caught embed::StorageWrappedTargetException!" );
473 // catch ( packages::WrongPasswordException const & )
474 // {
475 // // the key provided is wrong; rethrow; to be handled by caller.
476 // throw;
477 // }
479 return uno::Reference< io::XOutputStream >();
482 //=========================================================================
483 uno::Reference< io::XStream >
484 ContentProvider::queryStream( const rtl::OUString & rUri,
485 const rtl::OUString & rPassword,
486 bool bTruncate ) const
487 throw ( packages::WrongPasswordException )
489 if ( m_xStgElemFac.is() )
493 return m_xStgElemFac->createStream( rUri, rPassword, bTruncate );
495 catch ( embed::InvalidStorageException const & )
497 OSL_FAIL( "Caught InvalidStorageException!" );
499 catch ( lang::IllegalArgumentException const & )
501 OSL_FAIL( "Caught IllegalArgumentException!" );
503 catch ( io::IOException const & )
505 // Okay to happen, for instance when the storage does not exist.
506 //OSL_ENSURE( false, "Caught IOException!" );
508 catch ( embed::StorageWrappedTargetException const & )
510 OSL_FAIL( "Caught embed::StorageWrappedTargetException!" );
512 // catch ( packages::WrongPasswordException const & )
513 // {
514 // // the key provided is wrong; rethrow; to be handled by caller.
515 // throw;
516 // }
518 return uno::Reference< io::XStream >();
521 //=========================================================================
522 bool ContentProvider::queryNamesOfChildren(
523 const rtl::OUString & rUri, uno::Sequence< rtl::OUString > & rNames ) const
525 Uri aUri( rUri );
526 if ( aUri.isRoot() )
528 // special handling for root, which has no storage, but children.
529 if ( m_xDocsMgr.is() )
531 rNames = m_xDocsMgr->queryDocuments();
532 return true;
535 else
537 if ( m_xStgElemFac.is() )
541 uno::Reference< embed::XStorage > xStorage
542 = m_xStgElemFac->createStorage( rUri, READ );
544 OSL_ENSURE( xStorage.is(), "Got no Storage!" );
546 if ( xStorage.is() )
548 uno::Reference< container::XNameAccess > xNA(
549 xStorage, uno::UNO_QUERY );
551 OSL_ENSURE( xNA.is(), "Got no css.container.XNameAccess!" );
552 if ( xNA.is() )
554 rNames = xNA->getElementNames();
555 return true;
559 catch ( embed::InvalidStorageException const & )
561 OSL_FAIL( "Caught InvalidStorageException!" );
563 catch ( lang::IllegalArgumentException const & )
565 OSL_FAIL( "Caught IllegalArgumentException!" );
567 catch ( io::IOException const & )
569 // Okay to happen, for instance if the storage does not exist.
570 //OSL_ENSURE( false, "Caught IOException!" );
572 catch ( embed::StorageWrappedTargetException const & )
574 OSL_FAIL( "Caught embed::StorageWrappedTargetException!" );
578 return false;
581 //=========================================================================
582 rtl::OUString
583 ContentProvider::queryStorageTitle( const rtl::OUString & rUri ) const
585 rtl::OUString aTitle;
587 Uri aUri( rUri );
588 if ( aUri.isRoot() )
590 // always empty.
591 aTitle = rtl::OUString();
593 else if ( aUri.isDocument() )
595 // for documents, title shall not be derived from URL. It shall
596 // be somethimg more 'speaking' than just the document UID.
597 if ( m_xDocsMgr.is() )
598 aTitle = m_xDocsMgr->queryStorageTitle( aUri.getDocumentId() );
600 else
602 // derive title from URL
603 aTitle = aUri.getDecodedName();
606 OSL_ENSURE( !aTitle.isEmpty() || aUri.isRoot(),
607 "ContentProvider::queryStorageTitle - empty title!" );
608 return aTitle;
611 //=========================================================================
612 uno::Reference< frame::XModel >
613 ContentProvider::queryDocumentModel( const rtl::OUString & rUri ) const
615 uno::Reference< frame::XModel > xModel;
617 if ( m_xDocsMgr.is() )
619 Uri aUri( rUri );
620 xModel = m_xDocsMgr->queryDocumentModel( aUri.getDocumentId() );
623 OSL_ENSURE( xModel.is(),
624 "ContentProvider::queryDocumentModel - no model!" );
625 return xModel;
628 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */