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