LibreOffice Module ucb (master)  1
pkgprovider.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 
21 /**************************************************************************
22  TODO
23  **************************************************************************
24 
25  *************************************************************************/
26 
27 #include <cppuhelper/exc_hlp.hxx>
28 #include <cppuhelper/weak.hxx>
31 #include <ucbhelper/macros.hxx>
32 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
33 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
34 #include <com/sun/star/ucb/IllegalIdentifierException.hpp>
35 #include <com/sun/star/uno/XComponentContext.hpp>
36 #include "pkgprovider.hxx"
37 #include "pkgcontent.hxx"
38 #include "pkguri.hxx"
39 #include <unordered_map>
40 
41 using namespace com::sun::star;
42 
43 namespace package_ucp
44 {
45 
46 
47 
48 namespace {
49 
50 class Package : public cppu::OWeakObject,
51  public container::XHierarchicalNameAccess
52 {
54 
55  OUString m_aName;
56  uno::Reference< container::XHierarchicalNameAccess > m_xNA;
58 
59 public:
60  Package( const OUString& rName,
61  const uno::Reference< container::XHierarchicalNameAccess > & xNA,
62  ContentProvider* pOwner )
63  : m_aName( rName ), m_xNA( xNA ), m_pOwner( pOwner ) {}
64  virtual ~Package() override { m_pOwner->removePackage( m_aName ); }
65 
66  // XInterface
67  virtual uno::Any SAL_CALL
68  queryInterface( const uno::Type& aType ) override
69  { return m_xNA->queryInterface( aType ); }
70  virtual void SAL_CALL
71  acquire() noexcept override
72  { OWeakObject::acquire(); }
73  virtual void SAL_CALL
74  release() noexcept override
75  { OWeakObject::release(); }
76 
77  // XHierarchicalNameAccess
78  virtual uno::Any SAL_CALL
79  getByHierarchicalName( const OUString& aName ) override
80  { return m_xNA->getByHierarchicalName( aName ); }
81  virtual sal_Bool SAL_CALL
82  hasByHierarchicalName( const OUString& aName ) override
83  { return m_xNA->hasByHierarchicalName( aName ); }
84 };
85 
86 }
87 
88 class Packages : public std::unordered_map<OUString, Package*> {};
89 
90 }
91 
92 using namespace package_ucp;
93 
94 
95 // ContentProvider Implementation.
97  const uno::Reference< uno::XComponentContext >& rxContext )
98 : ::ucbhelper::ContentProviderImplHelper( rxContext )
99 {
100 }
101 
102 
103 // virtual
105 {
106 }
107 
108 // XInterface methods.
110  noexcept
111 {
112  OWeakObject::acquire();
113 }
114 
116  noexcept
117 {
118  OWeakObject::release();
119 }
120 
121 css::uno::Any SAL_CALL ContentProvider::queryInterface( const css::uno::Type & rType )
122 {
123  css::uno::Any aRet = cppu::queryInterface( rType,
124  static_cast< lang::XTypeProvider* >(this),
125  static_cast< lang::XServiceInfo* >(this),
126  static_cast< ucb::XContentProvider* >(this)
127  );
128  return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
129 }
130 
131 // XTypeProvider methods.
132 
133 
135  lang::XTypeProvider,
136  lang::XServiceInfo,
137  ucb::XContentProvider );
138 
139 
140 // XServiceInfo methods.
141 
142 OUString
144 {
145  return "com.sun.star.comp.ucb.PackageContentProvider";
146 }
147 
148 sal_Bool
150 {
151  return cppu::supportsService(this, s);
152 }
153 
154 css::uno::Sequence< OUString >
156 {
157  return { "com.sun.star.ucb.PackageContentProvider" };
158 }
159 
160 
161 // XContentProvider methods.
162 
163 
164 // virtual
165 uno::Reference< ucb::XContent > SAL_CALL ContentProvider::queryContent(
166  const uno::Reference< ucb::XContentIdentifier >& Identifier )
167 {
168  if ( !Identifier.is() )
169  return uno::Reference< ucb::XContent >();
170 
171  PackageUri aUri( Identifier->getContentIdentifier() );
172  if ( !aUri.isValid() )
173  throw ucb::IllegalIdentifierException();
174 
175  // Create a new identifier for the normalized URL returned by
176  // PackageUri::getUri().
177  uno::Reference< ucb::XContentIdentifier > xId = new ::ucbhelper::ContentIdentifier( aUri.getUri() );
178 
179  osl::MutexGuard aGuard( m_aMutex );
180 
181  // Check, if a content with given id already exists...
182  uno::Reference< ucb::XContent > xContent
183  = queryExistingContent( xId );
184  if ( xContent.is() )
185  return xContent;
186 
187  // Create a new content.
188 
189  xContent = Content::create( m_xContext, this, Identifier ); // not xId!!!
190  registerNewContent( xContent );
191 
192  if ( xContent.is() && !xContent->getIdentifier().is() )
193  throw ucb::IllegalIdentifierException();
194 
195  return xContent;
196 }
197 
198 
199 // Other methods.
200 
201 
202 uno::Reference< container::XHierarchicalNameAccess >
204 {
205  osl::MutexGuard aGuard( m_aMutex );
206 
207  OUString rURL = rURI.getPackage() + rURI.getParam();
208 
209  if ( m_pPackages )
210  {
211  Packages::const_iterator it = m_pPackages->find( rURL );
212  if ( it != m_pPackages->end() )
213  {
214  // Already instantiated. Return package.
215  return (*it).second->m_xNA;
216  }
217  }
218  else
219  m_pPackages.reset( new Packages );
220 
221  // Create new package...
222  uno::Sequence< uno::Any > aArguments( 1 );
223  aArguments[ 0 ] <<= rURL;
224  uno::Reference< container::XHierarchicalNameAccess > xNameAccess;
225  try
226  {
227  xNameAccess.set(
228  m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
229  "com.sun.star.packages.comp.ZipPackage",
230  aArguments, m_xContext ),
231  css::uno::UNO_QUERY_THROW );
232  }
233  catch ( uno::RuntimeException const & )
234  {
235  throw;
236  }
237  catch ( uno::Exception const & e )
238  {
239  css::uno::Any anyEx = cppu::getCaughtException();
240  throw css::lang::WrappedTargetRuntimeException(
241  e.Message, e.Context, anyEx);
242  }
243 
244  rtl::Reference< Package> xPackage = new Package( rURL, xNameAccess, this );
245  (*m_pPackages)[ rURL ] = xPackage.get();
246  return xPackage;
247 }
248 
249 
250 void ContentProvider::removePackage( const OUString & rName )
251 {
252  osl::MutexGuard aGuard( m_aMutex );
253 
254  if ( m_pPackages )
255  {
256  Packages::iterator it = m_pPackages->find( rName );
257  if ( it != m_pPackages->end() )
258  {
259  m_pPackages->erase( it );
260  return;
261  }
262  }
263 }
264 
265 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
267  css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
268 {
269  return cppu::acquire(new ContentProvider(context));
270 }
271 
272 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
const OUString & getParam() const
Definition: pkguri.hxx:71
OUString m_aName
Definition: pkgprovider.cxx:55
virtual void SAL_CALL acquire() noexcept override
void removePackage(const OUString &rName)
std::unique_ptr< Packages > m_pPackages
Definition: pkgprovider.hxx:50
XTYPEPROVIDER_IMPL_3(ContentProvider, lang::XTypeProvider, lang::XServiceInfo, ucb::XContentProvider)
virtual css::uno::Reference< css::ucb::XContent > SAL_CALL queryContent(const css::uno::Reference< css::ucb::XContentIdentifier > &Identifier) override
uno::Reference< container::XHierarchicalNameAccess > m_xNA
Definition: pkgprovider.cxx:56
virtual OUString SAL_CALL getImplementationName() override
Sequence< PropertyValue > aArguments
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * ucb_package_ContentProvider_get_implementation(css::uno::XComponentContext *context, css::uno::Sequence< css::uno::Any > const &)
Any SAL_CALL getCaughtException()
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
static rtl::Reference< Content > create(const css::uno::Reference< css::uno::XComponentContext > &rxContext, ContentProvider *pProvider, const css::uno::Reference< css::ucb::XContentIdentifier > &Identifier)
const OUString & getPackage() const
Definition: pkguri.hxx:62
ContentProvider * m_pOwner
Definition: pkgprovider.cxx:57
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
unsigned char sal_Bool
rtl::Reference< ContentImplHelper > queryExistingContent(const css::uno::Reference< css::ucb::XContentIdentifier > &Identifier)
css::uno::Reference< css::uno::XComponentContext > m_xContext
virtual ~ContentProvider() override
void registerNewContent(const css::uno::Reference< css::ucb::XContent > &xContent)
friend ContentProvider
Definition: pkgprovider.cxx:53
Reference< XContentIdentifier > xId
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType) override
uno::Reference< ucb::XContent > xContent
css::uno::Reference< css::container::XHierarchicalNameAccess > createPackage(const PackageUri &rParam)
css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType, Interface1 *p1)
virtual void SAL_CALL release() noexcept override