Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include "dp_package.hrc"
22 : #include "dp_backend.h"
23 : #include "dp_ucb.h"
24 : #include "dp_interact.h"
25 : #include "dp_dependencies.hxx"
26 : #include "dp_platform.hxx"
27 : #include "dp_descriptioninfoset.hxx"
28 : #include "dp_identifier.hxx"
29 : #include "rtl/uri.hxx"
30 : #include "cppuhelper/exc_hlp.hxx"
31 : #include "cppuhelper/implbase1.hxx"
32 : #include "cppuhelper/supportsservice.hxx"
33 : #include "ucbhelper/content.hxx"
34 : #include "svl/inettype.hxx"
35 : #include "comphelper/anytostring.hxx"
36 : #include "comphelper/makesequence.hxx"
37 : #include "comphelper/sequence.hxx"
38 : #include "com/sun/star/lang/WrappedTargetException.hpp"
39 : #include "com/sun/star/lang/XServiceInfo.hpp"
40 : #include "com/sun/star/beans/UnknownPropertyException.hpp"
41 : #include "com/sun/star/graphic/XGraphic.hpp"
42 : #include "com/sun/star/graphic/GraphicProvider.hpp"
43 : #include "com/sun/star/graphic/XGraphicProvider.hpp"
44 : #include <com/sun/star/io/Pipe.hpp>
45 : #include "com/sun/star/io/XOutputStream.hpp"
46 : #include "com/sun/star/io/XInputStream.hpp"
47 : #include "com/sun/star/task/InteractionClassification.hpp"
48 : #include "com/sun/star/task/XInteractionApprove.hpp"
49 : #include "com/sun/star/ucb/XInteractionReplaceExistingData.hpp"
50 : #include "com/sun/star/ucb/NameClashResolveRequest.hpp"
51 : #include "com/sun/star/ucb/XContentAccess.hpp"
52 : #include "com/sun/star/ucb/NameClash.hpp"
53 : #include "com/sun/star/ucb/UnsupportedCommandException.hpp"
54 : #include "com/sun/star/sdbc/XResultSet.hpp"
55 : #include "com/sun/star/sdbc/XRow.hpp"
56 : #include "com/sun/star/packages/manifest/ManifestReader.hpp"
57 : #include "com/sun/star/packages/manifest/ManifestWriter.hpp"
58 : #include "com/sun/star/deployment/DependencyException.hpp"
59 : #include "com/sun/star/deployment/LicenseException.hpp"
60 : #include "com/sun/star/deployment/PlatformException.hpp"
61 : #include "com/sun/star/deployment/Prerequisites.hpp"
62 : #include "com/sun/star/xml/dom/XDocumentBuilder.hpp"
63 : #include "com/sun/star/xml/xpath/XXPathAPI.hpp"
64 : #include "com/sun/star/deployment/XPackageManager.hpp"
65 : #include "boost/optional.hpp"
66 : #include <vector>
67 : #include <stdio.h>
68 :
69 : #include "dp_extbackenddb.hxx"
70 : using namespace ::dp_misc;
71 : using namespace ::com::sun::star;
72 : using namespace ::com::sun::star::uno;
73 :
74 :
75 : namespace dp_registry {
76 : namespace backend {
77 : namespace bundle {
78 : namespace {
79 :
80 : typedef cppu::ImplInheritanceHelper1<PackageRegistryBackend,
81 : lang::XServiceInfo> ImplBaseT;
82 :
83 : //==============================================================================
84 508 : class BackendImpl : public ImplBaseT
85 : {
86 202 : class PackageImpl : public ::dp_registry::backend::Package
87 : {
88 : BackendImpl * getMyBackend() const;
89 : /** constains the old tooltip description for the Extension Manager GUI in OOo v.2.x
90 : We keep it for backward compatibility.
91 : */
92 : OUString m_oldDescription;
93 : OUString m_url_expanded;
94 : const bool m_legacyBundle;
95 : Sequence< Reference<deployment::XPackage> > m_bundle;
96 : Sequence< Reference<deployment::XPackage> > * m_pBundle;
97 :
98 : ExtensionBackendDb::Data m_dbData;
99 :
100 : Reference<deployment::XPackage> bindBundleItem(
101 : OUString const & url, OUString const & mediaType,
102 : sal_Bool bRemoved, //that is, using data base information
103 : OUString const & identifier,
104 : Reference<ucb::XCommandEnvironment> const & xCmdEnv,
105 : bool notifyDetectionError = true );
106 :
107 : typedef ::std::vector< Reference<deployment::XPackage> > t_packagevec;
108 : void scanBundle(
109 : t_packagevec & bundle,
110 : ::rtl::Reference<AbortChannel> const & abortChannel,
111 : Reference<ucb::XCommandEnvironment> const & xCmdEnv );
112 : void scanLegacyBundle(
113 : t_packagevec & bundle,
114 : OUString const & url,
115 : ::rtl::Reference<AbortChannel> const & abortChannel,
116 : Reference<ucb::XCommandEnvironment> const & xCmdEnv,
117 : bool skip_registration = false );
118 : ::std::vector<Reference<deployment::XPackage> > getPackagesFromDb(
119 : Reference<ucb::XCommandEnvironment> const & xCmdEnv);
120 : bool checkPlatform(
121 : Reference<ucb::XCommandEnvironment > const & environment);
122 :
123 : bool checkDependencies(
124 : Reference<ucb::XCommandEnvironment > const &
125 : environment,
126 : DescriptionInfoset const & description);
127 : // throws css::uno::RuntimeException,
128 : // css::deployment::DeploymentException
129 :
130 : ::sal_Bool checkLicense(
131 : Reference< ucb::XCommandEnvironment > const & xCmdEnv,
132 : DescriptionInfoset const & description, bool bNoLicenseChecking)
133 : throw (deployment::DeploymentException,
134 : ucb::CommandFailedException,
135 : ucb::CommandAbortedException,
136 : RuntimeException);
137 : // @throws DeploymentException
138 : OUString getTextFromURL(
139 : const Reference< ucb::XCommandEnvironment >& xCmdEnv,
140 : const OUString& licenseUrl);
141 :
142 : DescriptionInfoset getDescriptionInfoset();
143 :
144 : // Package
145 : virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_(
146 : ::osl::ResettableMutexGuard & guard,
147 : ::rtl::Reference<AbortChannel> const & abortChannel,
148 : Reference<ucb::XCommandEnvironment> const & xCmdEnv );
149 : virtual void processPackage_(
150 : ::osl::ResettableMutexGuard & guard,
151 : bool registerPackage,
152 : bool startup,
153 : ::rtl::Reference<AbortChannel> const & abortChannel,
154 : Reference<ucb::XCommandEnvironment> const & xCmdEnv );
155 :
156 : virtual void SAL_CALL disposing();
157 :
158 :
159 :
160 : public:
161 : PackageImpl(
162 : ::rtl::Reference<PackageRegistryBackend> const & myBackend,
163 : OUString const & url,
164 : OUString const & name,
165 : Reference<deployment::XPackageTypeInfo> const & xPackageType,
166 : bool legacyBundle,
167 : bool bRemoved,
168 : OUString const & identifier);
169 :
170 : // XPackage
171 : virtual sal_Bool SAL_CALL isBundle() throw (RuntimeException);
172 :
173 : virtual Sequence< Reference<deployment::XPackage> > SAL_CALL getBundle(
174 : Reference<task::XAbortChannel> const & xAbortChannel,
175 : Reference<ucb::XCommandEnvironment> const & xCmdEnv )
176 : throw (deployment::DeploymentException,
177 : ucb::CommandFailedException,
178 : ucb::CommandAbortedException,
179 : lang::IllegalArgumentException, RuntimeException);
180 : virtual OUString SAL_CALL getDescription()
181 : throw (deployment::ExtensionRemovedException, RuntimeException);
182 :
183 : virtual OUString SAL_CALL getLicenseText()
184 : throw (deployment::ExtensionRemovedException, RuntimeException);
185 :
186 : virtual void SAL_CALL exportTo(
187 : OUString const & destFolderURL, OUString const & newTitle,
188 : sal_Int32 nameClashAction,
189 : Reference<ucb::XCommandEnvironment> const & xCmdEnv )
190 : throw (deployment::ExtensionRemovedException,
191 : ucb::CommandFailedException,
192 : ucb::CommandAbortedException,
193 : RuntimeException);
194 :
195 : virtual ::sal_Int32 SAL_CALL checkPrerequisites(
196 : const Reference< task::XAbortChannel >& xAbortChannel,
197 : const Reference< ucb::XCommandEnvironment >& xCmdEnv,
198 : ::sal_Bool noLicenseChecking)
199 : throw (deployment::ExtensionRemovedException,
200 : deployment::DeploymentException,
201 : ucb::CommandFailedException,
202 : ucb::CommandAbortedException,
203 : RuntimeException);
204 :
205 : virtual ::sal_Bool SAL_CALL checkDependencies(
206 : const Reference< ucb::XCommandEnvironment >& xCmdEnv )
207 : throw (deployment::DeploymentException,
208 : deployment::ExtensionRemovedException,
209 : ucb::CommandFailedException,
210 : RuntimeException);
211 :
212 : virtual beans::Optional<OUString> SAL_CALL getIdentifier()
213 : throw (RuntimeException);
214 :
215 : virtual OUString SAL_CALL getVersion()
216 : throw (deployment::ExtensionRemovedException, RuntimeException);
217 :
218 : virtual Sequence<OUString> SAL_CALL getUpdateInformationURLs()
219 : throw (deployment::ExtensionRemovedException, RuntimeException);
220 :
221 : virtual beans::StringPair SAL_CALL getPublisherInfo()
222 : throw (deployment::ExtensionRemovedException, RuntimeException);
223 :
224 : virtual OUString SAL_CALL getDisplayName()
225 : throw (deployment::ExtensionRemovedException, RuntimeException);
226 :
227 : virtual Reference< graphic::XGraphic > SAL_CALL
228 : getIcon( ::sal_Bool bHighContrast )
229 : throw (deployment::ExtensionRemovedException,
230 : RuntimeException);
231 : };
232 : friend class PackageImpl;
233 :
234 : Reference<deployment::XPackageRegistry> m_xRootRegistry;
235 : const Reference<deployment::XPackageTypeInfo> m_xBundleTypeInfo;
236 : const Reference<deployment::XPackageTypeInfo> m_xLegacyBundleTypeInfo;
237 : Sequence< Reference<deployment::XPackageTypeInfo> > m_typeInfos;
238 :
239 : std::auto_ptr<ExtensionBackendDb> m_backendDb;
240 :
241 : void addDataToDb(OUString const & url, ExtensionBackendDb::Data const & data);
242 : ExtensionBackendDb::Data readDataFromDb(OUString const & url);
243 : void revokeEntryFromDb(OUString const & url);
244 :
245 : // PackageRegistryBackend
246 : virtual Reference<deployment::XPackage> bindPackage_(
247 : OUString const & url, OUString const & mediaType,
248 : sal_Bool bRemoved, OUString const & identifier,
249 : Reference<ucb::XCommandEnvironment> const & xCmdEnv );
250 :
251 : virtual void SAL_CALL disposing();
252 :
253 : public:
254 : BackendImpl(
255 : Sequence<Any> const & args,
256 : Reference<XComponentContext> const & xComponentContext,
257 : Reference<deployment::XPackageRegistry> const & xRootRegistry );
258 :
259 : // XServiceInfo
260 : virtual OUString SAL_CALL getImplementationName() throw (RuntimeException);
261 : virtual sal_Bool SAL_CALL supportsService( OUString const& name )
262 : throw (RuntimeException);
263 : virtual Sequence<OUString> SAL_CALL getSupportedServiceNames()
264 : throw (RuntimeException);
265 :
266 : // XPackageRegistry
267 : virtual Sequence< Reference<deployment::XPackageTypeInfo> > SAL_CALL
268 : getSupportedPackageTypes() throw (RuntimeException);
269 : virtual void SAL_CALL packageRemoved(OUString const & url, OUString const & mediaType)
270 : throw (deployment::DeploymentException,
271 : uno::RuntimeException);
272 :
273 : using ImplBaseT::disposing;
274 : };
275 :
276 : //Used to find a XPackage with a particular URL
277 948 : class XPackage_eq : public std::unary_function<Reference<deployment::XPackage>, bool>
278 : {
279 : OUString m_URL;
280 : public:
281 316 : explicit XPackage_eq(const OUString & s) : m_URL(s) {}
282 630 : bool operator() (const Reference<deployment::XPackage> & p) const
283 : {
284 630 : return m_URL.equals(p->getURL());
285 : }
286 : };
287 :
288 : //______________________________________________________________________________
289 254 : BackendImpl::BackendImpl(
290 : Sequence<Any> const & args,
291 : Reference<XComponentContext> const & xComponentContext,
292 : Reference<deployment::XPackageRegistry> const & xRootRegistry )
293 : : ImplBaseT( args, xComponentContext ),
294 : m_xRootRegistry( xRootRegistry ),
295 : m_xBundleTypeInfo( new Package::TypeInfo(
296 : "application/vnd.sun.star.package-bundle",
297 : "*.oxt;*.uno.pkg",
298 : getResourceString(RID_STR_PACKAGE_BUNDLE),
299 254 : RID_IMG_DEF_PACKAGE_BUNDLE ) ),
300 : m_xLegacyBundleTypeInfo( new Package::TypeInfo(
301 : "application/vnd.sun.star.legacy-package-bundle",
302 : "*.zip",
303 254 : m_xBundleTypeInfo->getShortDescription(),
304 254 : RID_IMG_DEF_PACKAGE_BUNDLE ) ),
305 1016 : m_typeInfos(2)
306 : {
307 254 : m_typeInfos[ 0 ] = m_xBundleTypeInfo;
308 254 : m_typeInfos[ 1 ] = m_xLegacyBundleTypeInfo;
309 :
310 254 : if (!transientMode())
311 : {
312 254 : OUString dbFile = makeURL(getCachePath(), getImplementationName());
313 254 : dbFile = makeURL(dbFile, "backenddb.xml");
314 : m_backendDb.reset(
315 254 : new ExtensionBackendDb(getComponentContext(), dbFile));
316 : }
317 254 : }
318 :
319 : //______________________________________________________________________________
320 254 : void BackendImpl::disposing()
321 : {
322 254 : m_xRootRegistry.clear();
323 254 : PackageRegistryBackend::disposing();
324 254 : }
325 :
326 : // XServiceInfo
327 508 : OUString BackendImpl::getImplementationName() throw (RuntimeException)
328 : {
329 508 : return OUString("com.sun.star.comp.deployment.bundle.PackageRegistryBackend");
330 : }
331 :
332 0 : sal_Bool BackendImpl::supportsService(OUString const & ServiceName)
333 : throw (css::uno::RuntimeException)
334 : {
335 0 : return cppu::supportsService(this, ServiceName);
336 : }
337 :
338 0 : Sequence<OUString> BackendImpl::getSupportedServiceNames()
339 : throw (RuntimeException)
340 : {
341 : return comphelper::makeSequence(
342 0 : OUString(BACKEND_SERVICE_NAME) );
343 : }
344 :
345 : // XPackageRegistry
346 : //______________________________________________________________________________
347 : Sequence< Reference<deployment::XPackageTypeInfo> >
348 254 : BackendImpl::getSupportedPackageTypes() throw (RuntimeException)
349 : {
350 254 : return m_typeInfos;
351 : }
352 :
353 3 : void BackendImpl::packageRemoved(OUString const & url, OUString const & /*mediaType*/)
354 : throw (deployment::DeploymentException,
355 : uno::RuntimeException)
356 : {
357 : //Notify the backend responsible for processing the different media
358 : //types that this extension was removed.
359 3 : ExtensionBackendDb::Data data = readDataFromDb(url);
360 4 : for (ExtensionBackendDb::Data::ITC_ITEMS i = data.items.begin(); i != data.items.end(); ++i)
361 : {
362 1 : m_xRootRegistry->packageRemoved(i->first, i->second);
363 : }
364 :
365 3 : if (m_backendDb.get())
366 3 : m_backendDb->removeEntry(url);
367 3 : }
368 :
369 :
370 : // PackageRegistryBackend
371 : //______________________________________________________________________________
372 101 : Reference<deployment::XPackage> BackendImpl::bindPackage_(
373 : OUString const & url, OUString const & mediaType_,
374 : sal_Bool bRemoved, OUString const & identifier,
375 : Reference<ucb::XCommandEnvironment> const & xCmdEnv )
376 : {
377 101 : OUString mediaType( mediaType_ );
378 101 : if (mediaType.isEmpty())
379 : {
380 : // detect media-type:
381 35 : ::ucbhelper::Content ucbContent;
382 35 : if (create_ucb_content( &ucbContent, url, xCmdEnv ))
383 : {
384 35 : if (ucbContent.isFolder())
385 : {
386 : //Every .oxt, uno.pkg file must contain a META-INF folder
387 33 : ::ucbhelper::Content metaInfContent;
388 66 : if (create_ucb_content(
389 : &metaInfContent, makeURL( url, "META-INF" ),
390 66 : xCmdEnv, false /* no throw */ ))
391 : {
392 33 : mediaType = OUString("application/vnd.sun.star.package-bundle");
393 33 : }
394 : //No support of legacy bundles, because every folder could be one.
395 : }
396 : else
397 : {
398 2 : const OUString title( StrTitle::getTitle( ucbContent ) );
399 2 : if (title.endsWithIgnoreAsciiCase(".oxt") ||
400 0 : title.endsWithIgnoreAsciiCase(".uno.pkg"))
401 2 : mediaType = OUString("application/vnd.sun.star.package-bundle");
402 0 : else if (title.endsWithIgnoreAsciiCase(".zip"))
403 0 : mediaType =
404 2 : OUString("application/vnd.sun.star.legacy-package-bundle");
405 : }
406 : }
407 35 : if (mediaType.isEmpty())
408 : throw lang::IllegalArgumentException(
409 0 : StrCannotDetectMediaType::get() + url,
410 0 : static_cast<OWeakObject *>(this), static_cast<sal_Int16>(-1) );
411 : }
412 :
413 202 : OUString type, subType;
414 202 : INetContentTypeParameterList params;
415 101 : if (INetContentTypes::parse( mediaType, type, subType, ¶ms ))
416 : {
417 101 : if (type.equalsIgnoreAsciiCase("application"))
418 : {
419 :
420 : //In case a XPackage is created for a removed extension, we cannot
421 : //obtain the name
422 101 : OUString name;
423 101 : if (!bRemoved)
424 : {
425 : ::ucbhelper::Content ucbContent(
426 101 : url, xCmdEnv, getComponentContext() );
427 101 : name = StrTitle::getTitle( ucbContent );
428 : }
429 101 : if (subType.equalsIgnoreAsciiCase("vnd.sun.star.package-bundle"))
430 : {
431 : return new PackageImpl(
432 : this, url, name, m_xBundleTypeInfo, false, bRemoved,
433 101 : identifier);
434 : }
435 0 : else if (subType.equalsIgnoreAsciiCase( "vnd.sun.star.legacy-package-bundle"))
436 : {
437 : return new PackageImpl(
438 : this, url, name, m_xLegacyBundleTypeInfo, true, bRemoved,
439 0 : identifier);
440 0 : }
441 : }
442 : }
443 : throw lang::IllegalArgumentException(
444 0 : StrUnsupportedMediaType::get() + mediaType,
445 : static_cast<OWeakObject *>(this),
446 101 : static_cast<sal_Int16>(-1) );
447 : }
448 :
449 33 : void BackendImpl::addDataToDb(
450 : OUString const & url, ExtensionBackendDb::Data const & data)
451 : {
452 33 : if (m_backendDb.get())
453 33 : m_backendDb->addEntry(url, data);
454 33 : }
455 :
456 3 : ExtensionBackendDb::Data BackendImpl::readDataFromDb(
457 : OUString const & url)
458 : {
459 3 : ExtensionBackendDb::Data data;
460 3 : if (m_backendDb.get())
461 3 : data = m_backendDb->getEntry(url);
462 3 : return data;
463 : }
464 :
465 1 : void BackendImpl::revokeEntryFromDb(OUString const & url)
466 : {
467 1 : if (m_backendDb.get())
468 1 : m_backendDb->revokeEntry(url);
469 1 : }
470 :
471 :
472 :
473 101 : BackendImpl::PackageImpl::PackageImpl(
474 : ::rtl::Reference<PackageRegistryBackend> const & myBackend,
475 : OUString const & url,
476 : OUString const & name,
477 : Reference<deployment::XPackageTypeInfo> const & xPackageType,
478 : bool legacyBundle, bool bRemoved, OUString const & identifier)
479 : : Package( myBackend, url, name, name /* display-name */,
480 : xPackageType, bRemoved, identifier),
481 : m_url_expanded( expandUnoRcUrl( url ) ),
482 : m_legacyBundle( legacyBundle ),
483 101 : m_pBundle( 0 )
484 : {
485 101 : if (bRemoved)
486 0 : m_dbData = getMyBackend()->readDataFromDb(url);
487 101 : }
488 :
489 414 : BackendImpl * BackendImpl::PackageImpl::getMyBackend() const
490 : {
491 414 : BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get());
492 414 : if (NULL == pBackend)
493 : {
494 : //May throw a DisposedException
495 0 : check();
496 : //We should never get here...
497 : throw RuntimeException("Failed to get the BackendImpl",
498 0 : static_cast<OWeakObject*>(const_cast<PackageImpl *>(this)));
499 : }
500 414 : return pBackend;
501 : }
502 : //______________________________________________________________________________
503 101 : void BackendImpl::PackageImpl::disposing()
504 : {
505 101 : sal_Int32 len = m_bundle.getLength();
506 101 : Reference<deployment::XPackage> const * p = m_bundle.getConstArray();
507 417 : for ( sal_Int32 pos = 0; pos < len; ++pos )
508 316 : try_dispose( p[ pos ] );
509 101 : m_bundle.realloc( 0 );
510 :
511 101 : Package::disposing();
512 101 : }
513 :
514 : // Package
515 : //______________________________________________________________________________
516 : beans::Optional< beans::Ambiguous<sal_Bool> >
517 132 : BackendImpl::PackageImpl::isRegistered_(
518 : ::osl::ResettableMutexGuard &,
519 : ::rtl::Reference<AbortChannel> const & abortChannel,
520 : Reference<ucb::XCommandEnvironment> const & xCmdEnv )
521 : {
522 : //In case the object was created for a removed extension (m_bRemoved = true)
523 : //but the extension is not registered, then bundle will be empty. Then
524 : //the return value will be Optional<...>.IsPresent= false. Althoug this is
525 : //not true, this does not matter. Then registerPackage or revokePackage
526 : //would never be called for the items. But since the extension is removed
527 : //and not registered anyway, this does not matter.
528 : const Sequence< Reference<deployment::XPackage> > bundle(
529 132 : getBundle( abortChannel.get(), xCmdEnv ) );
530 :
531 132 : bool reg = false;
532 132 : bool present = false;
533 132 : bool ambig = false;
534 908 : for ( sal_Int32 pos = bundle.getLength(); pos--; )
535 : {
536 644 : Reference<deployment::XPackage> const & xPackage = bundle[ pos ];
537 : Reference<task::XAbortChannel> xSubAbortChannel(
538 644 : xPackage->createAbortChannel() );
539 1288 : AbortChannel::Chain chain( abortChannel, xSubAbortChannel );
540 : beans::Optional< beans::Ambiguous<sal_Bool> > option(
541 644 : xPackage->isRegistered( xSubAbortChannel, xCmdEnv ) );
542 :
543 : //present = true if at least one bundle item has this value.
544 : //reg = true if all bundle items have an option value (option.IsPresent == 1)
545 : //and all have value of true (option.Value.Value == true)
546 : //If not, then the bundle has the status of not registered and ambiguous.
547 644 : if (option.IsPresent)
548 : {
549 644 : beans::Ambiguous<sal_Bool> const & status = option.Value;
550 644 : if (present)
551 : {
552 : //we never come here in the first iteration
553 512 : if (reg != (status.Value != sal_False)) {
554 :
555 0 : ambig = true;
556 0 : reg = false;
557 0 : break;
558 : }
559 : }
560 : else
561 : {
562 : //we always come here in the first iteration
563 132 : reg = status.Value;
564 132 : present = true;
565 : }
566 : }
567 644 : }
568 : return beans::Optional< beans::Ambiguous<sal_Bool> >(
569 132 : present, beans::Ambiguous<sal_Bool>(reg, ambig) );
570 : }
571 :
572 0 : OUString BackendImpl::PackageImpl::getTextFromURL(
573 : const css::uno::Reference< css::ucb::XCommandEnvironment >& xCmdEnv,
574 : const OUString& licenseUrl)
575 : {
576 : try
577 : {
578 : ::ucbhelper::Content descContent(
579 0 : licenseUrl, xCmdEnv, getMyBackend()->getComponentContext());
580 0 : ::rtl::ByteSequence seq = dp_misc::readFile(descContent);
581 : return OUString( reinterpret_cast<sal_Char const *>(
582 0 : seq.getConstArray()), seq.getLength(), RTL_TEXTENCODING_UTF8);
583 : }
584 0 : catch (const css::uno::Exception&)
585 : {
586 0 : Any exc( ::cppu::getCaughtException() );
587 : throw css::deployment::DeploymentException(
588 0 : "Could not read file " + licenseUrl, 0, exc);
589 : }
590 :
591 : }
592 :
593 243 : DescriptionInfoset BackendImpl::PackageImpl::getDescriptionInfoset()
594 : {
595 243 : return dp_misc::getDescriptionInfoset(m_url_expanded);
596 : }
597 :
598 34 : bool BackendImpl::PackageImpl::checkPlatform(
599 : css::uno::Reference< css::ucb::XCommandEnvironment > const & environment)
600 : {
601 34 : bool ret = false;
602 34 : DescriptionInfoset info(getDescriptionInfoset());
603 68 : Sequence<OUString> platforms(info.getSupportedPlaforms());
604 34 : if (hasValidPlatform(platforms))
605 : {
606 34 : ret = true;
607 : }
608 : else
609 : {
610 0 : ret = false;
611 : OUString msg(
612 0 : "unsupported platform");
613 : Any e(
614 : css::deployment::PlatformException(
615 0 : msg, static_cast<OWeakObject *>(this), this));
616 0 : if (!interactContinuation(
617 0 : e, cppu::UnoType< css::task::XInteractionApprove >::get(),
618 0 : environment, NULL, NULL))
619 : {
620 : throw css::deployment::DeploymentException(
621 0 : msg, static_cast<OWeakObject *>(this), e);
622 0 : }
623 : }
624 68 : return ret;
625 : }
626 :
627 :
628 34 : bool BackendImpl::PackageImpl::checkDependencies(
629 : css::uno::Reference< css::ucb::XCommandEnvironment > const & environment,
630 : DescriptionInfoset const & description)
631 : {
632 : css::uno::Sequence< css::uno::Reference< css::xml::dom::XElement > >
633 34 : unsatisfied(dp_misc::Dependencies::check(description));
634 :
635 34 : if (unsatisfied.getLength() == 0) {
636 34 : return true;
637 : } else {
638 : OUString msg(
639 0 : "unsatisfied dependencies");
640 : Any e(
641 : css::deployment::DependencyException(
642 0 : msg, static_cast<OWeakObject *>(this), unsatisfied));
643 0 : if (!interactContinuation(
644 0 : e, cppu::UnoType< css::task::XInteractionApprove >::get(),
645 0 : environment, NULL, NULL))
646 : {
647 : throw css::deployment::DeploymentException(
648 0 : msg, static_cast<OWeakObject *>(this), e);
649 : }
650 0 : return false;
651 34 : }
652 : }
653 :
654 34 : ::sal_Bool BackendImpl::PackageImpl::checkLicense(
655 : css::uno::Reference< css::ucb::XCommandEnvironment > const & xCmdEnv,
656 : DescriptionInfoset const & info, bool alreadyInstalled)
657 : throw (css::deployment::DeploymentException,
658 : css::ucb::CommandFailedException,
659 : css::ucb::CommandAbortedException,
660 : css::uno::RuntimeException)
661 : {
662 : try
663 : {
664 : ::boost::optional<SimpleLicenseAttributes> simplLicAttr
665 34 : = info.getSimpleLicenseAttributes();
666 34 : if (! simplLicAttr)
667 34 : return true;
668 0 : OUString sLic = info.getLocalizedLicenseURL();
669 : //If we do not get a localized licence then there is an error in the description.xml
670 : //This should be handled by using a validating parser. Therefore we assume that no
671 : //license is available.
672 0 : if (sLic.isEmpty())
673 : throw css::deployment::DeploymentException(
674 0 : "Could not obtain path to license. Possible error in description.xml", 0, Any());
675 0 : OUString sHref = m_url_expanded + "/" + sLic;
676 0 : OUString sLicense = getTextFromURL(xCmdEnv, sHref);
677 : ////determine who has to agree to the license
678 : //check correct value for attribute
679 0 : if ( ! (simplLicAttr->acceptBy == "user" || simplLicAttr->acceptBy == "admin"))
680 : throw css::deployment::DeploymentException(
681 0 : "Could not obtain attribute simple-lincense@accept-by or it has no valid value", 0, Any());
682 :
683 :
684 : //Only use interaction if there is no version of this extension already installed
685 : //and the suppress-on-update flag is not set for the new extension
686 : // alreadyInstalled | bSuppressOnUpdate | show license
687 : //----------------------------------------
688 : // 0 | 0 | 1
689 : // 0 | 1 | 1
690 : // 1 | 0 | 1
691 : // 1 | 1 | 0
692 :
693 0 : if ( !(alreadyInstalled && simplLicAttr->suppressOnUpdate))
694 : {
695 : css::deployment::LicenseException licExc(
696 0 : OUString(), 0, getDisplayName(), sLicense,
697 0 : simplLicAttr->acceptBy);
698 0 : bool approve = false;
699 0 : bool abort = false;
700 0 : if (! interactContinuation(
701 0 : Any(licExc), task::XInteractionApprove::static_type(), xCmdEnv, &approve, &abort ))
702 : throw css::deployment::DeploymentException(
703 0 : "Could not interact with user.", 0, Any());
704 :
705 0 : if (approve == true)
706 0 : return true;
707 : else
708 0 : return false;
709 : }
710 34 : return true;
711 0 : } catch (const css::ucb::CommandFailedException&) {
712 0 : throw;
713 0 : } catch (const css::ucb::CommandAbortedException&) {
714 0 : throw;
715 0 : } catch (const css::deployment::DeploymentException&) {
716 0 : throw;
717 0 : } catch (const css::uno::RuntimeException&) {
718 0 : throw;
719 0 : } catch (const css::uno::Exception&) {
720 0 : Any anyExc = cppu::getCaughtException();
721 0 : throw css::deployment::DeploymentException("Unexpected exception", 0, anyExc);
722 : }
723 : }
724 :
725 34 : ::sal_Int32 BackendImpl::PackageImpl::checkPrerequisites(
726 : const css::uno::Reference< css::task::XAbortChannel >&,
727 : const css::uno::Reference< css::ucb::XCommandEnvironment >& xCmdEnv,
728 : sal_Bool alreadyInstalled)
729 : throw (css::deployment::DeploymentException,
730 : css::deployment::ExtensionRemovedException,
731 : css::ucb::CommandFailedException,
732 : css::ucb::CommandAbortedException,
733 : css::uno::RuntimeException)
734 : {
735 34 : if (m_bRemoved)
736 0 : throw deployment::ExtensionRemovedException();
737 34 : DescriptionInfoset info = getDescriptionInfoset();
738 34 : if (!info.hasDescription())
739 0 : return 0;
740 :
741 : //always return LICENSE as long as the user did not accept the license
742 : //so that XExtensonManager::checkPrerequisitesAndEnable will again
743 : //check the license
744 34 : if (!checkPlatform(xCmdEnv))
745 : return deployment::Prerequisites::PLATFORM |
746 0 : deployment::Prerequisites::LICENSE;
747 34 : else if(!checkDependencies(xCmdEnv, info))
748 : return deployment::Prerequisites::DEPENDENCIES |
749 0 : deployment::Prerequisites::LICENSE;
750 34 : else if(!checkLicense(xCmdEnv, info, alreadyInstalled))
751 0 : return deployment::Prerequisites::LICENSE;
752 : else
753 34 : return 0;
754 : }
755 :
756 0 : ::sal_Bool BackendImpl::PackageImpl::checkDependencies(
757 : const css::uno::Reference< css::ucb::XCommandEnvironment >& xCmdEnv )
758 : throw (deployment::DeploymentException,
759 : deployment::ExtensionRemovedException,
760 : ucb::CommandFailedException,
761 : RuntimeException)
762 : {
763 0 : if (m_bRemoved)
764 0 : throw deployment::ExtensionRemovedException();
765 0 : DescriptionInfoset info = getDescriptionInfoset();
766 0 : if (!info.hasDescription())
767 0 : return sal_True;
768 :
769 0 : return checkDependencies(xCmdEnv, info);
770 : }
771 :
772 107 : beans::Optional<OUString> BackendImpl::PackageImpl::getIdentifier()
773 : throw (RuntimeException)
774 : {
775 107 : OUString identifier;
776 107 : if (m_bRemoved)
777 0 : identifier = m_identifier;
778 : else
779 214 : identifier = dp_misc::generateIdentifier(
780 107 : getDescriptionInfoset().getIdentifier(), m_name);
781 :
782 : return beans::Optional<OUString>(
783 107 : true, identifier);
784 : }
785 :
786 33 : OUString BackendImpl::PackageImpl::getVersion()
787 : throw (deployment::ExtensionRemovedException, RuntimeException)
788 : {
789 33 : if (m_bRemoved)
790 0 : throw deployment::ExtensionRemovedException();
791 33 : return getDescriptionInfoset().getVersion();
792 : }
793 :
794 0 : Sequence<OUString> BackendImpl::PackageImpl::getUpdateInformationURLs()
795 : throw (deployment::ExtensionRemovedException, RuntimeException)
796 : {
797 0 : if (m_bRemoved)
798 0 : throw deployment::ExtensionRemovedException();
799 0 : return getDescriptionInfoset().getUpdateInformationUrls();
800 : }
801 :
802 0 : beans::StringPair BackendImpl::PackageImpl::getPublisherInfo()
803 : throw (deployment::ExtensionRemovedException, RuntimeException)
804 : {
805 0 : if (m_bRemoved)
806 0 : throw deployment::ExtensionRemovedException();
807 0 : ::std::pair< OUString, OUString > aInfo = getDescriptionInfoset().getLocalizedPublisherNameAndURL();
808 0 : beans::StringPair aStrPair( aInfo.first, aInfo.second );
809 0 : return aStrPair;
810 : }
811 :
812 : //______________________________________________________________________________
813 0 : uno::Reference< graphic::XGraphic > BackendImpl::PackageImpl::getIcon( sal_Bool bHighContrast )
814 : throw (deployment::ExtensionRemovedException, RuntimeException )
815 : {
816 0 : if (m_bRemoved)
817 0 : throw deployment::ExtensionRemovedException();
818 :
819 0 : uno::Reference< graphic::XGraphic > xGraphic;
820 :
821 0 : OUString aIconURL = getDescriptionInfoset().getIconURL( bHighContrast );
822 0 : if ( !aIconURL.isEmpty() )
823 : {
824 0 : OUString aFullIconURL = m_url_expanded + "/" + aIconURL;
825 :
826 0 : uno::Reference< XComponentContext > xContext( getMyBackend()->getComponentContext() );
827 0 : uno::Reference< graphic::XGraphicProvider > xGraphProvider( graphic::GraphicProvider::create(xContext) );
828 :
829 0 : uno::Sequence< beans::PropertyValue > aMediaProps( 1 );
830 0 : aMediaProps[0].Name = "URL";
831 0 : aMediaProps[0].Value <<= aFullIconURL;
832 :
833 0 : xGraphic = xGraphProvider->queryGraphic( aMediaProps );
834 : }
835 :
836 0 : return xGraphic;
837 : }
838 :
839 : //______________________________________________________________________________
840 34 : void BackendImpl::PackageImpl::processPackage_(
841 : ::osl::ResettableMutexGuard &,
842 : bool doRegisterPackage,
843 : bool startup,
844 : ::rtl::Reference<AbortChannel> const & abortChannel,
845 : Reference<ucb::XCommandEnvironment> const & xCmdEnv )
846 : {
847 : const Sequence< Reference<deployment::XPackage> > bundle(
848 34 : getBundle( abortChannel.get(), xCmdEnv ) );
849 :
850 34 : if (doRegisterPackage)
851 : {
852 33 : ExtensionBackendDb::Data data;
853 33 : const sal_Int32 len = bundle.getLength();
854 194 : for ( sal_Int32 pos = 0; pos < len; ++pos )
855 : {
856 161 : checkAborted(abortChannel);
857 161 : Reference<deployment::XPackage> const & xPackage = bundle[ pos ];
858 : Reference<task::XAbortChannel> xSubAbortChannel(
859 161 : xPackage->createAbortChannel() );
860 322 : AbortChannel::Chain chain( abortChannel, xSubAbortChannel );
861 : try {
862 161 : xPackage->registerPackage( startup, xSubAbortChannel, xCmdEnv );
863 : }
864 0 : catch (const Exception &)
865 : {
866 : //We even try a rollback if the user cancelled the action (CommandAbortedException)
867 : //in order to prevent invalid database entries.
868 0 : Any exc( ::cppu::getCaughtException() );
869 : // try to handle exception, notify:
870 0 : bool approve = false, abort = false;
871 0 : if (! interactContinuation(
872 : Any( lang::WrappedTargetException(
873 : "bundle item registration error!",
874 : static_cast<OWeakObject *>(this), exc ) ),
875 0 : task::XInteractionApprove::static_type(), xCmdEnv,
876 0 : &approve, &abort )) {
877 : OSL_ASSERT( !approve && !abort );
878 0 : if (m_legacyBundle) // default for legacy packages: ignore
879 0 : continue;
880 : // no selection at all, so rethrow;
881 : // no C++ rethrow after getCaughtException(),
882 : // see cppuhelper/exc_hlp.hxx:
883 0 : ::cppu::throwException(exc);
884 : }
885 0 : if (approve && !abort) // ignore error, just continue
886 0 : continue;
887 :
888 : {
889 0 : ProgressLevel progress( xCmdEnv, "rollback..." );
890 : // try rollback
891 0 : for ( ; pos--; )
892 : {
893 : try {
894 0 : bundle[ pos ]->revokePackage(
895 0 : startup, xSubAbortChannel, xCmdEnv );
896 : }
897 0 : catch (const Exception &)
898 : {
899 : OSL_FAIL( OUStringToOString(
900 : ::comphelper::anyToString(
901 : ::cppu::getCaughtException() ),
902 : RTL_TEXTENCODING_UTF8 ).getStr() );
903 : // ignore any errors of rollback
904 : }
905 : }
906 0 : progress.update( "rollback finished." );
907 : }
908 :
909 0 : deployment::DeploymentException dpExc;
910 0 : if (exc >>= dpExc) {
911 : throw ucb::CommandFailedException(
912 0 : dpExc.Message, dpExc.Context, dpExc.Cause );
913 : }
914 : else {
915 : // rethrow CommandFailedException
916 0 : ::cppu::throwException(exc);
917 0 : }
918 0 : }
919 : data.items.push_back(
920 161 : ::std::make_pair(xPackage->getURL(),
921 322 : xPackage->getPackageType()->getMediaType()));
922 161 : }
923 33 : getMyBackend()->addDataToDb(getURL(), data);
924 : }
925 : else
926 : {
927 : // revoke in reverse order:
928 3 : for ( sal_Int32 pos = bundle.getLength(); pos--; )
929 : {
930 1 : checkAborted(abortChannel);
931 1 : Reference<deployment::XPackage> const & xPackage = bundle[ pos ];
932 : Reference<task::XAbortChannel> xSubAbortChannel(
933 1 : xPackage->createAbortChannel() );
934 2 : AbortChannel::Chain chain( abortChannel, xSubAbortChannel );
935 : try {
936 1 : bundle[ pos ]->revokePackage(
937 1 : startup, xSubAbortChannel, xCmdEnv );
938 : }
939 0 : catch (const RuntimeException &) {
940 0 : throw;
941 : }
942 0 : catch (const ucb::CommandAbortedException &) {
943 0 : throw;
944 : }
945 0 : catch (const Exception &) {
946 : // CommandFailedException, DeploymentException:
947 0 : Any exc( ::cppu::getCaughtException() );
948 : // try to handle exception, notify:
949 0 : bool approve = false, abort = false;
950 0 : if (! interactContinuation(
951 : Any( lang::WrappedTargetException(
952 : "bundle item revocation error!",
953 : static_cast<OWeakObject *>(this), exc ) ),
954 0 : task::XInteractionApprove::static_type(), xCmdEnv,
955 0 : &approve, &abort )) {
956 : OSL_ASSERT( !approve && !abort );
957 0 : if (m_legacyBundle) // default for legacy packages: ignore
958 0 : continue;
959 : // no selection at all, so rethrow
960 : // no C++ rethrow after getCaughtException(),
961 : // see cppuhelper/exc_hlp.hxx:
962 0 : ::cppu::throwException(exc);
963 0 : }
964 : // ignore errors when revoking, although abort may have been
965 : // selected
966 0 : }
967 1 : }
968 1 : getMyBackend()->revokeEntryFromDb(getURL());
969 34 : }
970 34 : }
971 :
972 : //______________________________________________________________________________
973 0 : OUString BackendImpl::PackageImpl::getDescription()
974 : throw (deployment::ExtensionRemovedException, RuntimeException)
975 : {
976 0 : if (m_bRemoved)
977 0 : throw deployment::ExtensionRemovedException();
978 :
979 0 : const OUString sRelativeURL(getDescriptionInfoset().getLocalizedDescriptionURL());
980 0 : OUString sDescription;
981 0 : if (!sRelativeURL.isEmpty())
982 : {
983 0 : OUString sURL = m_url_expanded + "/" + sRelativeURL;
984 :
985 : try
986 : {
987 0 : sDescription = getTextFromURL( css::uno::Reference< css::ucb::XCommandEnvironment >(), sURL );
988 : }
989 0 : catch ( const css::deployment::DeploymentException& )
990 : {
991 : OSL_FAIL( OUStringToOString( ::comphelper::anyToString( ::cppu::getCaughtException() ), RTL_TEXTENCODING_UTF8 ).getStr() );
992 0 : }
993 : }
994 :
995 0 : if (!sDescription.isEmpty())
996 0 : return sDescription;
997 0 : return m_oldDescription;
998 : }
999 :
1000 : //______________________________________________________________________________
1001 0 : OUString BackendImpl::PackageImpl::getLicenseText()
1002 : throw (deployment::ExtensionRemovedException, RuntimeException)
1003 : {
1004 0 : if (m_bRemoved)
1005 0 : throw deployment::ExtensionRemovedException();
1006 :
1007 0 : OUString sLicense;
1008 0 : DescriptionInfoset aInfo = getDescriptionInfoset();
1009 :
1010 0 : ::boost::optional< SimpleLicenseAttributes > aSimplLicAttr = aInfo.getSimpleLicenseAttributes();
1011 0 : if ( aSimplLicAttr )
1012 : {
1013 0 : OUString aLicenseURL = aInfo.getLocalizedLicenseURL();
1014 :
1015 0 : if ( !aLicenseURL.isEmpty() )
1016 : {
1017 0 : OUString aFullURL = m_url_expanded + "/" + aLicenseURL;
1018 0 : sLicense = getTextFromURL( Reference< ucb::XCommandEnvironment >(), aFullURL);
1019 0 : }
1020 : }
1021 :
1022 0 : return sLicense;
1023 : }
1024 :
1025 : //______________________________________________________________________________
1026 0 : void BackendImpl::PackageImpl::exportTo(
1027 : OUString const & destFolderURL, OUString const & newTitle,
1028 : sal_Int32 nameClashAction, Reference<ucb::XCommandEnvironment> const & xCmdEnv )
1029 : throw (ucb::CommandFailedException,
1030 : deployment::ExtensionRemovedException,
1031 : ucb::CommandAbortedException, RuntimeException)
1032 : {
1033 0 : if (m_bRemoved)
1034 0 : throw deployment::ExtensionRemovedException();
1035 :
1036 : ::ucbhelper::Content sourceContent(
1037 0 : m_url_expanded, xCmdEnv, getMyBackend()->getComponentContext() );
1038 0 : OUString title(newTitle);
1039 0 : if (title.isEmpty())
1040 0 : sourceContent.getPropertyValue( "Title" ) >>= title;
1041 : OUString destURL( makeURL( destFolderURL, ::rtl::Uri::encode(
1042 : title, rtl_UriCharClassPchar,
1043 : rtl_UriEncodeIgnoreEscapes,
1044 0 : RTL_TEXTENCODING_UTF8 ) ) );
1045 :
1046 0 : if (nameClashAction == ucb::NameClash::ASK)
1047 : {
1048 0 : if (create_ucb_content(
1049 : 0, destURL, xCmdEnv, false /* no throw */ )) {
1050 0 : bool replace = false, abort = false;
1051 0 : if (! interactContinuation(
1052 : Any( ucb::NameClashResolveRequest(
1053 0 : "file already exists: " + title,
1054 : static_cast<OWeakObject *>(this),
1055 : task::InteractionClassification_QUERY,
1056 : destFolderURL, title, OUString() ) ),
1057 0 : ucb::XInteractionReplaceExistingData::static_type(), xCmdEnv,
1058 0 : &replace, &abort ) || !replace) {
1059 0 : return;
1060 : }
1061 : }
1062 : }
1063 0 : else if (nameClashAction != ucb::NameClash::OVERWRITE) {
1064 : throw ucb::CommandFailedException("unsupported nameClashAction!",
1065 0 : static_cast<OWeakObject *>(this), Any() );
1066 : }
1067 0 : erase_path( destURL, xCmdEnv );
1068 :
1069 0 : OUStringBuffer buf;
1070 0 : buf.appendAscii( "vnd.sun.star.zip://" );
1071 : buf.append( ::rtl::Uri::encode( destURL,
1072 : rtl_UriCharClassRegName,
1073 : rtl_UriEncodeIgnoreEscapes,
1074 0 : RTL_TEXTENCODING_UTF8 ) );
1075 0 : buf.append( static_cast<sal_Unicode>('/') );
1076 0 : OUString destFolder( buf.makeStringAndClear() );
1077 :
1078 : ::ucbhelper::Content destFolderContent(
1079 0 : destFolder, xCmdEnv, getMyBackend()->getComponentContext() );
1080 : {
1081 : // transfer every item of folder into zip:
1082 : Reference<sdbc::XResultSet> xResultSet(
1083 : sourceContent.createCursor(
1084 : Sequence<OUString>(),
1085 0 : ::ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS ) );
1086 0 : ProgressLevel progress( xCmdEnv, OUString() );
1087 0 : while (xResultSet->next())
1088 : {
1089 : ::ucbhelper::Content subContent(
1090 : Reference<ucb::XContentAccess>(
1091 0 : xResultSet, UNO_QUERY_THROW )->queryContent(),
1092 0 : xCmdEnv, getMyBackend()->getComponentContext() );
1093 0 : if (! destFolderContent.transferContent(
1094 : subContent, ::ucbhelper::InsertOperation_COPY,
1095 0 : OUString(), ucb::NameClash::OVERWRITE ))
1096 : throw RuntimeException( "UCB transferContent() failed!",
1097 0 : static_cast<OWeakObject *>(this) );
1098 0 : progress.update( Any() ); // animating progress bar
1099 0 : }
1100 : }
1101 :
1102 : // assure META-INF folder:
1103 0 : ::ucbhelper::Content metainfFolderContent;
1104 : create_folder( &metainfFolderContent,
1105 0 : makeURL( destFolderContent.getURL(), "META-INF" ),
1106 0 : xCmdEnv );
1107 :
1108 0 : if (m_legacyBundle)
1109 : {
1110 : // easy to migrate legacy bundles to new format:
1111 : // just export them once using a .oxt name!
1112 : // set detected media-types of any bundle item:
1113 :
1114 : // collect all manifest entries:
1115 0 : Sequence< Reference<deployment::XPackage> > bundle;
1116 : try {
1117 0 : bundle = getBundle( Reference<task::XAbortChannel>(), xCmdEnv );
1118 : }
1119 : // xxx todo: think about exception specs:
1120 0 : catch (const deployment::DeploymentException &) {
1121 : OSL_FAIL( OUStringToOString(
1122 : ::comphelper::anyToString(
1123 : ::cppu::getCaughtException() ),
1124 : RTL_TEXTENCODING_UTF8 ).getStr() );
1125 : }
1126 0 : catch (const lang::IllegalArgumentException & exc) {
1127 : (void) exc;
1128 : OSL_FAIL( OUStringToOString(
1129 : exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() );
1130 : }
1131 :
1132 0 : ::std::vector< Sequence<beans::PropertyValue> > manifest;
1133 0 : manifest.reserve( bundle.getLength() );
1134 0 : sal_Int32 baseURLlen = m_url_expanded.getLength();
1135 0 : Reference<deployment::XPackage> const *pbundle = bundle.getConstArray();
1136 0 : const OUString strMediaType( "MediaType" );
1137 0 : const OUString strFullPath( "FullPath" );
1138 0 : const OUString strIsFolder( "IsFolder" );
1139 0 : for ( sal_Int32 pos = bundle.getLength(); pos--; )
1140 : {
1141 0 : Reference<deployment::XPackage> const & xPackage = pbundle[ pos ];
1142 0 : OUString url_( expandUnoRcUrl( xPackage->getURL() ) );
1143 : OSL_ASSERT( url_.getLength() >= baseURLlen );
1144 0 : OUString fullPath;
1145 0 : if (url_.getLength() > baseURLlen)
1146 0 : fullPath = url_.copy( baseURLlen + 1 );
1147 : ::ucbhelper::Content ucbContent(
1148 0 : url_, xCmdEnv, getMyBackend()->getComponentContext() );
1149 0 : if (ucbContent.getPropertyValue(strIsFolder).get<bool>())
1150 0 : fullPath += "/";
1151 0 : Sequence<beans::PropertyValue> attribs( 2 );
1152 0 : beans::PropertyValue * pattribs = attribs.getArray();
1153 0 : pattribs[ 0 ].Name = strFullPath;
1154 0 : pattribs[ 0 ].Value <<= fullPath;
1155 0 : pattribs[ 1 ].Name = strMediaType;
1156 : const Reference<deployment::XPackageTypeInfo> xPackageType(
1157 0 : xPackage->getPackageType() );
1158 0 : OUString mediaType;
1159 : OSL_ASSERT( xPackageType.is() );
1160 0 : if (xPackageType.is())
1161 0 : mediaType = xPackageType->getMediaType();
1162 : else
1163 0 : mediaType = "unknown";
1164 0 : pattribs[ 1 ].Value <<= mediaType;
1165 0 : manifest.push_back( attribs );
1166 0 : }
1167 :
1168 : // write into pipe:
1169 : Reference<XComponentContext> xContext(
1170 0 : getMyBackend()->getComponentContext() );
1171 : Reference<packages::manifest::XManifestWriter> xManifestWriter =
1172 0 : packages::manifest::ManifestWriter::create( xContext );
1173 0 : Reference<io::XOutputStream> xPipe( io::Pipe::create(xContext), UNO_QUERY_THROW );
1174 0 : xManifestWriter->writeManifestSequence(
1175 0 : xPipe, comphelper::containerToSequence(manifest) );
1176 :
1177 : // write buffered pipe data to content:
1178 : ::ucbhelper::Content manifestContent(
1179 0 : makeURL( metainfFolderContent.getURL(), "manifest.xml" ),
1180 0 : xCmdEnv, getMyBackend()->getComponentContext() );
1181 : manifestContent.writeStream(
1182 : Reference<io::XInputStream>( xPipe, UNO_QUERY_THROW ),
1183 0 : true /* replace existing */ );
1184 : }
1185 : else
1186 : {
1187 : // overwrite manifest.xml:
1188 0 : ::ucbhelper::Content manifestContent;
1189 0 : if ( ! create_ucb_content(
1190 : &manifestContent,
1191 : makeURL( m_url_expanded, "META-INF/manifest.xml" ),
1192 0 : xCmdEnv, false ) )
1193 : {
1194 : OSL_FAIL( "### missing META-INF/manifest.xml file!" );
1195 0 : return;
1196 : }
1197 :
1198 0 : if (! metainfFolderContent.transferContent(
1199 : manifestContent, ::ucbhelper::InsertOperation_COPY,
1200 0 : OUString(), ucb::NameClash::OVERWRITE ))
1201 : throw RuntimeException( "UCB transferContent() failed!",
1202 0 : static_cast<OWeakObject *>(this) );
1203 : }
1204 :
1205 : // xxx todo: maybe obsolete in the future
1206 : try {
1207 0 : destFolderContent.executeCommand( "flush", Any() );
1208 : }
1209 0 : catch (const ucb::UnsupportedCommandException &) {
1210 0 : }
1211 : }
1212 :
1213 : //______________________________________________________________________________
1214 64 : sal_Bool BackendImpl::PackageImpl::isBundle() throw (RuntimeException)
1215 : {
1216 64 : return true;
1217 : }
1218 :
1219 : //______________________________________________________________________________
1220 230 : Sequence< Reference<deployment::XPackage> > BackendImpl::PackageImpl::getBundle(
1221 : Reference<task::XAbortChannel> const & xAbortChannel,
1222 : Reference<ucb::XCommandEnvironment> const & xCmdEnv )
1223 : throw (deployment::DeploymentException,
1224 : ucb::CommandFailedException, ucb::CommandAbortedException,
1225 : lang::IllegalArgumentException, RuntimeException)
1226 : {
1227 230 : Sequence< Reference<deployment::XPackage> > * pBundle = m_pBundle;
1228 230 : if (pBundle == 0)
1229 : {
1230 64 : t_packagevec bundle;
1231 64 : if (m_bRemoved)
1232 : {
1233 0 : bundle = getPackagesFromDb(xCmdEnv);
1234 : }
1235 : else
1236 : {
1237 : try {
1238 64 : if (m_legacyBundle)
1239 : {
1240 : // .zip legacy packages allow script.xlb, dialog.xlb in bundle
1241 : // root folder:
1242 0 : OUString mediaType;
1243 : // probe for script.xlb:
1244 0 : if (create_ucb_content(
1245 : 0, makeURL( m_url_expanded, "script.xlb" ),
1246 0 : xCmdEnv, false /* no throw */ )) {
1247 0 : mediaType = "application/vnd.sun.star.basic-library";
1248 : }
1249 : // probe for dialog.xlb:
1250 0 : else if (create_ucb_content(
1251 : 0, makeURL( m_url_expanded, "dialog.xlb" ),
1252 0 : xCmdEnv, false /* no throw */ ))
1253 0 : mediaType = "application/vnd.sun.star.dialog-library";
1254 :
1255 0 : if (!mediaType.isEmpty()) {
1256 : const Reference<deployment::XPackage> xPackage(
1257 0 : bindBundleItem( getURL(), mediaType, false, OUString(),
1258 0 : xCmdEnv ) );
1259 0 : if (xPackage.is())
1260 0 : bundle.push_back( xPackage );
1261 : // continue scanning:
1262 : }
1263 0 : scanLegacyBundle( bundle, getURL(),
1264 0 : AbortChannel::get(xAbortChannel), xCmdEnv );
1265 : }
1266 : else
1267 : {
1268 : // .oxt:
1269 64 : scanBundle( bundle, AbortChannel::get(xAbortChannel), xCmdEnv );
1270 : }
1271 :
1272 : }
1273 0 : catch (const RuntimeException &) {
1274 0 : throw;
1275 : }
1276 0 : catch (const ucb::CommandFailedException &) {
1277 0 : throw;
1278 : }
1279 0 : catch (const ucb::CommandAbortedException &) {
1280 0 : throw;
1281 : }
1282 0 : catch (const deployment::DeploymentException &) {
1283 0 : throw;
1284 : }
1285 0 : catch (const Exception &) {
1286 0 : Any exc( ::cppu::getCaughtException() );
1287 : throw deployment::DeploymentException(
1288 0 : "error scanning bundle: " + getURL(),
1289 0 : static_cast<OWeakObject *>(this), exc );
1290 : }
1291 : }
1292 :
1293 : // sort: schema before config data, typelibs before components:
1294 128 : Sequence< Reference<deployment::XPackage> > ret( bundle.size() );
1295 64 : Reference<deployment::XPackage> * pret = ret.getArray();
1296 64 : sal_Int32 lower_end = 0;
1297 64 : sal_Int32 upper_end = ret.getLength();
1298 64 : t_packagevec::const_iterator iPos( bundle.begin() );
1299 64 : t_packagevec::const_iterator const iEnd( bundle.end() );
1300 380 : for ( ; iPos != iEnd; ++iPos )
1301 : {
1302 : const Reference<deployment::XPackageTypeInfo> xPackageType(
1303 316 : (*iPos)->getPackageType() );
1304 : OSL_ASSERT( xPackageType.is() );
1305 316 : if (xPackageType.is())
1306 : {
1307 316 : const OUString mediaType( xPackageType->getMediaType() );
1308 442 : OUString type, subType;
1309 442 : INetContentTypeParameterList params;
1310 948 : if (INetContentTypes::parse( mediaType, type, subType, ¶ms ) &&
1311 822 : type.equalsIgnoreAsciiCase("application") &&
1312 631 : (subType.equalsIgnoreAsciiCase( "vnd.sun.star.uno-component") ||
1313 315 : subType.equalsIgnoreAsciiCase( "vnd.sun.star.configuration-data")))
1314 : {
1315 190 : --upper_end;
1316 190 : pret[ upper_end ] = *iPos;
1317 190 : continue;
1318 126 : }
1319 : }
1320 126 : pret[ lower_end ] = *iPos;
1321 126 : ++lower_end;
1322 126 : }
1323 : OSL_ASSERT( lower_end == upper_end );
1324 :
1325 128 : const ::osl::MutexGuard guard( getMutex() );
1326 64 : pBundle = m_pBundle;
1327 64 : if (pBundle == 0) {
1328 64 : m_bundle = ret;
1329 64 : pBundle = &m_bundle;
1330 : OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
1331 64 : m_pBundle = pBundle;
1332 64 : }
1333 : }
1334 : else {
1335 : OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
1336 : }
1337 230 : return *pBundle;
1338 : }
1339 :
1340 632 : inline bool isBundle_( OUString const & mediaType )
1341 : {
1342 : // xxx todo: additional parsing?
1343 1264 : return !mediaType.isEmpty() &&
1344 1264 : (mediaType.matchIgnoreAsciiCase( "application/vnd.sun.star.package-bundle") ||
1345 1264 : mediaType.matchIgnoreAsciiCase( "application/vnd.sun.star.legacy-package-bundle"));
1346 : }
1347 :
1348 : //______________________________________________________________________________
1349 316 : Reference<deployment::XPackage> BackendImpl::PackageImpl::bindBundleItem(
1350 : OUString const & url, OUString const & mediaType,
1351 : sal_Bool bRemoved, OUString const & identifier,
1352 : Reference<ucb::XCommandEnvironment> const & xCmdEnv,
1353 : bool notifyDetectionError )
1354 : {
1355 : // ignore any nested bundles:
1356 316 : if (isBundle_(mediaType))
1357 0 : return Reference<deployment::XPackage>();
1358 :
1359 316 : Reference<deployment::XPackage>xPackage;
1360 : try {
1361 : try {
1362 316 : xPackage.set( getMyBackend()->m_xRootRegistry->bindPackage(
1363 316 : url, mediaType, bRemoved, identifier, xCmdEnv ) );
1364 : OSL_ASSERT( xPackage.is() );
1365 0 : } catch (css::lang::IllegalArgumentException & e) {
1366 0 : css::uno::Any exc(cppu::getCaughtException());
1367 : throw css::lang::WrappedTargetException(
1368 0 : "wrapped: " + e.Message, e.Context, exc);
1369 : }
1370 : }
1371 0 : catch (const RuntimeException &) {
1372 0 : throw;
1373 : }
1374 0 : catch (const ucb::CommandFailedException &) {
1375 : // ignore already handled error
1376 : }
1377 0 : catch (const Exception &) {
1378 0 : const Any exc( ::cppu::getCaughtException() );
1379 0 : if (notifyDetectionError ||
1380 : !exc.isExtractableTo(
1381 : ::getCppuType( reinterpret_cast<
1382 0 : lang::IllegalArgumentException const *>(0) ) ))
1383 : {
1384 : interactContinuation(
1385 : Any( lang::WrappedTargetException("bundle item error!",
1386 : static_cast<OWeakObject *>(this), exc ) ),
1387 0 : task::XInteractionApprove::static_type(), xCmdEnv, 0, 0 );
1388 0 : }
1389 : }
1390 :
1391 316 : if (xPackage.is()) {
1392 : const Reference<deployment::XPackageTypeInfo> xPackageType(
1393 316 : xPackage->getPackageType() );
1394 : OSL_ASSERT( xPackageType.is() );
1395 : // ignore any nested bundles:
1396 316 : if (xPackageType.is() && isBundle_( xPackageType->getMediaType() ))
1397 0 : xPackage.clear();
1398 : }
1399 316 : return xPackage;
1400 : }
1401 :
1402 : //______________________________________________________________________________
1403 64 : void BackendImpl::PackageImpl::scanBundle(
1404 : t_packagevec & bundle,
1405 : ::rtl::Reference<AbortChannel> const & abortChannel,
1406 : Reference<ucb::XCommandEnvironment> const & xCmdEnv )
1407 : {
1408 : OSL_ASSERT( !m_legacyBundle );
1409 :
1410 64 : OUString mfUrl( makeURL( m_url_expanded, "META-INF/manifest.xml" ) );
1411 128 : ::ucbhelper::Content manifestContent;
1412 64 : if (! create_ucb_content(
1413 64 : &manifestContent, mfUrl, xCmdEnv, false /* no throw */ ))
1414 : {
1415 : SAL_WARN(
1416 : "desktop.deployment",
1417 : "cannot create UCB Content for <" << mfUrl << ">" );
1418 64 : return;
1419 : }
1420 :
1421 :
1422 64 : const LanguageTag& officeLocale = getOfficeLanguageTag();
1423 128 : const ::std::vector< OUString > officeFallbacks( officeLocale.getFallbackStrings());
1424 64 : const size_t nPenaltyMax = ::std::numeric_limits<size_t>::max();
1425 64 : size_t descrPenalty = nPenaltyMax;
1426 128 : OUString descrFile;
1427 :
1428 : const Reference<XComponentContext> xContext(
1429 128 : getMyBackend()->getComponentContext() );
1430 : Reference<packages::manifest::XManifestReader> xManifestReader =
1431 128 : packages::manifest::ManifestReader::create( xContext );
1432 : const Sequence< Sequence<beans::PropertyValue> > manifestSeq(
1433 128 : xManifestReader->readManifestSequence( manifestContent.openStream() ) );
1434 128 : const OUString packageRootURL( getURL() );
1435 444 : for ( sal_Int32 pos = manifestSeq.getLength(); pos--; )
1436 : {
1437 632 : OUString fullPath, mediaType;
1438 316 : Sequence<beans::PropertyValue> const & attribs = manifestSeq[ pos ];
1439 1264 : for ( sal_Int32 i = attribs.getLength(); i--; )
1440 : {
1441 632 : if (!(fullPath.isEmpty() || mediaType.isEmpty()))
1442 0 : break;
1443 632 : if ( attribs[i].Name == "FullPath" )
1444 316 : attribs[i].Value >>= fullPath;
1445 316 : else if ( attribs[i].Name == "MediaType" )
1446 316 : attribs[i].Value >>= mediaType;
1447 : }
1448 :
1449 316 : if ( fullPath.isEmpty() || mediaType.isEmpty() || mediaType == "text/xml" )// opt: exclude common text/xml
1450 0 : continue;
1451 :
1452 632 : OUString type, subType;
1453 632 : INetContentTypeParameterList params;
1454 316 : if (! INetContentTypes::parse( mediaType, type, subType, ¶ms ))
1455 0 : continue;
1456 :
1457 316 : INetContentTypeParameter const * param = params.find("platform");
1458 316 : if (param != 0 && !platform_fits( param->m_sValue ))
1459 0 : continue;
1460 632 : const OUString url( makeURL( packageRootURL, fullPath ) );
1461 :
1462 : // check for bundle description:
1463 632 : if (type.equalsIgnoreAsciiCase("application") &&
1464 316 : subType.equalsIgnoreAsciiCase( "vnd.sun.star.package-bundle-description"))
1465 : {
1466 : // check locale:
1467 0 : param = params.find("locale");
1468 0 : if (param == 0) {
1469 0 : if (descrFile.isEmpty())
1470 0 : descrFile = url;
1471 : }
1472 : else {
1473 : // match best locale:
1474 0 : LanguageTag descrTag( param->m_sValue);
1475 0 : if (officeLocale.getLanguage() == descrTag.getLanguage())
1476 : {
1477 0 : size_t nPenalty = nPenaltyMax;
1478 0 : const ::std::vector< OUString > descrFallbacks( descrTag.getFallbackStrings());
1479 0 : for (size_t o=0; o < officeFallbacks.size() && nPenalty == nPenaltyMax; ++o)
1480 : {
1481 0 : for (size_t d=0; d < descrFallbacks.size() && nPenalty == nPenaltyMax; ++d)
1482 : {
1483 0 : if (officeFallbacks[o] == descrFallbacks[d])
1484 : {
1485 : // The last fallbacks are always language-only
1486 : // fallbacks, so we _will_ have _some_ match if
1487 : // we ever entered the overall if() condition.
1488 0 : nPenalty = o * 1000 + d;
1489 0 : if (descrPenalty > nPenalty)
1490 : {
1491 0 : descrPenalty = nPenalty;
1492 0 : descrFile = url;
1493 : }
1494 : }
1495 : }
1496 0 : }
1497 0 : }
1498 : // TODO: we could break here if descrPenalty==0 for an exact
1499 : // match of officeLocale, but the previous code didn't; are
1500 : // there side effects?
1501 : }
1502 0 : continue;
1503 : }
1504 :
1505 316 : checkAborted( abortChannel );
1506 :
1507 : //We make sure that we only create one XPackage for a particular URL.
1508 : //Sometime programmers insert the same URL several times in the manifest
1509 : //which may lead to DisposedExceptions.
1510 316 : if (bundle.end() == std::find_if(bundle.begin(), bundle.end(), XPackage_eq(url)))
1511 : {
1512 : const Reference<deployment::XPackage> xPackage(
1513 316 : bindBundleItem( url, mediaType, false, OUString(), xCmdEnv ) );
1514 316 : if (xPackage.is())
1515 316 : bundle.push_back( xPackage );
1516 : }
1517 : else
1518 : {
1519 0 : fprintf(stderr, "manifest.xml contains a duplicate entry!\n");
1520 : }
1521 316 : }
1522 :
1523 64 : if (!descrFile.isEmpty())
1524 : {
1525 0 : ::ucbhelper::Content descrFileContent;
1526 0 : if (create_ucb_content( &descrFileContent, descrFile,
1527 : xCmdEnv, false /* no throw */ ))
1528 : {
1529 : // patch description:
1530 0 : ::rtl::ByteSequence bytes( readFile( descrFileContent ) );
1531 0 : OUStringBuffer buf;
1532 0 : if ( bytes.getLength() )
1533 : {
1534 : buf.append( OUString( reinterpret_cast<sal_Char const *>(
1535 0 : bytes.getConstArray() ),
1536 0 : bytes.getLength(), RTL_TEXTENCODING_UTF8 ) );
1537 : }
1538 : else
1539 : {
1540 0 : buf.append( Package::getDescription() );
1541 : }
1542 0 : m_oldDescription = buf.makeStringAndClear();
1543 0 : }
1544 64 : }
1545 : }
1546 :
1547 : //______________________________________________________________________________
1548 0 : void BackendImpl::PackageImpl::scanLegacyBundle(
1549 : t_packagevec & bundle,
1550 : OUString const & url,
1551 : ::rtl::Reference<AbortChannel> const & abortChannel,
1552 : Reference<ucb::XCommandEnvironment> const & xCmdEnv,
1553 : bool skip_registration )
1554 : {
1555 : ::ucbhelper::Content ucbContent(
1556 0 : url, xCmdEnv, getMyBackend()->getComponentContext() );
1557 :
1558 : // check for platform paths:
1559 0 : const OUString title( StrTitle::getTitle( ucbContent ) );
1560 0 : if (title.endsWithIgnoreAsciiCase( ".plt" ) &&
1561 0 : !platform_fits( title.copy( 0, title.getLength() - 4 ) )) {
1562 0 : return;
1563 : }
1564 0 : if (title.endsWithIgnoreAsciiCase("skip_registration") )
1565 0 : skip_registration = true;
1566 :
1567 0 : OUString ar [] = { OUString("Title"), OUString("IsFolder") };
1568 : Reference<sdbc::XResultSet> xResultSet(
1569 : ucbContent.createCursor(
1570 0 : Sequence<OUString>( ar, ARLEN(ar) ),
1571 0 : ::ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS ) );
1572 0 : while (xResultSet->next())
1573 : {
1574 0 : checkAborted( abortChannel );
1575 :
1576 0 : const Reference<sdbc::XRow> xRow( xResultSet, UNO_QUERY_THROW );
1577 : const OUString title_enc( ::rtl::Uri::encode(
1578 0 : xRow->getString( 1 /* Title */ ),
1579 : rtl_UriCharClassPchar,
1580 : rtl_UriEncodeIgnoreEscapes,
1581 0 : RTL_TEXTENCODING_UTF8 ) );
1582 0 : const OUString path( makeURL( url, title_enc ) );
1583 :
1584 0 : OUString mediaType;
1585 : const Reference<deployment::XPackage> xPackage(
1586 : bindBundleItem( path, OUString() /* detect */, false, OUString(),
1587 0 : xCmdEnv, false /* ignore detection errors */ ) );
1588 0 : if (xPackage.is()) {
1589 : const Reference<deployment::XPackageTypeInfo> xPackageType(
1590 0 : xPackage->getPackageType() );
1591 : OSL_ASSERT( xPackageType.is() );
1592 0 : if (xPackageType.is())
1593 0 : mediaType = xPackageType->getMediaType();
1594 :
1595 0 : if (skip_registration &&
1596 : // xxx todo: additional parsing?
1597 0 : mediaType.matchIgnoreAsciiCase("application/vnd.sun.star.uno-component"))
1598 0 : continue;
1599 :
1600 0 : bundle.push_back( xPackage );
1601 : }
1602 :
1603 0 : if (mediaType.isEmpty() ||
1604 : // script.xlb, dialog.xlb can be met everywhere:
1605 0 : mediaType.matchIgnoreAsciiCase("application/vnd.sun.star.basic-library") ||
1606 0 : mediaType.matchIgnoreAsciiCase("application/vnd.sun.star.dialog-library"))
1607 : {
1608 0 : if (xRow->getBoolean( 2 /* IsFolder */ )) { // recurse into folder:
1609 : scanLegacyBundle(
1610 0 : bundle, path, abortChannel, xCmdEnv, skip_registration );
1611 : }
1612 : }
1613 0 : }
1614 : }
1615 :
1616 35 : OUString BackendImpl::PackageImpl::getDisplayName()
1617 : throw (deployment::ExtensionRemovedException, RuntimeException)
1618 : {
1619 35 : if (m_bRemoved)
1620 0 : throw deployment::ExtensionRemovedException();
1621 :
1622 35 : OUString sName = getDescriptionInfoset().getLocalizedDisplayName();
1623 35 : if (sName.isEmpty())
1624 3 : return m_displayName;
1625 : else
1626 32 : return sName;
1627 : }
1628 :
1629 : ::std::vector<Reference<deployment::XPackage> >
1630 0 : BackendImpl::PackageImpl::getPackagesFromDb(
1631 : Reference<ucb::XCommandEnvironment> const & xCmdEnv)
1632 : {
1633 0 : ::std::vector<Reference<deployment::XPackage> > retVector;
1634 :
1635 : typedef ::std::vector< ::std::pair<OUString, OUString> >::const_iterator ITC;
1636 0 : for (ITC i = m_dbData.items.begin(); i != m_dbData.items.end(); ++i)
1637 : {
1638 : Reference<deployment::XPackage> xExtension =
1639 0 : bindBundleItem(i->first, i->second, true, m_identifier, xCmdEnv);
1640 : OSL_ASSERT(xExtension.is());
1641 0 : if (xExtension.is())
1642 0 : retVector.push_back(xExtension);
1643 0 : }
1644 :
1645 0 : return retVector;
1646 : }
1647 :
1648 : } // anon namespace
1649 :
1650 : //==============================================================================
1651 254 : Reference<deployment::XPackageRegistry> create(
1652 : Reference<deployment::XPackageRegistry> const & xRootRegistry,
1653 : OUString const & context, OUString const & cachePath, bool readOnly,
1654 : Reference<XComponentContext> const & xComponentContext )
1655 : {
1656 254 : Sequence<Any> args(cachePath.isEmpty() ? 1 : 3 );
1657 254 : args[ 0 ] <<= context;
1658 254 : if (!cachePath.isEmpty()) {
1659 254 : args[ 1 ] <<= cachePath;
1660 254 : args[ 2 ] <<= readOnly;
1661 : }
1662 254 : return new BackendImpl( args, xComponentContext, xRootRegistry );
1663 : }
1664 :
1665 : } // namespace bundle
1666 : } // namespace backend
1667 : } // namespace dp_registry
1668 :
1669 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|