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