1*2722ceddSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*2722ceddSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*2722ceddSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*2722ceddSAndrew Rist  * distributed with this work for additional information
6*2722ceddSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*2722ceddSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*2722ceddSAndrew Rist  * "License"); you may not use this file except in compliance
9*2722ceddSAndrew Rist  * with the License.  You may obtain a copy of the License at
10*2722ceddSAndrew Rist  *
11*2722ceddSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*2722ceddSAndrew Rist  *
13*2722ceddSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*2722ceddSAndrew Rist  * software distributed under the License is distributed on an
15*2722ceddSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*2722ceddSAndrew Rist  * KIND, either express or implied.  See the License for the
17*2722ceddSAndrew Rist  * specific language governing permissions and limitations
18*2722ceddSAndrew Rist  * under the License.
19*2722ceddSAndrew Rist  *
20*2722ceddSAndrew Rist  *************************************************************/
21*2722ceddSAndrew Rist 
22*2722ceddSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_desktop.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include "dp_registry.hrc"
28cdf0e10cSrcweir #include "dp_misc.h"
29cdf0e10cSrcweir #include "dp_resource.h"
30cdf0e10cSrcweir #include "dp_interact.h"
31cdf0e10cSrcweir #include "dp_ucb.h"
32cdf0e10cSrcweir #include "osl/diagnose.h"
33cdf0e10cSrcweir #include "rtl/ustrbuf.hxx"
34cdf0e10cSrcweir #include "rtl/uri.hxx"
35cdf0e10cSrcweir #include "cppuhelper/compbase2.hxx"
36cdf0e10cSrcweir #include "cppuhelper/exc_hlp.hxx"
37cdf0e10cSrcweir #include "comphelper/sequence.hxx"
38cdf0e10cSrcweir #include "ucbhelper/content.hxx"
39cdf0e10cSrcweir #include "com/sun/star/uno/DeploymentException.hpp"
40cdf0e10cSrcweir #include "com/sun/star/lang/DisposedException.hpp"
41cdf0e10cSrcweir #include "com/sun/star/lang/WrappedTargetRuntimeException.hpp"
42cdf0e10cSrcweir #include "com/sun/star/lang/XServiceInfo.hpp"
43cdf0e10cSrcweir #include "com/sun/star/lang/XSingleComponentFactory.hpp"
44cdf0e10cSrcweir #include "com/sun/star/lang/XSingleServiceFactory.hpp"
45cdf0e10cSrcweir #include "com/sun/star/util/XUpdatable.hpp"
46cdf0e10cSrcweir #include "com/sun/star/container/XContentEnumerationAccess.hpp"
47cdf0e10cSrcweir #include "com/sun/star/deployment/PackageRegistryBackend.hpp"
48cdf0e10cSrcweir #include <hash_map>
49cdf0e10cSrcweir #include <set>
50cdf0e10cSrcweir #include <hash_set>
51cdf0e10cSrcweir #include <memory>
52cdf0e10cSrcweir 
53cdf0e10cSrcweir using namespace ::dp_misc;
54cdf0e10cSrcweir using namespace ::com::sun::star;
55cdf0e10cSrcweir using namespace ::com::sun::star::uno;
56cdf0e10cSrcweir using namespace ::com::sun::star::ucb;
57cdf0e10cSrcweir using ::rtl::OUString;
58cdf0e10cSrcweir 
59cdf0e10cSrcweir 
60cdf0e10cSrcweir namespace dp_registry {
61cdf0e10cSrcweir 
62cdf0e10cSrcweir namespace backend {
63cdf0e10cSrcweir namespace bundle {
64cdf0e10cSrcweir Reference<deployment::XPackageRegistry> create(
65cdf0e10cSrcweir     Reference<deployment::XPackageRegistry> const & xRootRegistry,
66cdf0e10cSrcweir     OUString const & context, OUString const & cachePath, bool readOnly,
67cdf0e10cSrcweir     Reference<XComponentContext> const & xComponentContext );
68cdf0e10cSrcweir }
69cdf0e10cSrcweir }
70cdf0e10cSrcweir 
71cdf0e10cSrcweir namespace {
72cdf0e10cSrcweir 
73cdf0e10cSrcweir typedef ::cppu::WeakComponentImplHelper2<
74cdf0e10cSrcweir     deployment::XPackageRegistry, util::XUpdatable > t_helper;
75cdf0e10cSrcweir 
76cdf0e10cSrcweir //==============================================================================
77cdf0e10cSrcweir class PackageRegistryImpl : private MutexHolder, public t_helper
78cdf0e10cSrcweir {
79cdf0e10cSrcweir     struct ci_string_hash {
operator ()dp_registry::__anon93dd4b650111::PackageRegistryImpl::ci_string_hash80cdf0e10cSrcweir         ::std::size_t operator () ( OUString const & str ) const {
81cdf0e10cSrcweir             return str.toAsciiLowerCase().hashCode();
82cdf0e10cSrcweir         }
83cdf0e10cSrcweir     };
84cdf0e10cSrcweir     struct ci_string_equals {
operator ()dp_registry::__anon93dd4b650111::PackageRegistryImpl::ci_string_equals85cdf0e10cSrcweir         bool operator () ( OUString const & str1, OUString const & str2 ) const{
86cdf0e10cSrcweir             return str1.equalsIgnoreAsciiCase( str2 );
87cdf0e10cSrcweir         }
88cdf0e10cSrcweir     };
89cdf0e10cSrcweir     typedef ::std::hash_map<
90cdf0e10cSrcweir         OUString, Reference<deployment::XPackageRegistry>,
91cdf0e10cSrcweir         ci_string_hash, ci_string_equals > t_string2registry;
92cdf0e10cSrcweir     typedef ::std::hash_map<
93cdf0e10cSrcweir         OUString, OUString,
94cdf0e10cSrcweir         ci_string_hash, ci_string_equals > t_string2string;
95cdf0e10cSrcweir     typedef ::std::set<
96cdf0e10cSrcweir         Reference<deployment::XPackageRegistry> > t_registryset;
97cdf0e10cSrcweir 
98cdf0e10cSrcweir     t_string2registry m_mediaType2backend;
99cdf0e10cSrcweir     t_string2string m_filter2mediaType;
100cdf0e10cSrcweir     t_registryset m_ambiguousBackends;
101cdf0e10cSrcweir     t_registryset m_allBackends;
102cdf0e10cSrcweir     ::std::vector< Reference<deployment::XPackageTypeInfo> > m_typesInfos;
103cdf0e10cSrcweir 
104cdf0e10cSrcweir     void insertBackend(
105cdf0e10cSrcweir         Reference<deployment::XPackageRegistry> const & xBackend );
106cdf0e10cSrcweir 
107cdf0e10cSrcweir protected:
108cdf0e10cSrcweir     inline void check();
109cdf0e10cSrcweir     virtual void SAL_CALL disposing();
110cdf0e10cSrcweir 
111cdf0e10cSrcweir     virtual ~PackageRegistryImpl();
PackageRegistryImpl()112cdf0e10cSrcweir     PackageRegistryImpl() : t_helper( getMutex() ) {}
113cdf0e10cSrcweir 
114cdf0e10cSrcweir 
115cdf0e10cSrcweir public:
116cdf0e10cSrcweir     static Reference<deployment::XPackageRegistry> create(
117cdf0e10cSrcweir         OUString const & context,
118cdf0e10cSrcweir         OUString const & cachePath, bool readOnly,
119cdf0e10cSrcweir         Reference<XComponentContext> const & xComponentContext );
120cdf0e10cSrcweir 
121cdf0e10cSrcweir     // XUpdatable
122cdf0e10cSrcweir     virtual void SAL_CALL update() throw (RuntimeException);
123cdf0e10cSrcweir 
124cdf0e10cSrcweir     // XPackageRegistry
125cdf0e10cSrcweir     virtual Reference<deployment::XPackage> SAL_CALL bindPackage(
126cdf0e10cSrcweir         OUString const & url, OUString const & mediaType, sal_Bool bRemoved,
127cdf0e10cSrcweir         OUString const & identifier, Reference<XCommandEnvironment> const & xCmdEnv )
128cdf0e10cSrcweir         throw (deployment::DeploymentException,
129cdf0e10cSrcweir                deployment::InvalidRemovedParameterException,
130cdf0e10cSrcweir                CommandFailedException,
131cdf0e10cSrcweir                lang::IllegalArgumentException, RuntimeException);
132cdf0e10cSrcweir     virtual Sequence< Reference<deployment::XPackageTypeInfo> > SAL_CALL
133cdf0e10cSrcweir     getSupportedPackageTypes() throw (RuntimeException);
134cdf0e10cSrcweir     virtual void SAL_CALL packageRemoved(OUString const & url, OUString const & mediaType)
135cdf0e10cSrcweir                 throw (deployment::DeploymentException,
136cdf0e10cSrcweir                 RuntimeException);
137cdf0e10cSrcweir 
138cdf0e10cSrcweir };
139cdf0e10cSrcweir 
140cdf0e10cSrcweir //______________________________________________________________________________
check()141cdf0e10cSrcweir inline void PackageRegistryImpl::check()
142cdf0e10cSrcweir {
143cdf0e10cSrcweir     ::osl::MutexGuard guard( getMutex() );
144cdf0e10cSrcweir     if (rBHelper.bInDispose || rBHelper.bDisposed) {
145cdf0e10cSrcweir         throw lang::DisposedException(
146cdf0e10cSrcweir             OUSTR("PackageRegistry instance has already been disposed!"),
147cdf0e10cSrcweir             static_cast<OWeakObject *>(this) );
148cdf0e10cSrcweir     }
149cdf0e10cSrcweir }
150cdf0e10cSrcweir 
151cdf0e10cSrcweir //______________________________________________________________________________
disposing()152cdf0e10cSrcweir void PackageRegistryImpl::disposing()
153cdf0e10cSrcweir {
154cdf0e10cSrcweir     // dispose all backends:
155cdf0e10cSrcweir     t_registryset::const_iterator iPos( m_allBackends.begin() );
156cdf0e10cSrcweir     t_registryset::const_iterator const iEnd( m_allBackends.end() );
157cdf0e10cSrcweir     for ( ; iPos != iEnd; ++iPos ) {
158cdf0e10cSrcweir         try_dispose( *iPos );
159cdf0e10cSrcweir     }
160cdf0e10cSrcweir     m_mediaType2backend = t_string2registry();
161cdf0e10cSrcweir     m_ambiguousBackends = t_registryset();
162cdf0e10cSrcweir     m_allBackends = t_registryset();
163cdf0e10cSrcweir 
164cdf0e10cSrcweir     t_helper::disposing();
165cdf0e10cSrcweir }
166cdf0e10cSrcweir 
167cdf0e10cSrcweir //______________________________________________________________________________
~PackageRegistryImpl()168cdf0e10cSrcweir PackageRegistryImpl::~PackageRegistryImpl()
169cdf0e10cSrcweir {
170cdf0e10cSrcweir }
171cdf0e10cSrcweir 
172cdf0e10cSrcweir //______________________________________________________________________________
normalizeMediaType(OUString const & mediaType)173cdf0e10cSrcweir OUString normalizeMediaType( OUString const & mediaType )
174cdf0e10cSrcweir {
175cdf0e10cSrcweir     ::rtl::OUStringBuffer buf;
176cdf0e10cSrcweir     sal_Int32 index = 0;
177cdf0e10cSrcweir     for (;;) {
178cdf0e10cSrcweir         buf.append( mediaType.getToken( 0, '/', index ).trim() );
179cdf0e10cSrcweir         if (index < 0)
180cdf0e10cSrcweir             break;
181cdf0e10cSrcweir         buf.append( static_cast< sal_Unicode >('/') );
182cdf0e10cSrcweir     }
183cdf0e10cSrcweir     return buf.makeStringAndClear();
184cdf0e10cSrcweir }
185cdf0e10cSrcweir 
186cdf0e10cSrcweir //______________________________________________________________________________
187cdf0e10cSrcweir 
packageRemoved(::rtl::OUString const & url,::rtl::OUString const & mediaType)188cdf0e10cSrcweir void PackageRegistryImpl::packageRemoved(
189cdf0e10cSrcweir     ::rtl::OUString const & url, ::rtl::OUString const & mediaType)
190cdf0e10cSrcweir     throw (css::deployment::DeploymentException,
191cdf0e10cSrcweir            css::uno::RuntimeException)
192cdf0e10cSrcweir {
193cdf0e10cSrcweir     const t_string2registry::const_iterator i =
194cdf0e10cSrcweir         m_mediaType2backend.find(mediaType);
195cdf0e10cSrcweir 
196cdf0e10cSrcweir     if (i != m_mediaType2backend.end())
197cdf0e10cSrcweir     {
198cdf0e10cSrcweir         i->second->packageRemoved(url, mediaType);
199cdf0e10cSrcweir     }
200cdf0e10cSrcweir }
201cdf0e10cSrcweir 
insertBackend(Reference<deployment::XPackageRegistry> const & xBackend)202cdf0e10cSrcweir void PackageRegistryImpl::insertBackend(
203cdf0e10cSrcweir     Reference<deployment::XPackageRegistry> const & xBackend )
204cdf0e10cSrcweir {
205cdf0e10cSrcweir     m_allBackends.insert( xBackend );
206cdf0e10cSrcweir     typedef ::std::hash_set<OUString, ::rtl::OUStringHash> t_stringset;
207cdf0e10cSrcweir     t_stringset ambiguousFilters;
208cdf0e10cSrcweir 
209cdf0e10cSrcweir     const Sequence< Reference<deployment::XPackageTypeInfo> > packageTypes(
210cdf0e10cSrcweir         xBackend->getSupportedPackageTypes() );
211cdf0e10cSrcweir     for ( sal_Int32 pos = 0; pos < packageTypes.getLength(); ++pos )
212cdf0e10cSrcweir     {
213cdf0e10cSrcweir         Reference<deployment::XPackageTypeInfo> const & xPackageType =
214cdf0e10cSrcweir             packageTypes[ pos ];
215cdf0e10cSrcweir         m_typesInfos.push_back( xPackageType );
216cdf0e10cSrcweir 
217cdf0e10cSrcweir         const OUString mediaType( normalizeMediaType(
218cdf0e10cSrcweir                                       xPackageType->getMediaType() ) );
219cdf0e10cSrcweir         ::std::pair<t_string2registry::iterator, bool> mb_insertion(
220cdf0e10cSrcweir             m_mediaType2backend.insert( t_string2registry::value_type(
221cdf0e10cSrcweir                                             mediaType, xBackend ) ) );
222cdf0e10cSrcweir         if (mb_insertion.second)
223cdf0e10cSrcweir         {
224cdf0e10cSrcweir             // add parameterless media-type, too:
225cdf0e10cSrcweir             sal_Int32 semi = mediaType.indexOf( ';' );
226cdf0e10cSrcweir             if (semi >= 0) {
227cdf0e10cSrcweir                 m_mediaType2backend.insert(
228cdf0e10cSrcweir                     t_string2registry::value_type(
229cdf0e10cSrcweir                         mediaType.copy( 0, semi ), xBackend ) );
230cdf0e10cSrcweir             }
231cdf0e10cSrcweir             const OUString fileFilter( xPackageType->getFileFilter() );
232cdf0e10cSrcweir             //The package backend shall also be called to determine the mediatype
233cdf0e10cSrcweir             //(XPackageRegistry.bindPackage) when the URL points to a directory.
234cdf0e10cSrcweir             const bool bExtension = mediaType.equals(OUSTR("application/vnd.sun.star.package-bundle"));
235cdf0e10cSrcweir             if (fileFilter.getLength() == 0 ||
236cdf0e10cSrcweir                 fileFilter.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("*.*") ) ||
237cdf0e10cSrcweir                 fileFilter.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("*") ) ||
238cdf0e10cSrcweir                 bExtension)
239cdf0e10cSrcweir             {
240cdf0e10cSrcweir                 m_ambiguousBackends.insert( xBackend );
241cdf0e10cSrcweir             }
242cdf0e10cSrcweir             else
243cdf0e10cSrcweir             {
244cdf0e10cSrcweir                 sal_Int32 nIndex = 0;
245cdf0e10cSrcweir                 do {
246cdf0e10cSrcweir                     OUString token( fileFilter.getToken( 0, ';', nIndex ) );
247cdf0e10cSrcweir                     if (token.matchAsciiL( RTL_CONSTASCII_STRINGPARAM("*.") ))
248cdf0e10cSrcweir                         token = token.copy( 1 );
249cdf0e10cSrcweir                     if (token.getLength() == 0)
250cdf0e10cSrcweir                         continue;
251cdf0e10cSrcweir                     // mark any further wildcards ambig:
252cdf0e10cSrcweir                     bool ambig = (token.indexOf('*') >= 0 ||
253cdf0e10cSrcweir                                   token.indexOf('?') >= 0);
254cdf0e10cSrcweir                     if (! ambig) {
255cdf0e10cSrcweir                         ::std::pair<t_string2string::iterator, bool> ins(
256cdf0e10cSrcweir                             m_filter2mediaType.insert(
257cdf0e10cSrcweir                                 t_string2string::value_type(
258cdf0e10cSrcweir                                     token, mediaType ) ) );
259cdf0e10cSrcweir                         ambig = !ins.second;
260cdf0e10cSrcweir                         if (ambig) {
261cdf0e10cSrcweir                             // filter has already been in: add previously
262cdf0e10cSrcweir                             // added backend to ambig set
263cdf0e10cSrcweir                             const t_string2registry::const_iterator iFind(
264cdf0e10cSrcweir                                 m_mediaType2backend.find(
265cdf0e10cSrcweir                                     /* media-type of pr. added backend */
266cdf0e10cSrcweir                                     ins.first->second ) );
267cdf0e10cSrcweir                             OSL_ASSERT(
268cdf0e10cSrcweir                                 iFind != m_mediaType2backend.end() );
269cdf0e10cSrcweir                             if (iFind != m_mediaType2backend.end())
270cdf0e10cSrcweir                                 m_ambiguousBackends.insert( iFind->second );
271cdf0e10cSrcweir                         }
272cdf0e10cSrcweir                     }
273cdf0e10cSrcweir                     if (ambig) {
274cdf0e10cSrcweir                         m_ambiguousBackends.insert( xBackend );
275cdf0e10cSrcweir                         // mark filter to be removed later from filters map:
276cdf0e10cSrcweir                         ambiguousFilters.insert( token );
277cdf0e10cSrcweir                     }
278cdf0e10cSrcweir                 }
279cdf0e10cSrcweir                 while (nIndex >= 0);
280cdf0e10cSrcweir             }
281cdf0e10cSrcweir         }
282cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 0
283cdf0e10cSrcweir         else {
284cdf0e10cSrcweir             ::rtl::OUStringBuffer buf;
285cdf0e10cSrcweir             buf.appendAscii(
286cdf0e10cSrcweir                 RTL_CONSTASCII_STRINGPARAM(
287cdf0e10cSrcweir                     "more than one PackageRegistryBackend for "
288cdf0e10cSrcweir                     "media-type=\"") );
289cdf0e10cSrcweir             buf.append( mediaType );
290cdf0e10cSrcweir             buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\" => ") );
291cdf0e10cSrcweir             buf.append( Reference<lang::XServiceInfo>(
292cdf0e10cSrcweir                             xBackend, UNO_QUERY_THROW )->
293cdf0e10cSrcweir                         getImplementationName() );
294cdf0e10cSrcweir             buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\"!") );
295cdf0e10cSrcweir             OSL_ENSURE( 0, ::rtl::OUStringToOString(
296cdf0e10cSrcweir                             buf.makeStringAndClear(),
297cdf0e10cSrcweir                             RTL_TEXTENCODING_UTF8 ) );
298cdf0e10cSrcweir         }
299cdf0e10cSrcweir #endif
300cdf0e10cSrcweir     }
301cdf0e10cSrcweir 
302cdf0e10cSrcweir     // cut out ambiguous filters:
303cdf0e10cSrcweir     t_stringset::const_iterator iPos( ambiguousFilters.begin() );
304cdf0e10cSrcweir     const t_stringset::const_iterator iEnd( ambiguousFilters.end() );
305cdf0e10cSrcweir     for ( ; iPos != iEnd; ++iPos ) {
306cdf0e10cSrcweir         m_filter2mediaType.erase( *iPos );
307cdf0e10cSrcweir     }
308cdf0e10cSrcweir }
309cdf0e10cSrcweir 
310cdf0e10cSrcweir //______________________________________________________________________________
create(OUString const & context,OUString const & cachePath,bool readOnly,Reference<XComponentContext> const & xComponentContext)311cdf0e10cSrcweir Reference<deployment::XPackageRegistry> PackageRegistryImpl::create(
312cdf0e10cSrcweir     OUString const & context,
313cdf0e10cSrcweir     OUString const & cachePath, bool readOnly,
314cdf0e10cSrcweir     Reference<XComponentContext> const & xComponentContext )
315cdf0e10cSrcweir {
316cdf0e10cSrcweir     PackageRegistryImpl * that = new PackageRegistryImpl;
317cdf0e10cSrcweir     Reference<deployment::XPackageRegistry> xRet(that);
318cdf0e10cSrcweir 
319cdf0e10cSrcweir     // auto-detect all registered package registries:
320cdf0e10cSrcweir     Reference<container::XEnumeration> xEnum(
321cdf0e10cSrcweir         Reference<container::XContentEnumerationAccess>(
322cdf0e10cSrcweir             xComponentContext->getServiceManager(),
323cdf0e10cSrcweir             UNO_QUERY_THROW )->createContentEnumeration(
324cdf0e10cSrcweir                 OUSTR("com.sun.star.deployment.PackageRegistryBackend") ) );
325cdf0e10cSrcweir     if (xEnum.is())
326cdf0e10cSrcweir     {
327cdf0e10cSrcweir         while (xEnum->hasMoreElements())
328cdf0e10cSrcweir         {
329cdf0e10cSrcweir             Any element( xEnum->nextElement() );
330cdf0e10cSrcweir             Sequence<Any> registryArgs(
331cdf0e10cSrcweir                 cachePath.getLength() == 0 ? 1 : 3 );
332cdf0e10cSrcweir             registryArgs[ 0 ] <<= context;
333cdf0e10cSrcweir             if (cachePath.getLength() > 0)
334cdf0e10cSrcweir             {
335cdf0e10cSrcweir                 Reference<lang::XServiceInfo> xServiceInfo(
336cdf0e10cSrcweir                     element, UNO_QUERY_THROW );
337cdf0e10cSrcweir                 OUString registryCachePath(
338cdf0e10cSrcweir                     makeURL( cachePath,
339cdf0e10cSrcweir                              ::rtl::Uri::encode(
340cdf0e10cSrcweir                                  xServiceInfo->getImplementationName(),
341cdf0e10cSrcweir                                  rtl_UriCharClassPchar,
342cdf0e10cSrcweir                                  rtl_UriEncodeIgnoreEscapes,
343cdf0e10cSrcweir                                  RTL_TEXTENCODING_UTF8 ) ) );
344cdf0e10cSrcweir                 registryArgs[ 1 ] <<= registryCachePath;
345cdf0e10cSrcweir                 registryArgs[ 2 ] <<= readOnly;
346cdf0e10cSrcweir                 if (! readOnly)
347cdf0e10cSrcweir                     create_folder( 0, registryCachePath,
348cdf0e10cSrcweir                                    Reference<XCommandEnvironment>() );
349cdf0e10cSrcweir             }
350cdf0e10cSrcweir 
351cdf0e10cSrcweir             Reference<deployment::XPackageRegistry> xBackend;
352cdf0e10cSrcweir             Reference<lang::XSingleComponentFactory> xFac( element, UNO_QUERY );
353cdf0e10cSrcweir             if (xFac.is()) {
354cdf0e10cSrcweir                 xBackend.set(
355cdf0e10cSrcweir                     xFac->createInstanceWithArgumentsAndContext(
356cdf0e10cSrcweir                         registryArgs, xComponentContext ), UNO_QUERY );
357cdf0e10cSrcweir             }
358cdf0e10cSrcweir             else {
359cdf0e10cSrcweir                 Reference<lang::XSingleServiceFactory> xSingleServiceFac(
360cdf0e10cSrcweir                     element, UNO_QUERY_THROW );
361cdf0e10cSrcweir                 xBackend.set(
362cdf0e10cSrcweir                     xSingleServiceFac->createInstanceWithArguments(
363cdf0e10cSrcweir                         registryArgs ), UNO_QUERY );
364cdf0e10cSrcweir             }
365cdf0e10cSrcweir             if (! xBackend.is()) {
366cdf0e10cSrcweir                 throw DeploymentException(
367cdf0e10cSrcweir                     OUSTR("cannot instantiate PackageRegistryBackend service: ")
368cdf0e10cSrcweir                     + Reference<lang::XServiceInfo>(
369cdf0e10cSrcweir                         element, UNO_QUERY_THROW )->getImplementationName(),
370cdf0e10cSrcweir                     static_cast<OWeakObject *>(that) );
371cdf0e10cSrcweir             }
372cdf0e10cSrcweir 
373cdf0e10cSrcweir             that->insertBackend( xBackend );
374cdf0e10cSrcweir         }
375cdf0e10cSrcweir     }
376cdf0e10cSrcweir 
377cdf0e10cSrcweir     // Insert bundle back-end.
378cdf0e10cSrcweir     // Always register as last, because we want to add extensions also as folders
379cdf0e10cSrcweir     // and as a default we accept every folder, which was not recognized by the other
380cdf0e10cSrcweir     // backends.
381cdf0e10cSrcweir     Reference<deployment::XPackageRegistry> extensionBackend =
382cdf0e10cSrcweir         ::dp_registry::backend::bundle::create(
383cdf0e10cSrcweir             that, context, cachePath, readOnly, xComponentContext);
384cdf0e10cSrcweir     that->insertBackend(extensionBackend);
385cdf0e10cSrcweir 
386cdf0e10cSrcweir     Reference<lang::XServiceInfo> xServiceInfo(
387cdf0e10cSrcweir         extensionBackend, UNO_QUERY_THROW );
388cdf0e10cSrcweir 
389cdf0e10cSrcweir     OSL_ASSERT(xServiceInfo.is());
390cdf0e10cSrcweir     OUString registryCachePath(
391cdf0e10cSrcweir         makeURL( cachePath,
392cdf0e10cSrcweir                  ::rtl::Uri::encode(
393cdf0e10cSrcweir                      xServiceInfo->getImplementationName(),
394cdf0e10cSrcweir                      rtl_UriCharClassPchar,
395cdf0e10cSrcweir                      rtl_UriEncodeIgnoreEscapes,
396cdf0e10cSrcweir                      RTL_TEXTENCODING_UTF8 ) ) );
397cdf0e10cSrcweir     create_folder( 0, registryCachePath, Reference<XCommandEnvironment>());
398cdf0e10cSrcweir 
399cdf0e10cSrcweir 
400cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
401cdf0e10cSrcweir     // dump tables:
402cdf0e10cSrcweir     {
403cdf0e10cSrcweir         t_registryset allBackends;
404cdf0e10cSrcweir         dp_misc::TRACE("> [dp_registry.cxx] media-type detection:\n\n" );
405cdf0e10cSrcweir         for ( t_string2string::const_iterator iPos(
406cdf0e10cSrcweir                   that->m_filter2mediaType.begin() );
407cdf0e10cSrcweir               iPos != that->m_filter2mediaType.end(); ++iPos )
408cdf0e10cSrcweir         {
409cdf0e10cSrcweir             ::rtl::OUStringBuffer buf;
410cdf0e10cSrcweir             buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("extension \"") );
411cdf0e10cSrcweir             buf.append( iPos->first );
412cdf0e10cSrcweir             buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(
413cdf0e10cSrcweir                                  "\" maps to media-type \"") );
414cdf0e10cSrcweir             buf.append( iPos->second );
415cdf0e10cSrcweir             buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(
416cdf0e10cSrcweir                                  "\" maps to backend ") );
417cdf0e10cSrcweir             const Reference<deployment::XPackageRegistry> xBackend(
418cdf0e10cSrcweir                 that->m_mediaType2backend.find( iPos->second )->second );
419cdf0e10cSrcweir             allBackends.insert( xBackend );
420cdf0e10cSrcweir             buf.append( Reference<lang::XServiceInfo>(
421cdf0e10cSrcweir                             xBackend, UNO_QUERY_THROW )
422cdf0e10cSrcweir                         ->getImplementationName() );
423cdf0e10cSrcweir             dp_misc::writeConsole( buf.makeStringAndClear() + OUSTR("\n"));
424cdf0e10cSrcweir         }
425cdf0e10cSrcweir         dp_misc::TRACE( "> [dp_registry.cxx] ambiguous backends:\n\n" );
426cdf0e10cSrcweir         for ( t_registryset::const_iterator iPos(
427cdf0e10cSrcweir                   that->m_ambiguousBackends.begin() );
428cdf0e10cSrcweir               iPos != that->m_ambiguousBackends.end(); ++iPos )
429cdf0e10cSrcweir         {
430cdf0e10cSrcweir             ::rtl::OUStringBuffer buf;
431cdf0e10cSrcweir             buf.append(
432cdf0e10cSrcweir                 Reference<lang::XServiceInfo>(
433cdf0e10cSrcweir                     *iPos, UNO_QUERY_THROW )->getImplementationName() );
434cdf0e10cSrcweir             buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(": ") );
435cdf0e10cSrcweir             const Sequence< Reference<deployment::XPackageTypeInfo> > types(
436cdf0e10cSrcweir                 (*iPos)->getSupportedPackageTypes() );
437cdf0e10cSrcweir             for ( sal_Int32 pos = 0; pos < types.getLength(); ++pos ) {
438cdf0e10cSrcweir                 Reference<deployment::XPackageTypeInfo> const & xInfo =
439cdf0e10cSrcweir                     types[ pos ];
440cdf0e10cSrcweir                 buf.append( xInfo->getMediaType() );
441cdf0e10cSrcweir                 const OUString filter( xInfo->getFileFilter() );
442cdf0e10cSrcweir                 if (filter.getLength() > 0) {
443cdf0e10cSrcweir                     buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" (") );
444cdf0e10cSrcweir                     buf.append( filter );
445cdf0e10cSrcweir                     buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(")") );
446cdf0e10cSrcweir                 }
447cdf0e10cSrcweir                 if (pos < (types.getLength() - 1))
448cdf0e10cSrcweir                     buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", ") );
449cdf0e10cSrcweir             }
450cdf0e10cSrcweir             dp_misc::TRACE(buf.makeStringAndClear() + OUSTR("\n\n"));
451cdf0e10cSrcweir         }
452cdf0e10cSrcweir         allBackends.insert( that->m_ambiguousBackends.begin(),
453cdf0e10cSrcweir                             that->m_ambiguousBackends.end() );
454cdf0e10cSrcweir         OSL_ASSERT( allBackends == that->m_allBackends );
455cdf0e10cSrcweir     }
456cdf0e10cSrcweir #endif
457cdf0e10cSrcweir 
458cdf0e10cSrcweir     return xRet;
459cdf0e10cSrcweir }
460cdf0e10cSrcweir 
461cdf0e10cSrcweir // XUpdatable: broadcast to backends
462cdf0e10cSrcweir //______________________________________________________________________________
update()463cdf0e10cSrcweir void PackageRegistryImpl::update() throw (RuntimeException)
464cdf0e10cSrcweir {
465cdf0e10cSrcweir     check();
466cdf0e10cSrcweir     t_registryset::const_iterator iPos( m_allBackends.begin() );
467cdf0e10cSrcweir     const t_registryset::const_iterator iEnd( m_allBackends.end() );
468cdf0e10cSrcweir     for ( ; iPos != iEnd; ++iPos ) {
469cdf0e10cSrcweir         const Reference<util::XUpdatable> xUpdatable( *iPos, UNO_QUERY );
470cdf0e10cSrcweir         if (xUpdatable.is())
471cdf0e10cSrcweir             xUpdatable->update();
472cdf0e10cSrcweir     }
473cdf0e10cSrcweir }
474cdf0e10cSrcweir 
475cdf0e10cSrcweir // XPackageRegistry
476cdf0e10cSrcweir //______________________________________________________________________________
bindPackage(OUString const & url,OUString const & mediaType_,sal_Bool bRemoved,OUString const & identifier,Reference<XCommandEnvironment> const & xCmdEnv)477cdf0e10cSrcweir Reference<deployment::XPackage> PackageRegistryImpl::bindPackage(
478cdf0e10cSrcweir     OUString const & url, OUString const & mediaType_, sal_Bool bRemoved,
479cdf0e10cSrcweir     OUString const & identifier, Reference<XCommandEnvironment> const & xCmdEnv )
480cdf0e10cSrcweir     throw (deployment::DeploymentException, deployment::InvalidRemovedParameterException,
481cdf0e10cSrcweir            CommandFailedException,
482cdf0e10cSrcweir            lang::IllegalArgumentException, RuntimeException)
483cdf0e10cSrcweir {
484cdf0e10cSrcweir     check();
485cdf0e10cSrcweir     OUString mediaType(mediaType_);
486cdf0e10cSrcweir     if (mediaType.getLength() == 0)
487cdf0e10cSrcweir     {
488cdf0e10cSrcweir         ::ucbhelper::Content ucbContent;
489cdf0e10cSrcweir         if (create_ucb_content(
490cdf0e10cSrcweir                 &ucbContent, url, xCmdEnv, false /* no throw */ )
491cdf0e10cSrcweir                 && !ucbContent.isFolder())
492cdf0e10cSrcweir         {
493cdf0e10cSrcweir             OUString title( ucbContent.getPropertyValue(
494cdf0e10cSrcweir                                 StrTitle::get() ).get<OUString>() );
495cdf0e10cSrcweir             for (;;)
496cdf0e10cSrcweir             {
497cdf0e10cSrcweir                 const t_string2string::const_iterator iFind(
498cdf0e10cSrcweir                     m_filter2mediaType.find(title) );
499cdf0e10cSrcweir                 if (iFind != m_filter2mediaType.end()) {
500cdf0e10cSrcweir                     mediaType = iFind->second;
501cdf0e10cSrcweir                     break;
502cdf0e10cSrcweir                 }
503cdf0e10cSrcweir                 sal_Int32 point = title.indexOf( '.', 1 /* consume . */ );
504cdf0e10cSrcweir                 if (point < 0)
505cdf0e10cSrcweir                     break;
506cdf0e10cSrcweir                 title = title.copy(point);
507cdf0e10cSrcweir             }
508cdf0e10cSrcweir         }
509cdf0e10cSrcweir     }
510cdf0e10cSrcweir     if (mediaType.getLength() == 0)
511cdf0e10cSrcweir     {
512cdf0e10cSrcweir         // try ambiguous backends:
513cdf0e10cSrcweir         t_registryset::const_iterator iPos( m_ambiguousBackends.begin() );
514cdf0e10cSrcweir         const t_registryset::const_iterator iEnd( m_ambiguousBackends.end() );
515cdf0e10cSrcweir         for ( ; iPos != iEnd; ++iPos )
516cdf0e10cSrcweir         {
517cdf0e10cSrcweir             try {
518cdf0e10cSrcweir                 return (*iPos)->bindPackage( url, mediaType, bRemoved,
519cdf0e10cSrcweir                     identifier, xCmdEnv );
520cdf0e10cSrcweir             }
521cdf0e10cSrcweir             catch (lang::IllegalArgumentException &) {
522cdf0e10cSrcweir             }
523cdf0e10cSrcweir         }
524cdf0e10cSrcweir         throw lang::IllegalArgumentException(
525cdf0e10cSrcweir             getResourceString(RID_STR_CANNOT_DETECT_MEDIA_TYPE) + url,
526cdf0e10cSrcweir             static_cast<OWeakObject *>(this), static_cast<sal_Int16>(-1) );
527cdf0e10cSrcweir     }
528cdf0e10cSrcweir     else
529cdf0e10cSrcweir     {
530cdf0e10cSrcweir         // get backend by media-type:
531cdf0e10cSrcweir         t_string2registry::const_iterator iFind(
532cdf0e10cSrcweir             m_mediaType2backend.find( normalizeMediaType(mediaType) ) );
533cdf0e10cSrcweir         if (iFind == m_mediaType2backend.end()) {
534cdf0e10cSrcweir             // xxx todo: more sophisticated media-type argument parsing...
535cdf0e10cSrcweir             sal_Int32 q = mediaType.indexOf( ';' );
536cdf0e10cSrcweir             if (q >= 0) {
537cdf0e10cSrcweir                 iFind = m_mediaType2backend.find(
538cdf0e10cSrcweir                     normalizeMediaType(
539cdf0e10cSrcweir                         // cut parameters:
540cdf0e10cSrcweir                         mediaType.copy( 0, q ) ) );
541cdf0e10cSrcweir             }
542cdf0e10cSrcweir         }
543cdf0e10cSrcweir         if (iFind == m_mediaType2backend.end()) {
544cdf0e10cSrcweir             throw lang::IllegalArgumentException(
545cdf0e10cSrcweir                 getResourceString(RID_STR_UNSUPPORTED_MEDIA_TYPE) + mediaType,
546cdf0e10cSrcweir                 static_cast<OWeakObject *>(this), static_cast<sal_Int16>(-1) );
547cdf0e10cSrcweir         }
548cdf0e10cSrcweir         return iFind->second->bindPackage( url, mediaType, bRemoved,
549cdf0e10cSrcweir             identifier, xCmdEnv );
550cdf0e10cSrcweir     }
551cdf0e10cSrcweir }
552cdf0e10cSrcweir 
553cdf0e10cSrcweir //______________________________________________________________________________
554cdf0e10cSrcweir Sequence< Reference<deployment::XPackageTypeInfo> >
getSupportedPackageTypes()555cdf0e10cSrcweir PackageRegistryImpl::getSupportedPackageTypes() throw (RuntimeException)
556cdf0e10cSrcweir {
557cdf0e10cSrcweir     return comphelper::containerToSequence(m_typesInfos);
558cdf0e10cSrcweir }
559cdf0e10cSrcweir } // anon namespace
560cdf0e10cSrcweir 
561cdf0e10cSrcweir //==============================================================================
create(OUString const & context,OUString const & cachePath,bool readOnly,Reference<XComponentContext> const & xComponentContext)562cdf0e10cSrcweir Reference<deployment::XPackageRegistry> SAL_CALL create(
563cdf0e10cSrcweir     OUString const & context,
564cdf0e10cSrcweir     OUString const & cachePath, bool readOnly,
565cdf0e10cSrcweir     Reference<XComponentContext> const & xComponentContext )
566cdf0e10cSrcweir {
567cdf0e10cSrcweir     return PackageRegistryImpl::create(
568cdf0e10cSrcweir         context, cachePath, readOnly, xComponentContext );
569cdf0e10cSrcweir }
570cdf0e10cSrcweir 
571cdf0e10cSrcweir } // namespace dp_registry
572cdf0e10cSrcweir 
573