1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 /**************************************************************************
23 **************************************************************************
25 *************************************************************************/
27 #include <cppuhelper/exc_hlp.hxx>
28 #include <cppuhelper/weak.hxx>
29 #include <cppuhelper/queryinterface.hxx>
30 #include <ucbhelper/contentidentifier.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"
39 #include <unordered_map>
42 using namespace com::sun::star
;
51 class Package
: public cppu::OWeakObject
,
52 public container::XHierarchicalNameAccess
54 friend ContentProvider
;
57 uno::Reference
< container::XHierarchicalNameAccess
> m_xNA
;
58 ContentProvider
* m_pOwner
;
61 Package( OUString aName
,
62 uno::Reference
< container::XHierarchicalNameAccess
> xNA
,
63 ContentProvider
* pOwner
)
64 : m_aName(std::move( aName
)), m_xNA(std::move( xNA
)), m_pOwner( pOwner
) {}
65 virtual ~Package() override
{ m_pOwner
->removePackage( m_aName
); }
68 virtual uno::Any SAL_CALL
69 queryInterface( const uno::Type
& aType
) override
70 { return m_xNA
->queryInterface( aType
); }
72 acquire() noexcept override
73 { OWeakObject::acquire(); }
75 release() noexcept override
76 { OWeakObject::release(); }
78 // XHierarchicalNameAccess
79 virtual uno::Any SAL_CALL
80 getByHierarchicalName( const OUString
& aName
) override
81 { return m_xNA
->getByHierarchicalName( aName
); }
82 virtual sal_Bool SAL_CALL
83 hasByHierarchicalName( const OUString
& aName
) override
84 { return m_xNA
->hasByHierarchicalName( aName
); }
89 class Packages
: public std::unordered_map
<OUString
, Package
*> {};
93 using namespace package_ucp
;
96 // ContentProvider Implementation.
97 ContentProvider::ContentProvider(
98 const uno::Reference
< uno::XComponentContext
>& rxContext
)
99 : ::ucbhelper::ContentProviderImplHelper( rxContext
)
105 ContentProvider::~ContentProvider()
109 // XInterface methods.
110 void SAL_CALL
ContentProvider::acquire()
113 OWeakObject::acquire();
116 void SAL_CALL
ContentProvider::release()
119 OWeakObject::release();
122 css::uno::Any SAL_CALL
ContentProvider::queryInterface( const css::uno::Type
& rType
)
124 css::uno::Any aRet
= cppu::queryInterface( rType
,
125 static_cast< lang::XTypeProvider
* >(this),
126 static_cast< lang::XServiceInfo
* >(this),
127 static_cast< ucb::XContentProvider
* >(this)
129 return aRet
.hasValue() ? aRet
: OWeakObject::queryInterface( rType
);
132 // XTypeProvider methods.
135 XTYPEPROVIDER_IMPL_3( ContentProvider
,
138 ucb::XContentProvider
);
141 // XServiceInfo methods.
144 ContentProvider::getImplementationName()
146 return "com.sun.star.comp.ucb.PackageContentProvider";
150 ContentProvider::supportsService(const OUString
& s
)
152 return cppu::supportsService(this, s
);
155 css::uno::Sequence
< OUString
>
156 ContentProvider::getSupportedServiceNames()
158 return { "com.sun.star.ucb.PackageContentProvider" };
162 // XContentProvider methods.
166 uno::Reference
< ucb::XContent
> SAL_CALL
ContentProvider::queryContent(
167 const uno::Reference
< ucb::XContentIdentifier
>& Identifier
)
169 if ( !Identifier
.is() )
170 return uno::Reference
< ucb::XContent
>();
172 PackageUri
aUri( Identifier
->getContentIdentifier() );
173 if ( !aUri
.isValid() )
174 throw ucb::IllegalIdentifierException();
176 // Create a new identifier for the normalized URL returned by
177 // PackageUri::getUri().
178 uno::Reference
< ucb::XContentIdentifier
> xId
= new ::ucbhelper::ContentIdentifier( aUri
.getUri() );
180 osl::MutexGuard
aGuard( m_aMutex
);
182 // Check, if a content with given id already exists...
183 uno::Reference
< ucb::XContent
> xContent
184 = queryExistingContent( xId
);
188 // Create a new content.
190 xContent
= Content::create( m_xContext
, this, Identifier
); // not xId!!!
191 registerNewContent( xContent
);
193 if ( xContent
.is() && !xContent
->getIdentifier().is() )
194 throw ucb::IllegalIdentifierException();
203 uno::Reference
< container::XHierarchicalNameAccess
>
204 ContentProvider::createPackage( const PackageUri
& rURI
)
206 osl::MutexGuard
aGuard( m_aMutex
);
208 OUString rURL
= rURI
.getPackage() + rURI
.getParam();
212 Packages::const_iterator it
= m_pPackages
->find( rURL
);
213 if ( it
!= m_pPackages
->end() )
215 // Already instantiated. Return package.
216 return (*it
).second
->m_xNA
;
220 m_pPackages
.reset( new Packages
);
222 // Create new package...
223 uno::Sequence
< uno::Any
> aArguments
{ uno::Any(rURL
) };
224 uno::Reference
< container::XHierarchicalNameAccess
> xNameAccess
;
228 m_xContext
->getServiceManager()->createInstanceWithArgumentsAndContext(
229 "com.sun.star.packages.comp.ZipPackage",
230 aArguments
, m_xContext
),
231 css::uno::UNO_QUERY_THROW
);
233 catch ( uno::RuntimeException
const & )
237 catch ( uno::Exception
const & e
)
239 css::uno::Any anyEx
= cppu::getCaughtException();
240 throw css::lang::WrappedTargetRuntimeException(
241 e
.Message
, e
.Context
, anyEx
);
244 rtl::Reference
< Package
> xPackage
= new Package( rURL
, xNameAccess
, this );
245 (*m_pPackages
)[ rURL
] = xPackage
.get();
250 void ContentProvider::removePackage( const OUString
& rName
)
252 osl::MutexGuard
aGuard( m_aMutex
);
256 Packages::iterator it
= m_pPackages
->find( rName
);
257 if ( it
!= m_pPackages
->end() )
259 m_pPackages
->erase( it
);
265 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
266 ucb_package_ContentProvider_get_implementation(
267 css::uno::XComponentContext
* context
, css::uno::Sequence
<css::uno::Any
> const&)
269 return cppu::acquire(new ContentProvider(context
));
272 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */