bump product version to 4.1.6.2
[LibreOffice.git] / desktop / source / deployment / registry / component / dp_component.cxx
blob66cfd4b9bb89f6c8640d56837cdb2f5d04fb07a6
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "dp_component.hrc"
22 #include "dp_backend.h"
23 #include "dp_platform.hxx"
24 #include "dp_ucb.h"
25 #include "rtl/string.hxx"
26 #include "rtl/strbuf.hxx"
27 #include "rtl/ustrbuf.hxx"
28 #include "rtl/uri.hxx"
29 #include "cppuhelper/exc_hlp.hxx"
30 #include "ucbhelper/content.hxx"
31 #include "comphelper/anytostring.hxx"
32 #include "comphelper/servicedecl.hxx"
33 #include "comphelper/sequence.hxx"
34 #include "xmlscript/xml_helper.hxx"
35 #include "svl/inettype.hxx"
36 #include "com/sun/star/lang/WrappedTargetRuntimeException.hpp"
37 #include "com/sun/star/container/XNameContainer.hpp"
38 #include "com/sun/star/container/XSet.hpp"
39 #include "com/sun/star/registry/XSimpleRegistry.hpp"
40 #include "com/sun/star/registry/XImplementationRegistration.hpp"
41 #include "com/sun/star/loader/XImplementationLoader.hpp"
42 #include "com/sun/star/io/XInputStream.hpp"
43 #include "com/sun/star/ucb/NameClash.hpp"
44 #include "com/sun/star/util/theMacroExpander.hpp"
45 #include <list>
46 #include <boost/unordered_map.hpp>
47 #include <vector>
48 #include <memory>
49 #include <algorithm>
50 #include "dp_compbackenddb.hxx"
52 using namespace ::dp_misc;
53 using namespace ::com::sun::star;
54 using namespace ::com::sun::star::uno;
55 using namespace ::com::sun::star::ucb;
57 namespace dp_registry {
58 namespace backend {
59 namespace component {
60 namespace {
62 typedef ::std::list<OUString> t_stringlist;
63 typedef ::std::vector< ::std::pair<OUString, OUString> > t_stringpairvec;
65 #define IMPLEMENTATION_NAME "com.sun.star.comp.deployment.component.PackageRegistryBackend"
67 /** return a vector of bootstrap variables which have been provided
68 as command arguments.
70 ::std::vector<OUString> getCmdBootstrapVariables()
72 ::std::vector<OUString> ret;
73 sal_uInt32 count = osl_getCommandArgCount();
74 for (sal_uInt32 i = 0; i < count; i++)
76 OUString arg;
77 osl_getCommandArg(i, &arg.pData);
78 if (arg.match("-env:"))
79 ret.push_back(arg);
81 return ret;
84 bool jarManifestHeaderPresent(
85 OUString const & url, OUString const & name,
86 Reference<XCommandEnvironment> const & xCmdEnv )
88 OUStringBuffer buf;
89 buf.appendAscii( "vnd.sun.star.zip://" );
90 buf.append(
91 ::rtl::Uri::encode(
92 url, rtl_UriCharClassRegName, rtl_UriEncodeIgnoreEscapes,
93 RTL_TEXTENCODING_UTF8 ) );
94 buf.appendAscii( "/META-INF/MANIFEST.MF" );
95 ::ucbhelper::Content manifestContent;
96 OUString line;
97 return
98 create_ucb_content(
99 &manifestContent, buf.makeStringAndClear(), xCmdEnv,
100 false /* no throw */ )
101 && readLine( &line, name, manifestContent, RTL_TEXTENCODING_ASCII_US );
104 //==============================================================================
105 class BackendImpl : public ::dp_registry::backend::PackageRegistryBackend
107 class ComponentPackageImpl : public ::dp_registry::backend::Package
109 BackendImpl * getMyBackend() const;
111 const OUString m_loader;
113 enum reg {
114 REG_UNINIT, REG_VOID, REG_REGISTERED, REG_NOT_REGISTERED, REG_MAYBE_REGISTERED
115 } m_registered;
117 void getComponentInfo(
118 ComponentBackendDb::Data * data,
119 std::vector< css::uno::Reference< css::uno::XInterface > > *
120 factories,
121 Reference<XComponentContext> const & xContext );
123 void componentLiveInsertion(
124 ComponentBackendDb::Data const & data,
125 std::vector< css::uno::Reference< css::uno::XInterface > > const &
126 factories);
128 void componentLiveRemoval(ComponentBackendDb::Data const & data);
130 virtual void SAL_CALL disposing();
132 // Package
133 virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_(
134 ::osl::ResettableMutexGuard & guard,
135 ::rtl::Reference<AbortChannel> const & abortChannel,
136 Reference<XCommandEnvironment> const & xCmdEnv );
137 virtual void processPackage_(
138 ::osl::ResettableMutexGuard & guard,
139 bool registerPackage,
140 bool startup,
141 ::rtl::Reference<AbortChannel> const & abortChannel,
142 Reference<XCommandEnvironment> const & xCmdEnv );
144 const Reference<registry::XSimpleRegistry> getRDB() const;
146 public:
147 ComponentPackageImpl(
148 ::rtl::Reference<PackageRegistryBackend> const & myBackend,
149 OUString const & url, OUString const & name,
150 Reference<deployment::XPackageTypeInfo> const & xPackageType,
151 OUString const & loader, bool bRemoved,
152 OUString const & identifier);
154 friend class ComponentPackageImpl;
156 class ComponentsPackageImpl : public ::dp_registry::backend::Package
158 BackendImpl * getMyBackend() const;
160 // Package
161 virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_(
162 ::osl::ResettableMutexGuard & guard,
163 ::rtl::Reference<AbortChannel> const & abortChannel,
164 Reference<XCommandEnvironment> const & xCmdEnv );
165 virtual void processPackage_(
166 ::osl::ResettableMutexGuard & guard,
167 bool registerPackage,
168 bool startup,
169 ::rtl::Reference<AbortChannel> const & abortChannel,
170 Reference<XCommandEnvironment> const & xCmdEnv );
171 public:
172 ComponentsPackageImpl(
173 ::rtl::Reference<PackageRegistryBackend> const & myBackend,
174 OUString const & url, OUString const & name,
175 Reference<deployment::XPackageTypeInfo> const & xPackageType,
176 bool bRemoved, OUString const & identifier);
178 friend class ComponentsPackageImpl;
180 class TypelibraryPackageImpl : public ::dp_registry::backend::Package
182 BackendImpl * getMyBackend() const;
184 const bool m_jarFile;
186 virtual void SAL_CALL disposing();
188 // Package
189 virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_(
190 ::osl::ResettableMutexGuard & guard,
191 ::rtl::Reference<AbortChannel> const & abortChannel,
192 Reference<XCommandEnvironment> const & xCmdEnv );
193 virtual void processPackage_(
194 ::osl::ResettableMutexGuard & guard,
195 bool registerPackage,
196 bool startup,
197 ::rtl::Reference<AbortChannel> const & abortChannel,
198 Reference<XCommandEnvironment> const & xCmdEnv );
200 public:
201 TypelibraryPackageImpl(
202 ::rtl::Reference<PackageRegistryBackend> const & myBackend,
203 OUString const & url, OUString const & name,
204 Reference<deployment::XPackageTypeInfo> const & xPackageType,
205 bool jarFile, bool bRemoved,
206 OUString const & identifier);
208 friend class TypelibraryPackageImpl;
210 /** Serves for unregistering packages that were registered on a
211 different platform. This can happen if one has remotely mounted
212 /home, for example.
214 class OtherPlatformPackageImpl : public ::dp_registry::backend::Package
216 public:
217 OtherPlatformPackageImpl(
218 ::rtl::Reference<PackageRegistryBackend> const & myBackend,
219 OUString const & url, OUString const & name,
220 Reference<deployment::XPackageTypeInfo> const & xPackageType,
221 bool bRemoved, OUString const & identifier, OUString const& rPlatform);
223 private:
224 BackendImpl * getMyBackend() const;
226 const Reference<registry::XSimpleRegistry> impl_openRDB() const;
227 const Reference<XInterface> impl_createInstance(OUString const& rService) const;
229 // Package
230 virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_(
231 ::osl::ResettableMutexGuard & guard,
232 ::rtl::Reference<AbortChannel> const & abortChannel,
233 Reference<XCommandEnvironment> const & xCmdEnv );
234 virtual void processPackage_(
235 ::osl::ResettableMutexGuard & guard,
236 bool registerPackage,
237 bool startup,
238 ::rtl::Reference<AbortChannel> const & abortChannel,
239 Reference<XCommandEnvironment> const & xCmdEnv );
241 private:
242 OUString const m_aPlatform;
244 friend class OtherPlatformPackageImpl;
246 t_stringlist m_jar_typelibs;
247 t_stringlist m_rdb_typelibs;
248 t_stringlist m_components;
250 enum RcItem { RCITEM_JAR_TYPELIB, RCITEM_RDB_TYPELIB, RCITEM_COMPONENTS };
252 t_stringlist & getRcItemList( RcItem kind ) {
253 switch (kind)
255 case RCITEM_JAR_TYPELIB:
256 return m_jar_typelibs;
257 case RCITEM_RDB_TYPELIB:
258 return m_rdb_typelibs;
259 default: // case RCITEM_COMPONENTS
260 return m_components;
264 bool m_unorc_inited;
265 bool m_unorc_modified;
266 bool bSwitchedRdbFiles;
268 typedef ::boost::unordered_map< OUString, Reference<XInterface>,
269 OUStringHash > t_string2object;
270 t_string2object m_backendObjects;
272 // PackageRegistryBackend
273 virtual Reference<deployment::XPackage> bindPackage_(
274 OUString const & url, OUString const & mediaType,
275 sal_Bool bRemoved, OUString const & identifier,
276 Reference<XCommandEnvironment> const & xCmdEnv );
278 virtual void SAL_CALL disposing();
280 const Reference<deployment::XPackageTypeInfo> m_xDynComponentTypeInfo;
281 const Reference<deployment::XPackageTypeInfo> m_xJavaComponentTypeInfo;
282 const Reference<deployment::XPackageTypeInfo> m_xPythonComponentTypeInfo;
283 const Reference<deployment::XPackageTypeInfo> m_xComponentsTypeInfo;
284 const Reference<deployment::XPackageTypeInfo> m_xRDBTypelibTypeInfo;
285 const Reference<deployment::XPackageTypeInfo> m_xJavaTypelibTypeInfo;
286 Sequence< Reference<deployment::XPackageTypeInfo> > m_typeInfos;
288 OUString m_commonRDB;
289 OUString m_nativeRDB;
291 //URLs of the original rdbs (before any switching):
292 OUString m_commonRDB_orig;
293 OUString m_nativeRDB_orig;
295 std::auto_ptr<ComponentBackendDb> m_backendDb;
297 void addDataToDb(OUString const & url, ComponentBackendDb::Data const & data);
298 ComponentBackendDb::Data readDataFromDb(OUString const & url);
299 void revokeEntryFromDb(OUString const & url);
301 Reference<registry::XSimpleRegistry> m_xCommonRDB;
302 Reference<registry::XSimpleRegistry> m_xNativeRDB;
304 void unorc_verify_init( Reference<XCommandEnvironment> const & xCmdEnv );
305 void unorc_flush( Reference<XCommandEnvironment> const & xCmdEnv );
307 Reference<XInterface> getObject( OUString const & id );
308 Reference<XInterface> insertObject(
309 OUString const & id, Reference<XInterface> const & xObject );
310 void releaseObject( OUString const & id );
312 bool addToUnoRc( RcItem kind, OUString const & url,
313 Reference<XCommandEnvironment> const & xCmdEnv );
314 bool removeFromUnoRc( RcItem kind, OUString const & url,
315 Reference<XCommandEnvironment> const & xCmdEnv );
316 bool hasInUnoRc( RcItem kind, OUString const & url );
318 css::uno::Reference< css::uno::XComponentContext > getRootContext() const;
320 public:
321 BackendImpl( Sequence<Any> const & args,
322 Reference<XComponentContext> const & xComponentContext );
324 // XPackageRegistry
325 virtual Sequence< Reference<deployment::XPackageTypeInfo> > SAL_CALL
326 getSupportedPackageTypes() throw (RuntimeException);
328 virtual void SAL_CALL packageRemoved(OUString const & url, OUString const & mediaType)
329 throw (deployment::DeploymentException,
330 uno::RuntimeException);
332 using PackageRegistryBackend::disposing;
334 //Will be called from ComponentPackageImpl
335 void initServiceRdbFiles();
338 //______________________________________________________________________________
340 BackendImpl::ComponentPackageImpl::ComponentPackageImpl(
341 ::rtl::Reference<PackageRegistryBackend> const & myBackend,
342 OUString const & url, OUString const & name,
343 Reference<deployment::XPackageTypeInfo> const & xPackageType,
344 OUString const & loader, bool bRemoved,
345 OUString const & identifier)
346 : Package( myBackend, url, name, name /* display-name */,
347 xPackageType, bRemoved, identifier),
348 m_loader( loader ),
349 m_registered( REG_UNINIT )
352 const Reference<registry::XSimpleRegistry>
353 BackendImpl::ComponentPackageImpl::getRDB() const
355 BackendImpl * that = getMyBackend();
357 //Late "initialization" of the services rdb files
358 //This is to prevent problems when running several
359 //instances of OOo with root rights in parallel. This
360 //would otherwise cause problems when copying the rdbs.
361 //See http://qa.openoffice.org/issues/show_bug.cgi?id=99257
363 const ::osl::MutexGuard guard( getMutex() );
364 if (!that->bSwitchedRdbFiles)
366 that->bSwitchedRdbFiles = true;
367 that->initServiceRdbFiles();
370 if ( m_loader == "com.sun.star.loader.SharedLibrary" )
371 return that->m_xNativeRDB;
372 else
373 return that->m_xCommonRDB;
376 BackendImpl * BackendImpl::ComponentPackageImpl::getMyBackend() const
378 BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get());
379 if (NULL == pBackend)
381 //Throws a DisposedException
382 check();
383 //We should never get here...
384 throw RuntimeException(
385 "Failed to get the BackendImpl",
386 static_cast<OWeakObject*>(const_cast<ComponentPackageImpl *>(this)));
388 return pBackend;
392 //______________________________________________________________________________
393 void BackendImpl::ComponentPackageImpl::disposing()
395 Package::disposing();
398 //______________________________________________________________________________
399 void BackendImpl::TypelibraryPackageImpl::disposing()
401 Package::disposing();
404 //______________________________________________________________________________
405 void BackendImpl::disposing()
407 try {
408 m_backendObjects = t_string2object();
409 if (m_xNativeRDB.is()) {
410 m_xNativeRDB->close();
411 m_xNativeRDB.clear();
413 if (m_xCommonRDB.is()) {
414 m_xCommonRDB->close();
415 m_xCommonRDB.clear();
417 unorc_flush( Reference<XCommandEnvironment>() );
419 PackageRegistryBackend::disposing();
421 catch (const RuntimeException &) {
422 throw;
424 catch (const Exception &) {
425 Any exc( ::cppu::getCaughtException() );
426 throw lang::WrappedTargetRuntimeException(
427 "caught unexpected exception while disposing...",
428 static_cast<OWeakObject *>(this), exc );
433 void BackendImpl::initServiceRdbFiles()
435 const Reference<XCommandEnvironment> xCmdEnv;
437 ::ucbhelper::Content cacheDir( getCachePath(), xCmdEnv, m_xComponentContext );
438 ::ucbhelper::Content oldRDB;
439 // switch common rdb:
440 if (!m_commonRDB_orig.isEmpty())
442 create_ucb_content(
443 &oldRDB, makeURL( getCachePath(), m_commonRDB_orig),
444 xCmdEnv, false /* no throw */ );
446 m_commonRDB = m_commonRDB_orig == "common.rdb" ? OUString("common_.rdb") : OUString("common.rdb");
447 if (oldRDB.get().is())
449 if (! cacheDir.transferContent(
450 oldRDB, ::ucbhelper::InsertOperation_COPY,
451 m_commonRDB, NameClash::OVERWRITE ))
454 throw RuntimeException( "UCB transferContent() failed!", 0 );
456 oldRDB = ::ucbhelper::Content();
458 // switch native rdb:
459 if (!m_nativeRDB_orig.isEmpty())
461 create_ucb_content(
462 &oldRDB, makeURL(getCachePath(), m_nativeRDB_orig),
463 xCmdEnv, false /* no throw */ );
465 const OUString plt_rdb( getPlatformString() + ".rdb" );
466 const OUString plt_rdb_( getPlatformString() + "_.rdb" );
467 m_nativeRDB = (m_nativeRDB_orig == plt_rdb ) ? plt_rdb_ : plt_rdb;
468 if (oldRDB.get().is())
470 if (! cacheDir.transferContent(
471 oldRDB, ::ucbhelper::InsertOperation_COPY,
472 m_nativeRDB, NameClash::OVERWRITE ))
473 throw RuntimeException( "UCB transferContent() failed!", 0 );
476 // UNO is bootstrapped, flush for next process start:
477 m_unorc_modified = true;
478 unorc_flush( Reference<XCommandEnvironment>() );
481 // common rdb for java, native rdb for shared lib components
482 if (!m_commonRDB.isEmpty()) {
483 m_xCommonRDB.set(
484 m_xComponentContext->getServiceManager()
485 ->createInstanceWithContext(
486 "com.sun.star.registry.SimpleRegistry",
487 m_xComponentContext ), UNO_QUERY_THROW );
488 m_xCommonRDB->open(
489 makeURL( expandUnoRcUrl(getCachePath()), m_commonRDB ),
490 false, true);
492 if (!m_nativeRDB.isEmpty()) {
493 m_xNativeRDB.set(
494 m_xComponentContext->getServiceManager()
495 ->createInstanceWithContext(
496 "com.sun.star.registry.SimpleRegistry",
497 m_xComponentContext ), UNO_QUERY_THROW );
498 m_xNativeRDB->open(
499 makeURL( expandUnoRcUrl(getCachePath()), m_nativeRDB ),
500 false, true);
504 BackendImpl::BackendImpl(
505 Sequence<Any> const & args,
506 Reference<XComponentContext> const & xComponentContext )
507 : PackageRegistryBackend( args, xComponentContext ),
508 m_unorc_inited( false ),
509 m_unorc_modified( false ),
510 bSwitchedRdbFiles(false),
511 m_xDynComponentTypeInfo( new Package::TypeInfo(
512 "application/vnd.sun.star.uno-component;type=native;platform=" +
513 getPlatformString(),
514 OUString("*") + OUString(SAL_DLLEXTENSION),
515 getResourceString(RID_STR_DYN_COMPONENT),
516 RID_IMG_COMPONENT) ),
517 m_xJavaComponentTypeInfo( new Package::TypeInfo(
518 "application/vnd.sun.star.uno-component;type=Java",
519 "*.jar",
520 getResourceString(RID_STR_JAVA_COMPONENT),
521 RID_IMG_JAVA_COMPONENT) ),
522 m_xPythonComponentTypeInfo( new Package::TypeInfo(
523 "application/vnd.sun.star.uno-component;type=Python",
524 "*.py",
525 getResourceString(
526 RID_STR_PYTHON_COMPONENT),
527 RID_IMG_COMPONENT ) ),
528 m_xComponentsTypeInfo( new Package::TypeInfo(
529 "application/vnd.sun.star.uno-components",
530 "*.components",
531 getResourceString(RID_STR_COMPONENTS),
532 RID_IMG_COMPONENT ) ),
533 m_xRDBTypelibTypeInfo( new Package::TypeInfo(
534 "application/vnd.sun.star.uno-typelibrary;type=RDB",
535 "*.rdb",
536 getResourceString(RID_STR_RDB_TYPELIB),
537 RID_IMG_TYPELIB ) ),
538 m_xJavaTypelibTypeInfo( new Package::TypeInfo(
539 "application/vnd.sun.star.uno-typelibrary;type=Java",
540 "*.jar",
541 getResourceString(RID_STR_JAVA_TYPELIB),
542 RID_IMG_JAVA_TYPELIB ) ),
543 m_typeInfos( 6 )
545 m_typeInfos[ 0 ] = m_xDynComponentTypeInfo;
546 m_typeInfos[ 1 ] = m_xJavaComponentTypeInfo;
547 m_typeInfos[ 2 ] = m_xPythonComponentTypeInfo;
548 m_typeInfos[ 3 ] = m_xComponentsTypeInfo;
549 m_typeInfos[ 4 ] = m_xRDBTypelibTypeInfo;
550 m_typeInfos[ 5 ] = m_xJavaTypelibTypeInfo;
552 const Reference<XCommandEnvironment> xCmdEnv;
554 if (transientMode())
556 // in-mem rdbs:
557 // common rdb for java, native rdb for shared lib components
558 m_xCommonRDB.set(
559 xComponentContext->getServiceManager()->createInstanceWithContext(
560 "com.sun.star.registry.SimpleRegistry",
561 xComponentContext ), UNO_QUERY_THROW );
562 m_xCommonRDB->open( OUString() /* in-mem */,
563 false /* ! read-only */, true /* create */ );
564 m_xNativeRDB.set(
565 xComponentContext->getServiceManager()->createInstanceWithContext(
566 "com.sun.star.registry.SimpleRegistry",
567 xComponentContext ), UNO_QUERY_THROW );
568 m_xNativeRDB->open( OUString() /* in-mem */,
569 false /* ! read-only */, true /* create */ );
571 else
573 unorc_verify_init( xCmdEnv );
574 OUString dbFile = makeURL(getCachePath(), "backenddb.xml");
575 m_backendDb.reset(
576 new ComponentBackendDb(getComponentContext(), dbFile));
580 void BackendImpl::addDataToDb(
581 OUString const & url, ComponentBackendDb::Data const & data)
583 if (m_backendDb.get())
584 m_backendDb->addEntry(url, data);
587 ComponentBackendDb::Data BackendImpl::readDataFromDb(OUString const & url)
589 ComponentBackendDb::Data data;
590 if (m_backendDb.get())
591 data = m_backendDb->getEntry(url);
592 return data;
595 void BackendImpl::revokeEntryFromDb(OUString const & url)
597 if (m_backendDb.get())
598 m_backendDb->revokeEntry(url);
601 // XPackageRegistry
602 //______________________________________________________________________________
603 Sequence< Reference<deployment::XPackageTypeInfo> >
604 BackendImpl::getSupportedPackageTypes() throw (RuntimeException)
606 return m_typeInfos;
609 void BackendImpl::packageRemoved(OUString const & url, OUString const & /*mediaType*/)
610 throw (deployment::DeploymentException,
611 uno::RuntimeException)
613 if (m_backendDb.get())
614 m_backendDb->removeEntry(url);
617 // PackageRegistryBackend
618 //______________________________________________________________________________
619 Reference<deployment::XPackage> BackendImpl::bindPackage_(
620 OUString const & url, OUString const & mediaType_,
621 sal_Bool bRemoved, OUString const & identifier,
622 Reference<XCommandEnvironment> const & xCmdEnv )
624 OUString mediaType(mediaType_);
625 if ( mediaType.isEmpty() || mediaType == "application/vnd.sun.star.uno-component" || mediaType == "application/vnd.sun.star.uno-typelibrary" )
627 // detect exact media-type:
628 ::ucbhelper::Content ucbContent;
629 if (create_ucb_content( &ucbContent, url, xCmdEnv )) {
630 const OUString title( StrTitle::getTitle( ucbContent ) );
631 if (title.endsWithIgnoreAsciiCase(SAL_DLLEXTENSION))
633 mediaType = "application/vnd.sun.star.uno-component;type=native;platform=" +
634 getPlatformString();
636 else if (title.endsWithIgnoreAsciiCase(".jar"))
638 if (jarManifestHeaderPresent(
639 url, "RegistrationClassName", xCmdEnv ))
640 mediaType = "application/vnd.sun.star.uno-component;type=Java";
641 if (mediaType.isEmpty())
642 mediaType = "application/vnd.sun.star.uno-typelibrary;type=Java";
644 else if (title.endsWithIgnoreAsciiCase(".py"))
645 mediaType = "application/vnd.sun.star.uno-component;type=Python";
646 else if (title.endsWithIgnoreAsciiCase(".rdb"))
647 mediaType = "application/vnd.sun.star.uno-typelibrary;type=RDB";
649 if (mediaType.isEmpty())
650 throw lang::IllegalArgumentException(
651 StrCannotDetectMediaType::get() + url,
652 static_cast<OWeakObject *>(this), static_cast<sal_Int16>(-1) );
655 OUString type, subType;
656 INetContentTypeParameterList params;
657 if (INetContentTypes::parse( mediaType, type, subType, &params ))
659 if (type.equalsIgnoreAsciiCase("application"))
661 OUString name;
662 if (!bRemoved)
664 ::ucbhelper::Content ucbContent( url, xCmdEnv, m_xComponentContext );
665 name = StrTitle::getTitle( ucbContent );
668 if (subType.equalsIgnoreAsciiCase("vnd.sun.star.uno-component"))
670 // xxx todo: probe and evaluate component xml description
672 INetContentTypeParameter const * param = params.find(OString("platform"));
673 bool bPlatformFits(param == 0);
674 String aPlatform;
675 if (!bPlatformFits) // platform is specified, we have to check
677 aPlatform = param->m_sValue;
678 bPlatformFits = platform_fits(aPlatform);
680 // If the package is being removed, do not care whether
681 // platform fits. We won't be using it anyway.
682 if (bPlatformFits || bRemoved) {
683 param = params.find(OString("type"));
684 if (param != 0)
686 String const & value = param->m_sValue;
687 if (value.EqualsIgnoreCaseAscii("native")) {
688 if (bPlatformFits)
689 return new BackendImpl::ComponentPackageImpl(
690 this, url, name, m_xDynComponentTypeInfo,
691 "com.sun.star.loader.SharedLibrary",
692 bRemoved, identifier);
693 else
694 return new BackendImpl::OtherPlatformPackageImpl(
695 this, url, name, m_xDynComponentTypeInfo,
696 bRemoved, identifier, aPlatform);
698 if (value.EqualsIgnoreCaseAscii("Java")) {
699 return new BackendImpl::ComponentPackageImpl(
700 this, url, name, m_xJavaComponentTypeInfo,
701 "com.sun.star.loader.Java2",
702 bRemoved, identifier);
704 if (value.EqualsIgnoreCaseAscii("Python")) {
705 return new BackendImpl::ComponentPackageImpl(
706 this, url, name, m_xPythonComponentTypeInfo,
707 "com.sun.star.loader.Python",
708 bRemoved, identifier);
713 else if (subType.equalsIgnoreAsciiCase("vnd.sun.star.uno-components"))
715 INetContentTypeParameter const * param = params.find(OString("platform"));
716 if (param == 0 || platform_fits( param->m_sValue )) {
717 return new BackendImpl::ComponentsPackageImpl(
718 this, url, name, m_xComponentsTypeInfo, bRemoved,
719 identifier);
722 else if (subType.equalsIgnoreAsciiCase( "vnd.sun.star.uno-typelibrary"))
724 INetContentTypeParameter const * param = params.find(OString("type"));
725 if (param != 0) {
726 String const & value = param->m_sValue;
727 if (value.EqualsIgnoreCaseAscii("RDB"))
729 return new BackendImpl::TypelibraryPackageImpl(
730 this, url, name, m_xRDBTypelibTypeInfo,
731 false /* rdb */, bRemoved, identifier);
733 if (value.EqualsIgnoreCaseAscii("Java")) {
734 return new BackendImpl::TypelibraryPackageImpl(
735 this, url, name, m_xJavaTypelibTypeInfo,
736 true /* jar */, bRemoved, identifier);
742 throw lang::IllegalArgumentException(
743 StrUnsupportedMediaType::get() + mediaType,
744 static_cast<OWeakObject *>(this),
745 static_cast<sal_Int16>(-1) );
749 //______________________________________________________________________________
750 void BackendImpl::unorc_verify_init(
751 Reference<XCommandEnvironment> const & xCmdEnv )
753 if (transientMode())
754 return;
755 const ::osl::MutexGuard guard( getMutex() );
756 if (! m_unorc_inited)
758 // common rc:
759 ::ucbhelper::Content ucb_content;
760 if (create_ucb_content(
761 &ucb_content,
762 makeURL( getCachePath(), "unorc" ),
763 xCmdEnv, false /* no throw */ ))
765 OUString line;
766 if (readLine( &line, "UNO_JAVA_CLASSPATH=", ucb_content,
767 RTL_TEXTENCODING_UTF8 ))
769 sal_Int32 index = sizeof ("UNO_JAVA_CLASSPATH=") - 1;
770 do {
771 OUString token( line.getToken( 0, ' ', index ).trim() );
772 if (!token.isEmpty())
774 if (create_ucb_content(
775 0, expandUnoRcTerm(token), xCmdEnv,
776 false /* no throw */ ))
778 //The jar file may not exist anymore if a shared or bundled
779 //extension was removed, but it can still be in the unorc
780 //After running XExtensionManager::synchronize, the unorc is
781 //cleaned up
782 m_jar_typelibs.push_back( token );
786 while (index >= 0);
788 if (readLine( &line, "UNO_TYPES=", ucb_content,
789 RTL_TEXTENCODING_UTF8 )) {
790 sal_Int32 index = sizeof ("UNO_TYPES=") - 1;
791 do {
792 OUString token( line.getToken( 0, ' ', index ).trim() );
793 if (!token.isEmpty())
795 if (token[ 0 ] == '?')
796 token = token.copy( 1 );
797 if (create_ucb_content(
798 0, expandUnoRcTerm(token), xCmdEnv,
799 false /* no throw */ ))
801 //The RDB file may not exist anymore if a shared or bundled
802 //extension was removed, but it can still be in the unorc.
803 //After running XExtensionManager::synchronize, the unorc is
804 //cleaned up
805 m_rdb_typelibs.push_back( token );
809 while (index >= 0);
811 if (readLine( &line, "UNO_SERVICES=", ucb_content,
812 RTL_TEXTENCODING_UTF8 ))
814 // The UNO_SERVICES line always has the BNF form
815 // "UNO_SERVICES="
816 // ("?$ORIGIN/" <common-rdb>)? -- first
817 // "${$ORIGIN/${_OS}_${_ARCH}rc:UNO_SERVICES}"? -- second
818 // ("?" ("BUNDLED_EXTENSIONS" | -- third
819 // "UNO_SHARED_PACKAGES_CACHE" | "UNO_USER_PACKAGES_CACHE")
820 // ...)*
821 // so can unambiguously be split into its thre parts:
822 int state = 1;
823 for (sal_Int32 i = RTL_CONSTASCII_LENGTH("UNO_SERVICES=");
824 i >= 0;)
826 OUString token(line.getToken(0, ' ', i));
827 if (!token.isEmpty())
829 if (state == 1 && token.match("?$ORIGIN/"))
831 m_commonRDB_orig = token.copy(
832 RTL_CONSTASCII_LENGTH("?$ORIGIN/"));
833 state = 2;
835 else if ( state <= 2 && token == "${$ORIGIN/${_OS}_${_ARCH}rc:UNO_SERVICES}" )
837 state = 3;
839 else
841 if (token[0] == '?')
843 token = token.copy(1);
845 m_components.push_back(token);
846 state = 3;
852 // native rc:
853 if (create_ucb_content(
854 &ucb_content,
855 makeURL( getCachePath(), getPlatformString() + "rc"),
856 xCmdEnv, false /* no throw */ )) {
857 if (readLine( &line, "UNO_SERVICES=", ucb_content,
858 RTL_TEXTENCODING_UTF8 )) {
859 m_nativeRDB_orig = line.copy(
860 sizeof ("UNO_SERVICES=?$ORIGIN/") - 1 );
864 m_unorc_modified = false;
865 m_unorc_inited = true;
869 //______________________________________________________________________________
870 void BackendImpl::unorc_flush( Reference<XCommandEnvironment> const & xCmdEnv )
872 if (transientMode())
873 return;
874 if (!m_unorc_inited || !m_unorc_modified)
875 return;
877 OStringBuffer buf;
879 buf.append("ORIGIN=");
880 OUString sOrigin = dp_misc::makeRcTerm(m_cachePath);
881 OString osOrigin = OUStringToOString(sOrigin, RTL_TEXTENCODING_UTF8);
882 buf.append(osOrigin);
883 buf.append(LF);
885 if (! m_jar_typelibs.empty())
887 t_stringlist::const_iterator iPos( m_jar_typelibs.begin() );
888 t_stringlist::const_iterator const iEnd( m_jar_typelibs.end() );
889 buf.append( "UNO_JAVA_CLASSPATH=" );
890 while (iPos != iEnd) {
891 // encoded ASCII file-urls:
892 const OString item(
893 OUStringToOString( *iPos, RTL_TEXTENCODING_ASCII_US ) );
894 buf.append( item );
895 ++iPos;
896 if (iPos != iEnd)
897 buf.append( ' ' );
899 buf.append(LF);
901 if (! m_rdb_typelibs.empty())
903 t_stringlist::const_iterator iPos( m_rdb_typelibs.begin() );
904 t_stringlist::const_iterator const iEnd( m_rdb_typelibs.end() );
905 buf.append( "UNO_TYPES=" );
906 while (iPos != iEnd) {
907 buf.append( '?' );
908 // encoded ASCII file-urls:
909 const OString item(
910 OUStringToOString( *iPos, RTL_TEXTENCODING_ASCII_US ) );
911 buf.append( item );
912 ++iPos;
913 if (iPos != iEnd)
914 buf.append( ' ' );
916 buf.append(LF);
919 // If we duplicated the common or native rdb then we must use those urls
920 //otherwise we use those of the original files. That is, m_commonRDB_orig
921 //and m_nativeRDB_orig;
922 OUString sCommonRDB(m_commonRDB.isEmpty() ? m_commonRDB_orig : m_commonRDB );
923 OUString sNativeRDB(m_nativeRDB.isEmpty() ? m_nativeRDB_orig : m_nativeRDB );
925 if (!sCommonRDB.isEmpty() || !sNativeRDB.isEmpty() ||
926 !m_components.empty())
928 buf.append( "UNO_SERVICES=" );
929 bool space = false;
930 if (!sCommonRDB.isEmpty())
932 buf.append( "?$ORIGIN/" );
933 buf.append( OUStringToOString(
934 sCommonRDB, RTL_TEXTENCODING_ASCII_US ) );
935 space = true;
937 if (!sNativeRDB.isEmpty())
939 if (space)
941 buf.append(' ');
943 buf.append( "${$ORIGIN/${_OS}_${_ARCH}rc:UNO_SERVICES}" );
944 space = true;
946 // write native rc:
947 OStringBuffer buf2;
948 buf2.append("ORIGIN=");
949 buf2.append(osOrigin);
950 buf2.append(LF);
951 buf2.append( "UNO_SERVICES=?$ORIGIN/" );
952 buf2.append( OUStringToOString(
953 sNativeRDB, RTL_TEXTENCODING_ASCII_US ) );
954 buf2.append(LF);
956 const Reference<io::XInputStream> xData(
957 ::xmlscript::createInputStream(
958 ::rtl::ByteSequence(
959 reinterpret_cast<sal_Int8 const *>(buf2.getStr()),
960 buf2.getLength() ) ) );
961 ::ucbhelper::Content ucb_content(
962 makeURL( getCachePath(), getPlatformString() + "rc" ),
963 xCmdEnv, m_xComponentContext );
964 ucb_content.writeStream( xData, true /* replace existing */ );
966 for (t_stringlist::iterator i(m_components.begin());
967 i != m_components.end(); ++i)
969 if (space)
971 buf.append(' ');
973 buf.append('?');
974 buf.append(OUStringToOString(*i, RTL_TEXTENCODING_UTF8));
975 space = true;
977 buf.append(LF);
980 // write unorc:
981 const Reference<io::XInputStream> xData(
982 ::xmlscript::createInputStream(
983 ::rtl::ByteSequence(
984 reinterpret_cast<sal_Int8 const *>(buf.getStr()),
985 buf.getLength() ) ) );
986 ::ucbhelper::Content ucb_content(
987 makeURL( getCachePath(), "unorc" ), xCmdEnv, m_xComponentContext );
988 ucb_content.writeStream( xData, true /* replace existing */ );
990 m_unorc_modified = false;
993 //______________________________________________________________________________
994 bool BackendImpl::addToUnoRc( RcItem kind, OUString const & url_,
995 Reference<XCommandEnvironment> const & xCmdEnv )
997 const OUString rcterm( dp_misc::makeRcTerm(url_) );
998 const ::osl::MutexGuard guard( getMutex() );
999 unorc_verify_init( xCmdEnv );
1000 t_stringlist & rSet = getRcItemList(kind);
1001 if (::std::find( rSet.begin(), rSet.end(), rcterm ) == rSet.end()) {
1002 rSet.push_front( rcterm ); // prepend to list, thus overriding
1003 // write immediately:
1004 m_unorc_modified = true;
1005 unorc_flush( xCmdEnv );
1006 return true;
1008 else
1009 return false;
1012 //______________________________________________________________________________
1013 bool BackendImpl::removeFromUnoRc(
1014 RcItem kind, OUString const & url_,
1015 Reference<XCommandEnvironment> const & xCmdEnv )
1017 const OUString rcterm( dp_misc::makeRcTerm(url_) );
1018 const ::osl::MutexGuard guard( getMutex() );
1019 unorc_verify_init( xCmdEnv );
1020 getRcItemList(kind).remove( rcterm );
1021 // write immediately:
1022 m_unorc_modified = true;
1023 unorc_flush( xCmdEnv );
1024 return true;
1027 //______________________________________________________________________________
1028 bool BackendImpl::hasInUnoRc(
1029 RcItem kind, OUString const & url_ )
1031 const OUString rcterm( dp_misc::makeRcTerm(url_) );
1032 const ::osl::MutexGuard guard( getMutex() );
1033 t_stringlist const & rSet = getRcItemList(kind);
1034 return ::std::find( rSet.begin(), rSet.end(), rcterm ) != rSet.end();
1037 css::uno::Reference< css::uno::XComponentContext > BackendImpl::getRootContext()
1038 const
1040 css::uno::Reference< css::uno::XComponentContext > rootContext(
1041 getComponentContext()->getValueByName("_root"),
1042 css::uno::UNO_QUERY);
1043 return rootContext.is() ? rootContext : getComponentContext();
1046 //______________________________________________________________________________
1047 void BackendImpl::releaseObject( OUString const & id )
1049 const ::osl::MutexGuard guard( getMutex() );
1050 m_backendObjects.erase( id );
1053 //______________________________________________________________________________
1054 Reference<XInterface> BackendImpl::getObject( OUString const & id )
1056 const ::osl::MutexGuard guard( getMutex() );
1057 const t_string2object::const_iterator iFind( m_backendObjects.find( id ) );
1058 if (iFind == m_backendObjects.end())
1059 return Reference<XInterface>();
1060 else
1061 return iFind->second;
1064 //______________________________________________________________________________
1065 Reference<XInterface> BackendImpl::insertObject(
1066 OUString const & id, Reference<XInterface> const & xObject )
1068 const ::osl::MutexGuard guard( getMutex() );
1069 const ::std::pair<t_string2object::iterator, bool> insertion(
1070 m_backendObjects.insert( t_string2object::value_type(
1071 id, xObject ) ) );
1072 return insertion.first->second;
1075 //------------------------------------------------------------------------------
1076 Reference<XComponentContext> raise_uno_process(
1077 Reference<XComponentContext> const & xContext,
1078 ::rtl::Reference<AbortChannel> const & abortChannel )
1080 OSL_ASSERT( xContext.is() );
1082 OUString url( util::theMacroExpander::get(xContext)->expandMacros( "$URE_BIN_DIR/uno" ) );
1084 OUStringBuffer buf;
1085 buf.appendAscii( "uno:pipe,name=" );
1086 OUString pipeId( generateRandomPipeId() );
1087 buf.append( pipeId );
1088 buf.appendAscii( ";urp;uno.ComponentContext" );
1089 const OUString connectStr( buf.makeStringAndClear() );
1091 // raise core UNO process to register/run a component,
1092 // javavm service uses unorc next to executable to retrieve deployed
1093 // jar typelibs
1095 ::std::vector<OUString> args;
1096 #if OSL_DEBUG_LEVEL == 0
1097 args.push_back( "--quiet" );
1098 #endif
1099 args.push_back( "--singleaccept" );
1100 args.push_back( "-u" );
1101 args.push_back( connectStr );
1102 // don't inherit from unorc:
1103 args.push_back( "-env:INIFILENAME=" );
1105 //now add the bootstrap variables which were supplied on the command line
1106 ::std::vector<OUString> bootvars = getCmdBootstrapVariables();
1107 args.insert(args.end(), bootvars.begin(), bootvars.end());
1109 oslProcess hProcess = raiseProcess(
1110 url, comphelper::containerToSequence(args) );
1111 try {
1112 return Reference<XComponentContext>(
1113 resolveUnoURL( connectStr, xContext, abortChannel.get() ),
1114 UNO_QUERY_THROW );
1116 catch (...) {
1117 // try to terminate process:
1118 if ( osl_terminateProcess( hProcess ) != osl_Process_E_None )
1120 OSL_ASSERT( false );
1122 throw;
1126 //------------------------------------------------------------------------------
1127 namespace {
1129 void extractComponentData(
1130 css::uno::Reference< css::uno::XComponentContext > const & context,
1131 css::uno::Reference< css::registry::XRegistryKey > const & registry,
1132 ComponentBackendDb::Data * data,
1133 std::vector< css::uno::Reference< css::uno::XInterface > > * factories,
1134 css::uno::Reference< css::loader::XImplementationLoader > const &
1135 componentLoader,
1136 OUString const & componentUrl)
1138 OSL_ASSERT(
1139 context.is() && registry.is() && data != 0 && componentLoader.is());
1140 OUString registryName(registry->getKeyName());
1141 sal_Int32 prefix = registryName.getLength();
1142 if (!registryName.endsWith("/")) {
1143 prefix += RTL_CONSTASCII_LENGTH("/");
1145 css::uno::Sequence< css::uno::Reference< css::registry::XRegistryKey > >
1146 keys(registry->openKeys());
1147 css::uno::Reference< css::lang::XMultiComponentFactory > smgr(
1148 context->getServiceManager(), css::uno::UNO_QUERY_THROW);
1149 for (sal_Int32 i = 0; i < keys.getLength(); ++i) {
1150 OUString name(keys[i]->getKeyName().copy(prefix));
1151 data->implementationNames.push_back(name);
1152 css::uno::Reference< css::registry::XRegistryKey > singletons(
1153 keys[i]->openKey("UNO/SINGLETONS"));
1154 if (singletons.is()) {
1155 sal_Int32 prefix2 = keys[i]->getKeyName().getLength() +
1156 RTL_CONSTASCII_LENGTH("/UNO/SINGLETONS/");
1157 css::uno::Sequence<
1158 css::uno::Reference< css::registry::XRegistryKey > >
1159 singletonKeys(singletons->openKeys());
1160 for (sal_Int32 j = 0; j < singletonKeys.getLength(); ++j) {
1161 data->singletons.push_back(
1162 std::pair< OUString, OUString >(
1163 singletonKeys[j]->getKeyName().copy(prefix2), name));
1166 if (factories != 0) {
1167 factories->push_back(
1168 componentLoader->activate(
1169 name, OUString(), componentUrl, keys[i]));
1176 void BackendImpl::ComponentPackageImpl::getComponentInfo(
1177 ComponentBackendDb::Data * data,
1178 std::vector< css::uno::Reference< css::uno::XInterface > > * factories,
1179 Reference<XComponentContext> const & xContext )
1181 const Reference<loader::XImplementationLoader> xLoader(
1182 xContext->getServiceManager()->createInstanceWithContext(
1183 m_loader, xContext ), UNO_QUERY );
1184 if (! xLoader.is())
1186 throw css::deployment::DeploymentException(
1187 "cannot instantiate loader " + m_loader,
1188 static_cast< OWeakObject * >(this), Any());
1191 // HACK: highly dependent on stoc/source/servicemanager
1192 // and stoc/source/implreg implementation which rely on the same
1193 // services.rdb format!
1194 // .../UNO/LOCATION and .../UNO/ACTIVATOR appear not to be written by
1195 // writeRegistryInfo, however, but are known, fixed values here, so
1196 // can be passed into extractComponentData
1197 OUString url(getURL());
1198 const Reference<registry::XSimpleRegistry> xMemReg(
1199 xContext->getServiceManager()->createInstanceWithContext(
1200 "com.sun.star.registry.SimpleRegistry", xContext ),
1201 UNO_QUERY_THROW );
1202 xMemReg->open( OUString() /* in mem */, false, true );
1203 xLoader->writeRegistryInfo( xMemReg->getRootKey(), OUString(), url );
1204 extractComponentData(
1205 xContext, xMemReg->getRootKey(), data, factories, xLoader, url);
1208 void BackendImpl::ComponentPackageImpl::componentLiveInsertion(
1209 ComponentBackendDb::Data const & data,
1210 std::vector< css::uno::Reference< css::uno::XInterface > > const &
1211 factories)
1213 css::uno::Reference< css::uno::XComponentContext > rootContext(
1214 getMyBackend()->getRootContext());
1215 css::uno::Reference< css::container::XSet > set(
1216 rootContext->getServiceManager(), css::uno::UNO_QUERY_THROW);
1217 std::vector< css::uno::Reference< css::uno::XInterface > >::const_iterator
1218 factory(factories.begin());
1219 for (t_stringlist::const_iterator i(data.implementationNames.begin());
1220 i != data.implementationNames.end(); ++i)
1222 try {
1223 set->insert(css::uno::Any(*factory++));
1224 } catch (const container::ElementExistException &) {
1225 OSL_TRACE(
1226 "implementation %s already registered",
1227 OUStringToOString(*i, RTL_TEXTENCODING_UTF8).getStr());
1230 if (!data.singletons.empty()) {
1231 css::uno::Reference< css::container::XNameContainer > cont(
1232 rootContext, css::uno::UNO_QUERY_THROW);
1233 for (t_stringpairvec::const_iterator i(data.singletons.begin());
1234 i != data.singletons.end(); ++i)
1236 OUString name("/singletons/" + i->first);
1237 //TODO: Update should be atomic:
1238 try {
1239 cont->removeByName( name + "/arguments");
1240 } catch (const container::NoSuchElementException &) {}
1241 try {
1242 cont->insertByName( name + "/service", css::uno::Any(i->second));
1243 } catch (const container::ElementExistException &) {
1244 cont->replaceByName( name + "/service", css::uno::Any(i->second));
1246 try {
1247 cont->insertByName(name, css::uno::Any());
1248 } catch (const container::ElementExistException &) {
1249 OSL_TRACE(
1250 "singleton %s already registered",
1251 OUStringToOString(
1252 i->first, RTL_TEXTENCODING_UTF8).getStr());
1253 cont->replaceByName(name, css::uno::Any());
1259 void BackendImpl::ComponentPackageImpl::componentLiveRemoval(
1260 ComponentBackendDb::Data const & data)
1262 css::uno::Reference< css::uno::XComponentContext > rootContext(
1263 getMyBackend()->getRootContext());
1264 css::uno::Reference< css::container::XSet > set(
1265 rootContext->getServiceManager(), css::uno::UNO_QUERY_THROW);
1266 for (t_stringlist::const_iterator i(data.implementationNames.begin());
1267 i != data.implementationNames.end(); ++i)
1269 try {
1270 set->remove(css::uno::Any(*i));
1271 } catch (const css::container::NoSuchElementException &) {
1272 // ignore if factory has not been live deployed
1275 if (!data.singletons.empty()) {
1276 css::uno::Reference< css::container::XNameContainer > cont(
1277 rootContext, css::uno::UNO_QUERY_THROW);
1278 for (t_stringpairvec::const_iterator i(data.singletons.begin());
1279 i != data.singletons.end(); ++i)
1281 OUString name("/singletons/" + i->first);
1282 //TODO: Removal should be atomic:
1283 try {
1284 cont->removeByName(name);
1285 } catch (const container::NoSuchElementException &) {}
1286 try {
1287 cont->removeByName( name + "/service" );
1288 } catch (const container::NoSuchElementException &) {}
1289 try {
1290 cont->removeByName( name + "/arguments" );
1291 } catch (const container::NoSuchElementException &) {}
1296 // Package
1297 //______________________________________________________________________________
1298 //We could use here BackendImpl::hasActiveEntry. However, this check is just as well.
1299 //And it also shows the problem if another extension has overwritten an implementation
1300 //entry, because it contains the same service implementation
1301 beans::Optional< beans::Ambiguous<sal_Bool> >
1302 BackendImpl::ComponentPackageImpl::isRegistered_(
1303 ::osl::ResettableMutexGuard &,
1304 ::rtl::Reference<AbortChannel> const & abortChannel,
1305 Reference<XCommandEnvironment> const & )
1307 if (m_registered == REG_UNINIT)
1309 m_registered = REG_NOT_REGISTERED;
1310 bool bAmbiguousComponentName = false;
1311 const Reference<registry::XSimpleRegistry> xRDB( getRDB() );
1312 if (xRDB.is())
1314 // lookup rdb for location URL:
1315 const Reference<registry::XRegistryKey> xRootKey(
1316 xRDB->getRootKey() );
1317 const Reference<registry::XRegistryKey> xImplKey(
1318 xRootKey->openKey( "IMPLEMENTATIONS" ) );
1319 Sequence<OUString> implNames;
1320 if (xImplKey.is() && xImplKey->isValid())
1321 implNames = xImplKey->getKeyNames();
1322 OUString const * pImplNames = implNames.getConstArray();
1323 sal_Int32 pos = implNames.getLength();
1324 for ( ; pos--; )
1326 checkAborted( abortChannel );
1327 const OUString key(
1328 pImplNames[ pos ] + "/UNO/LOCATION" );
1329 const Reference<registry::XRegistryKey> xKey(
1330 xRootKey->openKey(key) );
1331 if (xKey.is() && xKey->isValid())
1333 const OUString location( xKey->getAsciiValue() );
1334 if (location.equalsIgnoreAsciiCase( getURL() ))
1336 break;
1338 else
1340 //try to match only the file name
1341 OUString thisUrl(getURL());
1342 OUString thisFileName(thisUrl.copy(thisUrl.lastIndexOf('/')));
1344 OUString locationFileName(location.copy(location.lastIndexOf('/')));
1345 if (locationFileName.equalsIgnoreAsciiCase(thisFileName))
1346 bAmbiguousComponentName = true;
1350 if (pos >= 0)
1351 m_registered = REG_REGISTERED;
1352 else if (bAmbiguousComponentName)
1353 m_registered = REG_MAYBE_REGISTERED;
1357 //Different extensions can use the same service implementations. Then the extensions
1358 //which was installed last will overwrite the one from the other extension. That is
1359 //the registry will contain the path (the location) of the library or jar of the
1360 //second extension. In this case isRegistered called for the lib of the first extension
1361 //would return "not registered". That would mean that during uninstallation
1362 //XPackage::registerPackage is not called, because it just was not registered. This is,
1363 //however, necessary for jar files. Registering and unregistering update
1364 //uno_packages/cache/registry/com.sun.star.comp.deployment.component.PackageRegistryBackend/unorc
1365 //Therefore, we will return always "is ambiguous" if the path of this component cannot
1366 //be found in the registry and if there is another path and both have the same file name (but
1367 //the rest of the path is different).
1368 //If the caller cannot precisely determine that this package was registered, then it must
1369 //call registerPackage.
1370 sal_Bool bAmbiguous = m_registered == REG_VOID // REG_VOID == we are in the progress of unregistration
1371 || m_registered == REG_MAYBE_REGISTERED;
1372 return beans::Optional< beans::Ambiguous<sal_Bool> >(
1373 true /* IsPresent */,
1374 beans::Ambiguous<sal_Bool>(
1375 m_registered == REG_REGISTERED, bAmbiguous) );
1378 //______________________________________________________________________________
1379 void BackendImpl::ComponentPackageImpl::processPackage_(
1380 ::osl::ResettableMutexGuard &,
1381 bool doRegisterPackage,
1382 bool startup,
1383 ::rtl::Reference<AbortChannel> const & abortChannel,
1384 Reference<XCommandEnvironment> const & xCmdEnv )
1386 BackendImpl * that = getMyBackend();
1387 OUString url(getURL());
1388 if (doRegisterPackage) {
1389 ComponentBackendDb::Data data;
1390 css::uno::Reference< css::uno::XComponentContext > context;
1391 if (startup) {
1392 context = that->getComponentContext();
1393 } else {
1394 context.set(that->getObject(url), css::uno::UNO_QUERY);
1395 if (!context.is()) {
1396 context.set(
1397 that->insertObject(
1398 url,
1399 raise_uno_process(
1400 that->getComponentContext(), abortChannel)),
1401 css::uno::UNO_QUERY_THROW);
1404 css::uno::Reference< css::registry::XImplementationRegistration> impreg(
1405 context->getServiceManager()->createInstanceWithContext(
1406 "com.sun.star.registry.ImplementationRegistration",
1407 context),
1408 css::uno::UNO_QUERY_THROW);
1409 css::uno::Reference< css::registry::XSimpleRegistry > rdb(getRDB());
1410 impreg->registerImplementation(m_loader, url, rdb);
1411 // Only write to unorc after successful registration; it may fail if
1412 // there is no suitable java
1413 if (m_loader == "com.sun.star.loader.Java2" && !jarManifestHeaderPresent(url, "UNO-Type-Path", xCmdEnv))
1415 that->addToUnoRc(RCITEM_JAR_TYPELIB, url, xCmdEnv);
1416 data.javaTypeLibrary = true;
1418 std::vector< css::uno::Reference< css::uno::XInterface > > factories;
1419 getComponentInfo(&data, startup ? 0 : &factories, context);
1420 if (!startup) {
1421 try {
1422 componentLiveInsertion(data, factories);
1423 } catch (css::uno::Exception & e) {
1424 SAL_INFO(
1425 "desktop.deployment", "caught Exception " << e.Message);
1426 try {
1427 impreg->revokeImplementation(url, rdb);
1428 } catch (css::uno::RuntimeException & e2) {
1429 SAL_WARN(
1430 "desktop.deployment",
1431 "ignored RuntimeException " << e2.Message);
1433 throw;
1436 m_registered = REG_REGISTERED;
1437 that->addDataToDb(url, data);
1438 } else { // revoke
1439 m_registered = REG_VOID;
1440 ComponentBackendDb::Data data(that->readDataFromDb(url));
1441 css::uno::Reference< css::uno::XComponentContext > context(
1442 that->getObject(url), css::uno::UNO_QUERY);
1443 bool remoteContext = context.is();
1444 if (!remoteContext) {
1445 context = that->getComponentContext();
1447 if (!startup) {
1448 componentLiveRemoval(data);
1450 css::uno::Reference< css::registry::XImplementationRegistration >(
1451 context->getServiceManager()->createInstanceWithContext(
1452 "com.sun.star.registry.ImplementationRegistration",
1453 context),
1454 css::uno::UNO_QUERY_THROW)->revokeImplementation(url, getRDB());
1455 if (data.javaTypeLibrary) {
1456 that->removeFromUnoRc(RCITEM_JAR_TYPELIB, url, xCmdEnv);
1458 if (remoteContext) {
1459 that->releaseObject(url);
1461 m_registered = REG_NOT_REGISTERED;
1462 getMyBackend()->revokeEntryFromDb(url);
1466 BackendImpl::TypelibraryPackageImpl::TypelibraryPackageImpl(
1467 ::rtl::Reference<PackageRegistryBackend> const & myBackend,
1468 OUString const & url, OUString const & name,
1469 Reference<deployment::XPackageTypeInfo> const & xPackageType,
1470 bool jarFile, bool bRemoved, OUString const & identifier)
1471 : Package( myBackend, url, name, name /* display-name */,
1472 xPackageType, bRemoved, identifier),
1473 m_jarFile( jarFile )
1477 // Package
1478 BackendImpl * BackendImpl::TypelibraryPackageImpl::getMyBackend() const
1480 BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get());
1481 if (NULL == pBackend)
1483 //May throw a DisposedException
1484 check();
1485 //We should never get here...
1486 throw RuntimeException( "Failed to get the BackendImpl",
1487 static_cast<OWeakObject*>(const_cast<TypelibraryPackageImpl *>(this)));
1489 return pBackend;
1491 //______________________________________________________________________________
1492 beans::Optional< beans::Ambiguous<sal_Bool> >
1493 BackendImpl::TypelibraryPackageImpl::isRegistered_(
1494 ::osl::ResettableMutexGuard &,
1495 ::rtl::Reference<AbortChannel> const &,
1496 Reference<XCommandEnvironment> const & )
1498 BackendImpl * that = getMyBackend();
1499 return beans::Optional< beans::Ambiguous<sal_Bool> >(
1500 true /* IsPresent */,
1501 beans::Ambiguous<sal_Bool>(
1502 that->hasInUnoRc(
1503 m_jarFile ? RCITEM_JAR_TYPELIB : RCITEM_RDB_TYPELIB, getURL() ),
1504 false /* IsAmbiguous */ ) );
1507 //______________________________________________________________________________
1508 void BackendImpl::TypelibraryPackageImpl::processPackage_(
1509 ::osl::ResettableMutexGuard &,
1510 bool doRegisterPackage,
1511 bool /*startup*/,
1512 ::rtl::Reference<AbortChannel> const &,
1513 Reference<XCommandEnvironment> const & xCmdEnv )
1515 BackendImpl * that = getMyBackend();
1516 const OUString url( getURL() );
1518 if (doRegisterPackage)
1520 // live insertion:
1521 if (m_jarFile) {
1522 // xxx todo add to classpath at runtime: ???
1523 //SB: It is probably not worth it to add the live inserted type
1524 // library JAR to the UnoClassLoader in the soffice process. Any
1525 // live inserted component JAR that might reference this type
1526 // library JAR runs in its own uno process, so there is probably no
1527 // Java code in the soffice process that would see any UNO types
1528 // introduced by this type library JAR.
1530 else // RDB:
1532 css::uno::Reference< css::container::XSet >(
1533 that->getComponentContext()->getValueByName(
1534 "/singletons"
1535 "/com.sun.star.reflection.theTypeDescriptionManager"),
1536 css::uno::UNO_QUERY_THROW)->insert(
1537 css::uno::makeAny(expandUnoRcUrl(url)));
1540 that->addToUnoRc( m_jarFile ? RCITEM_JAR_TYPELIB : RCITEM_RDB_TYPELIB,
1541 url, xCmdEnv );
1543 else // revokePackage()
1545 that->removeFromUnoRc(
1546 m_jarFile ? RCITEM_JAR_TYPELIB : RCITEM_RDB_TYPELIB, url, xCmdEnv );
1548 // revoking types at runtime, possible, sensible?
1549 if (!m_jarFile) {
1550 css::uno::Reference< css::container::XSet >(
1551 that->getComponentContext()->getValueByName(
1552 "/singletons"
1553 "/com.sun.star.reflection.theTypeDescriptionManager"),
1554 css::uno::UNO_QUERY_THROW)->remove(
1555 css::uno::makeAny(expandUnoRcUrl(url)));
1560 BackendImpl::OtherPlatformPackageImpl::OtherPlatformPackageImpl(
1561 ::rtl::Reference<PackageRegistryBackend> const & myBackend,
1562 OUString const & url, OUString const & name,
1563 Reference<deployment::XPackageTypeInfo> const & xPackageType,
1564 bool bRemoved, OUString const & identifier, OUString const& rPlatform)
1565 : Package(myBackend, url, name, name, xPackageType, bRemoved, identifier)
1566 , m_aPlatform(rPlatform)
1568 OSL_PRECOND(bRemoved, "this class can only be used for removing packages!");
1571 BackendImpl *
1572 BackendImpl::OtherPlatformPackageImpl::getMyBackend() const
1574 BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get());
1575 if (NULL == pBackend)
1577 //Throws a DisposedException
1578 check();
1579 //We should never get here...
1580 throw RuntimeException("Failed to get the BackendImpl",
1581 static_cast<OWeakObject*>(const_cast<OtherPlatformPackageImpl*>(this)));
1583 return pBackend;
1586 Reference<registry::XSimpleRegistry> const
1587 BackendImpl::OtherPlatformPackageImpl::impl_openRDB() const
1589 OUString const aRDB(m_aPlatform + ".rdb");
1590 OUString const aRDBPath(makeURL(getMyBackend()->getCachePath(), aRDB));
1592 Reference<registry::XSimpleRegistry> xRegistry;
1596 xRegistry.set(
1597 impl_createInstance("com.sun.star.registry.SimpleRegistry"),
1598 UNO_QUERY)
1600 if (xRegistry.is())
1601 xRegistry->open(expandUnoRcUrl(aRDBPath), false, false);
1603 catch (registry::InvalidRegistryException const&)
1605 // If the registry does not exist, we do not need to bother at all
1606 xRegistry.set(0);
1609 OSL_POSTCOND(xRegistry.is(), "could not create registry for the package's platform");
1610 return xRegistry;
1613 Reference<XInterface> const
1614 BackendImpl::OtherPlatformPackageImpl::impl_createInstance(OUString const& rService)
1615 const
1617 Reference<XComponentContext> const xContext(getMyBackend()->getComponentContext());
1618 OSL_ASSERT(xContext.is());
1619 Reference<XInterface> xService;
1620 if (xContext.is())
1621 xService.set(xContext->getServiceManager()->createInstanceWithContext(rService, xContext));
1622 return xService;
1625 beans::Optional<beans::Ambiguous<sal_Bool> >
1626 BackendImpl::OtherPlatformPackageImpl::isRegistered_(
1627 ::osl::ResettableMutexGuard& /* guard */,
1628 ::rtl::Reference<AbortChannel> const& /* abortChannel */,
1629 Reference<XCommandEnvironment> const& /* xCmdEnv */ )
1631 return beans::Optional<beans::Ambiguous<sal_Bool> >(sal_True,
1632 beans::Ambiguous<sal_Bool>(sal_True, sal_False));
1635 void
1636 BackendImpl::OtherPlatformPackageImpl::processPackage_(
1637 ::osl::ResettableMutexGuard& /* guard */,
1638 bool bRegisterPackage,
1639 bool /* bStartup */,
1640 ::rtl::Reference<AbortChannel> const& /* abortChannel */,
1641 Reference<XCommandEnvironment> const& /* xCmdEnv */)
1643 OSL_PRECOND(!bRegisterPackage, "this class can only be used for removing packages!");
1644 (void) bRegisterPackage;
1646 OUString const aURL(getURL());
1648 Reference<registry::XSimpleRegistry> const xServicesRDB(impl_openRDB());
1649 Reference<registry::XImplementationRegistration> const xImplReg(
1650 impl_createInstance("com.sun.star.registry.ImplementationRegistration"),
1651 UNO_QUERY)
1653 if (xImplReg.is() && xServicesRDB.is())
1654 xImplReg->revokeImplementation(aURL, xServicesRDB);
1655 if (xServicesRDB.is())
1656 xServicesRDB->close();
1658 getMyBackend()->revokeEntryFromDb(aURL);
1661 BackendImpl * BackendImpl::ComponentsPackageImpl::getMyBackend() const
1663 BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get());
1664 if (NULL == pBackend)
1666 //Throws a DisposedException
1667 check();
1668 //We should never get here...
1669 throw RuntimeException("Failed to get the BackendImpl",
1670 static_cast<OWeakObject*>(const_cast<ComponentsPackageImpl *>(this)));
1672 return pBackend;
1675 beans::Optional< beans::Ambiguous<sal_Bool> >
1676 BackendImpl::ComponentsPackageImpl::isRegistered_(
1677 ::osl::ResettableMutexGuard &,
1678 ::rtl::Reference<AbortChannel> const &,
1679 Reference<XCommandEnvironment> const & )
1681 return beans::Optional< beans::Ambiguous<sal_Bool> >(
1682 true,
1683 beans::Ambiguous<sal_Bool>(
1684 getMyBackend()->hasInUnoRc(RCITEM_COMPONENTS, getURL()), false));
1687 void BackendImpl::ComponentsPackageImpl::processPackage_(
1688 ::osl::ResettableMutexGuard &,
1689 bool doRegisterPackage,
1690 bool startup,
1691 ::rtl::Reference<AbortChannel> const & abortChannel,
1692 Reference<XCommandEnvironment> const & xCmdEnv )
1694 BackendImpl * that = getMyBackend();
1695 OUString url(getURL());
1696 if (doRegisterPackage) {
1697 if (!startup) {
1698 css::uno::Reference< css::uno::XComponentContext > context(
1699 that->getObject(url), css::uno::UNO_QUERY);
1700 if (!context.is()) {
1701 context.set(
1702 that->insertObject(
1703 url,
1704 raise_uno_process(
1705 that->getComponentContext(), abortChannel)),
1706 css::uno::UNO_QUERY_THROW);
1708 // This relies on the root component context's service manager
1709 // supporting the extended XSet semantics:
1710 css::uno::Sequence< css::beans::NamedValue > args(2);
1711 args[0].Name = OUString("uri");
1712 args[0].Value <<= expandUnoRcUrl(url);
1713 args[1].Name = OUString("component-context");
1714 args[1].Value <<= context;
1715 css::uno::Reference< css::container::XSet > smgr(
1716 that->getRootContext()->getServiceManager(),
1717 css::uno::UNO_QUERY_THROW);
1718 smgr->insert(css::uno::makeAny(args));
1720 that->addToUnoRc(RCITEM_COMPONENTS, url, xCmdEnv);
1721 } else { // revoke
1722 that->removeFromUnoRc(RCITEM_COMPONENTS, url, xCmdEnv);
1723 if (!startup) {
1724 // This relies on the root component context's service manager
1725 // supporting the extended XSet semantics:
1726 css::uno::Sequence< css::beans::NamedValue > args(1);
1727 args[0].Name = OUString("uri");
1728 args[0].Value <<= expandUnoRcUrl(url);
1729 css::uno::Reference< css::container::XSet > smgr(
1730 that->getRootContext()->getServiceManager(),
1731 css::uno::UNO_QUERY_THROW);
1732 smgr->remove(css::uno::makeAny(args));
1734 that->releaseObject(url);
1735 that->revokeEntryFromDb(url); // in case it got added with old code
1739 BackendImpl::ComponentsPackageImpl::ComponentsPackageImpl(
1740 ::rtl::Reference<PackageRegistryBackend> const & myBackend,
1741 OUString const & url, OUString const & name,
1742 Reference<deployment::XPackageTypeInfo> const & xPackageType,
1743 bool bRemoved, OUString const & identifier)
1744 : Package( myBackend, url, name, name /* display-name */,
1745 xPackageType, bRemoved, identifier)
1748 } // anon namespace
1750 namespace sdecl = comphelper::service_decl;
1751 sdecl::class_<BackendImpl, sdecl::with_args<true> > serviceBI;
1752 extern sdecl::ServiceDecl const serviceDecl(
1753 serviceBI,
1754 IMPLEMENTATION_NAME,
1755 BACKEND_SERVICE_NAME );
1757 } // namespace component
1758 } // namespace backend
1759 } // namespace dp_registry
1762 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */