xref: /trunk/main/desktop/source/deployment/registry/component/dp_component.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_desktop.hxx"
26 
27 #include "dp_component.hrc"
28 #include "dp_backend.h"
29 #include "dp_platform.hxx"
30 #include "dp_ucb.h"
31 #include "rtl/string.hxx"
32 #include "rtl/strbuf.hxx"
33 #include "rtl/ustrbuf.hxx"
34 #include "rtl/uri.hxx"
35 #include "cppuhelper/exc_hlp.hxx"
36 #include "ucbhelper/content.hxx"
37 #include "comphelper/anytostring.hxx"
38 #include "comphelper/servicedecl.hxx"
39 #include "comphelper/sequence.hxx"
40 #include "xmlscript/xml_helper.hxx"
41 #include "svl/inettype.hxx"
42 #include "com/sun/star/lang/WrappedTargetRuntimeException.hpp"
43 #include "com/sun/star/container/XNameContainer.hpp"
44 #include "com/sun/star/container/XHierarchicalNameAccess.hpp"
45 #include "com/sun/star/container/XSet.hpp"
46 #include "com/sun/star/registry/XSimpleRegistry.hpp"
47 #include "com/sun/star/registry/XImplementationRegistration.hpp"
48 #include "com/sun/star/loader/XImplementationLoader.hpp"
49 #include "com/sun/star/io/XInputStream.hpp"
50 #include "com/sun/star/ucb/NameClash.hpp"
51 #include "com/sun/star/util/XMacroExpander.hpp"
52 #include <list>
53 #include <hash_map>
54 #include <vector>
55 #include <memory>
56 #include <algorithm>
57 #include "dp_compbackenddb.hxx"
58 
59 using namespace ::dp_misc;
60 using namespace ::com::sun::star;
61 using namespace ::com::sun::star::uno;
62 using namespace ::com::sun::star::ucb;
63 using ::rtl::OUString;
64 namespace css = com::sun::star;
65 
66 namespace dp_registry {
67 namespace backend {
68 namespace component {
69 namespace {
70 
71 typedef ::std::list<OUString> t_stringlist;
72 typedef ::std::vector< ::std::pair<OUString, OUString> > t_stringpairvec;
73 
74 #define IMPLEMENTATION_NAME  "com.sun.star.comp.deployment.component.PackageRegistryBackend"
75 
76 /** return a vector of bootstrap variables which have been provided
77     as command arguments.
78 */
getCmdBootstrapVariables()79 ::std::vector<OUString> getCmdBootstrapVariables()
80 {
81     ::std::vector<OUString> ret;
82     sal_uInt32 count = osl_getCommandArgCount();
83     for (sal_uInt32 i = 0; i < count; i++)
84     {
85         OUString arg;
86         osl_getCommandArg(i, &arg.pData);
87         if (arg.matchAsciiL("-env:", 5))
88             ret.push_back(arg);
89     }
90     return ret;
91 }
92 
jarManifestHeaderPresent(OUString const & url,OUString const & name,Reference<XCommandEnvironment> const & xCmdEnv)93 bool jarManifestHeaderPresent(
94     OUString const & url, OUString const & name,
95     Reference<XCommandEnvironment> const & xCmdEnv )
96 {
97     ::rtl::OUStringBuffer buf;
98     buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.zip://") );
99     buf.append(
100         ::rtl::Uri::encode(
101             url, rtl_UriCharClassRegName, rtl_UriEncodeIgnoreEscapes,
102             RTL_TEXTENCODING_UTF8 ) );
103     buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("/META-INF/MANIFEST.MF") );
104     ::ucbhelper::Content manifestContent;
105     OUString line;
106     return
107         create_ucb_content(
108             &manifestContent, buf.makeStringAndClear(), xCmdEnv,
109             false /* no throw */ )
110         && readLine( &line, name, manifestContent, RTL_TEXTENCODING_ASCII_US );
111 }
112 
113 //==============================================================================
114 class BackendImpl : public ::dp_registry::backend::PackageRegistryBackend
115 {
116     class ComponentPackageImpl : public ::dp_registry::backend::Package
117     {
118         BackendImpl * getMyBackend() const;
119 
120         const OUString m_loader;
121 
122         enum reg {
123             REG_UNINIT, REG_VOID, REG_REGISTERED, REG_NOT_REGISTERED, REG_MAYBE_REGISTERED
124         } m_registered;
125 
126         void getComponentInfo(
127             ComponentBackendDb::Data * data,
128             std::vector< css::uno::Reference< css::uno::XInterface > > *
129                 factories,
130             Reference<XComponentContext> const & xContext );
131 
132         virtual void SAL_CALL disposing();
133 
134         // Package
135         virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_(
136             ::osl::ResettableMutexGuard & guard,
137             ::rtl::Reference<AbortChannel> const & abortChannel,
138             Reference<XCommandEnvironment> const & xCmdEnv );
139         virtual void processPackage_(
140             ::osl::ResettableMutexGuard & guard,
141             bool registerPackage,
142             bool startup,
143             ::rtl::Reference<AbortChannel> const & abortChannel,
144             Reference<XCommandEnvironment> const & xCmdEnv );
145 
146         const Reference<registry::XSimpleRegistry> getRDB() const;
147 
148         //Provides the read-only registry (e.g. not the one based on the duplicated
149         //rdb files
150         const Reference<registry::XSimpleRegistry> getRDB_RO() const;
151 
152     public:
153         ComponentPackageImpl(
154             ::rtl::Reference<PackageRegistryBackend> const & myBackend,
155             OUString const & url, OUString const & name,
156             Reference<deployment::XPackageTypeInfo> const & xPackageType,
157             OUString const & loader, bool bRemoved,
158             OUString const & identifier);
159     };
160     friend class ComponentPackageImpl;
161 
162     class ComponentsPackageImpl : public ::dp_registry::backend::Package
163     {
164         BackendImpl * getMyBackend() const;
165 
166         // Package
167         virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_(
168             ::osl::ResettableMutexGuard & guard,
169             ::rtl::Reference<AbortChannel> const & abortChannel,
170             Reference<XCommandEnvironment> const & xCmdEnv );
171         virtual void processPackage_(
172             ::osl::ResettableMutexGuard & guard,
173             bool registerPackage,
174             bool startup,
175             ::rtl::Reference<AbortChannel> const & abortChannel,
176             Reference<XCommandEnvironment> const & xCmdEnv );
177     public:
178         ComponentsPackageImpl(
179             ::rtl::Reference<PackageRegistryBackend> const & myBackend,
180             OUString const & url, OUString const & name,
181             Reference<deployment::XPackageTypeInfo> const & xPackageType,
182             bool bRemoved, OUString const & identifier);
183     };
184     friend class ComponentsPackageImpl;
185 
186     class TypelibraryPackageImpl : public ::dp_registry::backend::Package
187     {
188         BackendImpl * getMyBackend() const;
189 
190         const bool m_jarFile;
191         Reference<container::XHierarchicalNameAccess> m_xTDprov;
192 
193         virtual void SAL_CALL disposing();
194 
195         // Package
196         virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_(
197             ::osl::ResettableMutexGuard & guard,
198             ::rtl::Reference<AbortChannel> const & abortChannel,
199             Reference<XCommandEnvironment> const & xCmdEnv );
200         virtual void processPackage_(
201             ::osl::ResettableMutexGuard & guard,
202             bool registerPackage,
203             bool startup,
204             ::rtl::Reference<AbortChannel> const & abortChannel,
205             Reference<XCommandEnvironment> const & xCmdEnv );
206 
207     public:
208         TypelibraryPackageImpl(
209             ::rtl::Reference<PackageRegistryBackend> const & myBackend,
210             OUString const & url, OUString const & name,
211             Reference<deployment::XPackageTypeInfo> const & xPackageType,
212             bool jarFile, bool bRemoved,
213             OUString const & identifier);
214     };
215     friend class TypelibraryPackageImpl;
216 
217     t_stringlist m_jar_typelibs;
218     t_stringlist m_rdb_typelibs;
219     t_stringlist m_components;
220 
221     enum RcItem { RCITEM_JAR_TYPELIB, RCITEM_RDB_TYPELIB, RCITEM_COMPONENTS };
222 
getRcItemList(RcItem kind)223     t_stringlist & getRcItemList( RcItem kind ) {
224         switch (kind)
225         {
226         case RCITEM_JAR_TYPELIB:
227             return m_jar_typelibs;
228         case RCITEM_RDB_TYPELIB:
229             return m_rdb_typelibs;
230         default: // case RCITEM_COMPONENTS
231             return m_components;
232         }
233     }
234 
235     bool m_unorc_inited;
236     bool m_unorc_modified;
237     bool bSwitchedRdbFiles;
238 
239     typedef ::std::hash_map< OUString, Reference<XInterface>,
240                              ::rtl::OUStringHash > t_string2object;
241     t_string2object m_backendObjects;
242 
243     // PackageRegistryBackend
244     virtual Reference<deployment::XPackage> bindPackage_(
245         OUString const & url, OUString const & mediaType,
246         sal_Bool bRemoved, OUString const & identifier,
247         Reference<XCommandEnvironment> const & xCmdEnv );
248 
249     virtual void SAL_CALL disposing();
250 
251     const Reference<deployment::XPackageTypeInfo> m_xDynComponentTypeInfo;
252     const Reference<deployment::XPackageTypeInfo> m_xJavaComponentTypeInfo;
253     const Reference<deployment::XPackageTypeInfo> m_xPythonComponentTypeInfo;
254     const Reference<deployment::XPackageTypeInfo> m_xComponentsTypeInfo;
255     const Reference<deployment::XPackageTypeInfo> m_xRDBTypelibTypeInfo;
256     const Reference<deployment::XPackageTypeInfo> m_xJavaTypelibTypeInfo;
257     Sequence< Reference<deployment::XPackageTypeInfo> > m_typeInfos;
258 
259     OUString m_commonRDB;
260     OUString m_nativeRDB;
261 
262     //URLs of the read-only rdbs (e.g. not the ones of the duplicated files)
263     OUString m_commonRDB_RO;
264     OUString m_nativeRDB_RO;
265 
266     std::auto_ptr<ComponentBackendDb> m_backendDb;
267 
268     void addDataToDb(OUString const & url, ComponentBackendDb::Data const & data);
269     ComponentBackendDb::Data readDataFromDb(OUString const & url);
270     void revokeEntryFromDb(OUString const & url);
271 
272 
273     //These rdbs are for writing new service entries. The rdb files are copies
274     //which are created when services are added or removed.
275     Reference<registry::XSimpleRegistry> m_xCommonRDB;
276     Reference<registry::XSimpleRegistry> m_xNativeRDB;
277 
278     //These rdbs are created on the read-only rdbs which are already used
279     //by UNO since the startup of the current session.
280     Reference<registry::XSimpleRegistry> m_xCommonRDB_RO;
281     Reference<registry::XSimpleRegistry> m_xNativeRDB_RO;
282 
283 
284     void unorc_verify_init( Reference<XCommandEnvironment> const & xCmdEnv );
285     void unorc_flush( Reference<XCommandEnvironment> const & xCmdEnv );
286 
287     Reference<XInterface> getObject( OUString const & id );
288     Reference<XInterface> insertObject(
289         OUString const & id, Reference<XInterface> const & xObject );
290     void releaseObject( OUString const & id );
291 
292     bool addToUnoRc( RcItem kind, OUString const & url,
293                      Reference<XCommandEnvironment> const & xCmdEnv );
294     bool removeFromUnoRc( RcItem kind, OUString const & url,
295                           Reference<XCommandEnvironment> const & xCmdEnv );
296     bool hasInUnoRc( RcItem kind, OUString const & url );
297 
298     css::uno::Reference< css::registry::XRegistryKey > openRegistryKey(
299         css::uno::Reference< css::registry::XRegistryKey > const & base,
300         rtl::OUString const & path);
301 
302     void extractComponentData(
303         css::uno::Reference< css::uno::XComponentContext > const & context,
304         css::uno::Reference< css::registry::XRegistryKey > const & registry,
305         ComponentBackendDb::Data * data,
306         std::vector< css::uno::Reference< css::uno::XInterface > > * factories,
307         css::uno::Reference< css::loader::XImplementationLoader > const *
308             componentLoader,
309         rtl::OUString const * componentUrl);
310 
311     void componentLiveInsertion(
312         ComponentBackendDb::Data const & data,
313         std::vector< css::uno::Reference< css::uno::XInterface > > const &
314             factories);
315 
316     void componentLiveRemoval(ComponentBackendDb::Data const & data);
317 
318 public:
319     BackendImpl( Sequence<Any> const & args,
320                  Reference<XComponentContext> const & xComponentContext );
321 
322     // XPackageRegistry
323     virtual Sequence< Reference<deployment::XPackageTypeInfo> > SAL_CALL
324     getSupportedPackageTypes();
325 
326     virtual void SAL_CALL packageRemoved(OUString const & url, OUString const & mediaType);
327 
328     using PackageRegistryBackend::disposing;
329 
330     //Will be called from ComponentPackageImpl
331     void initServiceRdbFiles();
332 
333     //Creates the READ ONLY registries (m_xCommonRDB_RO,m_xNativeRDB_RO)
334     void initServiceRdbFiles_RO();
335 };
336 
337 //______________________________________________________________________________
338 
ComponentPackageImpl(::rtl::Reference<PackageRegistryBackend> const & myBackend,OUString const & url,OUString const & name,Reference<deployment::XPackageTypeInfo> const & xPackageType,OUString const & loader,bool bRemoved,OUString const & identifier)339 BackendImpl::ComponentPackageImpl::ComponentPackageImpl(
340     ::rtl::Reference<PackageRegistryBackend> const & myBackend,
341     OUString const & url, OUString const & name,
342     Reference<deployment::XPackageTypeInfo> const & xPackageType,
343     OUString const & loader, bool bRemoved,
344     OUString const & identifier)
345     : Package( myBackend, url, name, name /* display-name */,
346                xPackageType, bRemoved, identifier),
347       m_loader( loader ),
348       m_registered( REG_UNINIT )
349 {}
350 
351 const Reference<registry::XSimpleRegistry>
getRDB() const352 BackendImpl::ComponentPackageImpl::getRDB() const
353 {
354     BackendImpl * that = getMyBackend();
355 
356     //Late "initialization" of the services rdb files
357     //This is to prevent problems when running several
358     //instances of OOo with root rights in parallel. This
359     //would otherwise cause problems when copying the rdbs.
360     //See  http://qa.openoffice.org/issues/show_bug.cgi?id=99257
361     {
362         const ::osl::MutexGuard guard( getMutex() );
363         if (!that->bSwitchedRdbFiles)
364         {
365             that->bSwitchedRdbFiles = true;
366             that->initServiceRdbFiles();
367         }
368     }
369     if (m_loader.equalsAsciiL(
370             RTL_CONSTASCII_STRINGPARAM("com.sun.star.loader.SharedLibrary") ))
371         return that->m_xNativeRDB;
372     else
373         return that->m_xCommonRDB;
374 }
375 
376 //Returns the read only RDB.
377 const Reference<registry::XSimpleRegistry>
getRDB_RO() const378 BackendImpl::ComponentPackageImpl::getRDB_RO() const
379 {
380     BackendImpl * that = getMyBackend();
381 
382     if (m_loader.equalsAsciiL(
383             RTL_CONSTASCII_STRINGPARAM("com.sun.star.loader.SharedLibrary") ))
384         return that->m_xNativeRDB_RO;
385     else
386         return that->m_xCommonRDB_RO;
387 }
388 
getMyBackend() const389 BackendImpl * BackendImpl::ComponentPackageImpl::getMyBackend() const
390 {
391     BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get());
392     if (NULL == pBackend)
393     {
394         //Throws a DisposedException
395         check();
396         //We should never get here...
397         throw RuntimeException(
398             OUSTR("Failed to get the BackendImpl"),
399             static_cast<OWeakObject*>(const_cast<ComponentPackageImpl *>(this)));
400     }
401     return pBackend;
402 }
403 
404 
405 //______________________________________________________________________________
disposing()406 void BackendImpl::ComponentPackageImpl::disposing()
407 {
408 //    m_xRemoteContext.clear();
409     Package::disposing();
410 }
411 
412 //______________________________________________________________________________
disposing()413 void BackendImpl::TypelibraryPackageImpl::disposing()
414 {
415     m_xTDprov.clear();
416     Package::disposing();
417 }
418 
419 //______________________________________________________________________________
disposing()420 void BackendImpl::disposing()
421 {
422     try {
423         m_backendObjects = t_string2object();
424         if (m_xNativeRDB.is()) {
425             m_xNativeRDB->close();
426             m_xNativeRDB.clear();
427         }
428         if (m_xCommonRDB.is()) {
429             m_xCommonRDB->close();
430             m_xCommonRDB.clear();
431         }
432         unorc_flush( Reference<XCommandEnvironment>() );
433 
434         PackageRegistryBackend::disposing();
435     }
436     catch (RuntimeException &) {
437         throw;
438     }
439     catch (Exception &) {
440         Any exc( ::cppu::getCaughtException() );
441         throw lang::WrappedTargetRuntimeException(
442             OUSTR("caught unexpected exception while disposing..."),
443             static_cast<OWeakObject *>(this), exc );
444     }
445 }
446 
447 
initServiceRdbFiles()448 void BackendImpl::initServiceRdbFiles()
449 {
450     const Reference<XCommandEnvironment> xCmdEnv;
451 
452     ::ucbhelper::Content cacheDir( getCachePath(), xCmdEnv );
453     ::ucbhelper::Content oldRDB;
454     // switch common rdb:
455     if (m_commonRDB_RO.getLength() > 0)
456     {
457         create_ucb_content(
458             &oldRDB, makeURL( getCachePath(), m_commonRDB_RO),
459             xCmdEnv, false /* no throw */ );
460     }
461     m_commonRDB = m_commonRDB_RO.equalsAsciiL(
462         RTL_CONSTASCII_STRINGPARAM("common.rdb") )
463         ? OUSTR("common_.rdb") : OUSTR("common.rdb");
464     if (oldRDB.get().is())
465     {
466         if (! cacheDir.transferContent(
467                 oldRDB, ::ucbhelper::InsertOperation_COPY,
468                 m_commonRDB, NameClash::OVERWRITE ))
469         {
470 
471             throw RuntimeException(
472                 OUSTR("UCB transferContent() failed!"), 0 );
473         }
474         oldRDB = ::ucbhelper::Content();
475     }
476     // switch native rdb:
477     if (m_nativeRDB_RO.getLength() > 0)
478     {
479         create_ucb_content(
480             &oldRDB, makeURL(getCachePath(), m_nativeRDB_RO),
481             xCmdEnv, false /* no throw */ );
482     }
483     const OUString plt_rdb( getPlatformString() + OUSTR(".rdb") );
484     const OUString plt_rdb_( getPlatformString() + OUSTR("_.rdb") );
485     m_nativeRDB = m_nativeRDB_RO.equals( plt_rdb ) ? plt_rdb_ : plt_rdb;
486     if (oldRDB.get().is())
487     {
488         if (! cacheDir.transferContent(
489                 oldRDB, ::ucbhelper::InsertOperation_COPY,
490                 m_nativeRDB, NameClash::OVERWRITE ))
491             throw RuntimeException(
492                 OUSTR("UCB transferContent() failed!"), 0 );
493     }
494 
495     // UNO is bootstrapped, flush for next process start:
496     m_unorc_modified = true;
497     unorc_flush( Reference<XCommandEnvironment>() );
498 
499 
500     // common rdb for java, native rdb for shared lib components
501     if (m_commonRDB.getLength() > 0) {
502         m_xCommonRDB.set(
503             m_xComponentContext->getServiceManager()
504             ->createInstanceWithContext(
505             OUSTR("com.sun.star.registry.SimpleRegistry"),
506             m_xComponentContext ), UNO_QUERY_THROW );
507         m_xCommonRDB->open(
508             makeURL( expandUnoRcUrl(getCachePath()), m_commonRDB ),
509 //            m_readOnly, !m_readOnly );
510             false, true);
511     }
512     if (m_nativeRDB.getLength() > 0) {
513         m_xNativeRDB.set(
514             m_xComponentContext->getServiceManager()
515             ->createInstanceWithContext(
516             OUSTR("com.sun.star.registry.SimpleRegistry"),
517             m_xComponentContext ), UNO_QUERY_THROW );
518         m_xNativeRDB->open(
519             makeURL( expandUnoRcUrl(getCachePath()), m_nativeRDB ),
520 //            m_readOnly, !m_readOnly );
521             false, true);
522     }
523 }
524 
initServiceRdbFiles_RO()525 void BackendImpl::initServiceRdbFiles_RO()
526 {
527     const Reference<XCommandEnvironment> xCmdEnv;
528 
529     // common rdb for java, native rdb for shared lib components
530     if (m_commonRDB_RO.getLength() > 0)
531     {
532         m_xCommonRDB_RO.set(
533             m_xComponentContext->getServiceManager()
534             ->createInstanceWithContext(
535             OUSTR("com.sun.star.registry.SimpleRegistry"),
536             m_xComponentContext), UNO_QUERY_THROW);
537         m_xCommonRDB_RO->open(
538             makeURL(expandUnoRcUrl(getCachePath()), m_commonRDB_RO),
539             sal_True, //read-only
540             sal_True); // create data source if necessary
541     }
542     if (m_nativeRDB_RO.getLength() > 0)
543     {
544         m_xNativeRDB_RO.set(
545             m_xComponentContext->getServiceManager()
546             ->createInstanceWithContext(
547             OUSTR("com.sun.star.registry.SimpleRegistry"),
548             m_xComponentContext), UNO_QUERY_THROW);
549         m_xNativeRDB_RO->open(
550             makeURL(expandUnoRcUrl(getCachePath()), m_nativeRDB_RO),
551             sal_True, //read-only
552             sal_True); // create data source if necessary
553     }
554 }
555 
556 //______________________________________________________________________________
BackendImpl(Sequence<Any> const & args,Reference<XComponentContext> const & xComponentContext)557 BackendImpl::BackendImpl(
558     Sequence<Any> const & args,
559     Reference<XComponentContext> const & xComponentContext )
560     : PackageRegistryBackend( args, xComponentContext ),
561       m_unorc_inited( false ),
562       m_unorc_modified( false ),
563       bSwitchedRdbFiles(false),
564       m_xDynComponentTypeInfo( new Package::TypeInfo(
565                                    OUSTR("application/"
566                                          "vnd.sun.star.uno-component;"
567                                          "type=native;platform=") +
568                                    getPlatformString(),
569                                    OUSTR("*" SAL_DLLEXTENSION),
570                                    getResourceString(RID_STR_DYN_COMPONENT),
571                                    RID_IMG_COMPONENT,
572                                    RID_IMG_COMPONENT_HC ) ),
573       m_xJavaComponentTypeInfo( new Package::TypeInfo(
574                                     OUSTR("application/"
575                                           "vnd.sun.star.uno-component;"
576                                           "type=Java"),
577                                     OUSTR("*.jar"),
578                                     getResourceString(RID_STR_JAVA_COMPONENT),
579                                     RID_IMG_JAVA_COMPONENT,
580                                     RID_IMG_JAVA_COMPONENT_HC ) ),
581       m_xPythonComponentTypeInfo( new Package::TypeInfo(
582                                       OUSTR("application/"
583                                             "vnd.sun.star.uno-component;"
584                                             "type=Python"),
585                                       OUSTR("*.py"),
586                                       getResourceString(
587                                           RID_STR_PYTHON_COMPONENT),
588                                       RID_IMG_COMPONENT,
589                                       RID_IMG_COMPONENT_HC ) ),
590       m_xComponentsTypeInfo( new Package::TypeInfo(
591                                  OUSTR("application/"
592                                        "vnd.sun.star.uno-components"),
593                                  OUSTR("*.components"),
594                                  getResourceString(RID_STR_COMPONENTS),
595                                  RID_IMG_COMPONENT,
596                                  RID_IMG_COMPONENT_HC ) ),
597       m_xRDBTypelibTypeInfo( new Package::TypeInfo(
598                                  OUSTR("application/"
599                                        "vnd.sun.star.uno-typelibrary;"
600                                        "type=RDB"),
601                                  OUSTR("*.rdb"),
602                                  getResourceString(RID_STR_RDB_TYPELIB),
603                                  RID_IMG_TYPELIB, RID_IMG_TYPELIB_HC ) ),
604       m_xJavaTypelibTypeInfo( new Package::TypeInfo(
605                                   OUSTR("application/"
606                                         "vnd.sun.star.uno-typelibrary;"
607                                         "type=Java"),
608                                   OUSTR("*.jar"),
609                                   getResourceString(RID_STR_JAVA_TYPELIB),
610                                   RID_IMG_JAVA_TYPELIB,
611                                   RID_IMG_JAVA_TYPELIB_HC ) ),
612       m_typeInfos( 6 )
613 {
614     m_typeInfos[ 0 ] = m_xDynComponentTypeInfo;
615     m_typeInfos[ 1 ] = m_xJavaComponentTypeInfo;
616     m_typeInfos[ 2 ] = m_xPythonComponentTypeInfo;
617     m_typeInfos[ 3 ] = m_xComponentsTypeInfo;
618     m_typeInfos[ 4 ] = m_xRDBTypelibTypeInfo;
619     m_typeInfos[ 5 ] = m_xJavaTypelibTypeInfo;
620 
621     const Reference<XCommandEnvironment> xCmdEnv;
622 
623     if (transientMode())
624     {
625         // in-mem rdbs:
626         // common rdb for java, native rdb for shared lib components
627         m_xCommonRDB.set(
628             xComponentContext->getServiceManager()->createInstanceWithContext(
629                 OUSTR("com.sun.star.registry.SimpleRegistry"),
630                 xComponentContext ), UNO_QUERY_THROW );
631         m_xCommonRDB->open( OUString() /* in-mem */,
632                             false /* ! read-only */, true /* create */ );
633         m_xNativeRDB.set(
634             xComponentContext->getServiceManager()->createInstanceWithContext(
635                 OUSTR("com.sun.star.registry.SimpleRegistry"),
636                 xComponentContext ), UNO_QUERY_THROW );
637         m_xNativeRDB->open( OUString() /* in-mem */,
638                             false /* ! read-only */, true /* create */ );
639     }
640     else
641     {
642         //do this before initServiceRdbFiles_RO, because it determines
643         //m_commonRDB and m_nativeRDB
644         unorc_verify_init( xCmdEnv );
645 
646         initServiceRdbFiles_RO();
647 
648         OUString dbFile = makeURL(getCachePath(), OUSTR("backenddb.xml"));
649         m_backendDb.reset(
650             new ComponentBackendDb(getComponentContext(), dbFile));
651     }
652 }
653 
addDataToDb(OUString const & url,ComponentBackendDb::Data const & data)654 void BackendImpl::addDataToDb(
655     OUString const & url, ComponentBackendDb::Data const & data)
656 {
657     if (m_backendDb.get())
658         m_backendDb->addEntry(url, data);
659 }
660 
readDataFromDb(OUString const & url)661 ComponentBackendDb::Data BackendImpl::readDataFromDb(OUString const & url)
662 {
663     ComponentBackendDb::Data data;
664     if (m_backendDb.get())
665         data = m_backendDb->getEntry(url);
666     return data;
667 }
668 
revokeEntryFromDb(OUString const & url)669 void BackendImpl::revokeEntryFromDb(OUString const & url)
670 {
671     if (m_backendDb.get())
672         m_backendDb->revokeEntry(url);
673 }
674 
675 // XPackageRegistry
676 //______________________________________________________________________________
677 Sequence< Reference<deployment::XPackageTypeInfo> >
getSupportedPackageTypes()678 BackendImpl::getSupportedPackageTypes()
679 {
680     return m_typeInfos;
681 }
682 
packageRemoved(OUString const & url,OUString const &)683 void BackendImpl::packageRemoved(OUString const & url, OUString const & /*mediaType*/)
684 {
685     if (m_backendDb.get())
686         m_backendDb->removeEntry(url);
687 }
688 
689 // PackageRegistryBackend
690 //______________________________________________________________________________
bindPackage_(OUString const & url,OUString const & mediaType_,sal_Bool bRemoved,OUString const & identifier,Reference<XCommandEnvironment> const & xCmdEnv)691 Reference<deployment::XPackage> BackendImpl::bindPackage_(
692     OUString const & url, OUString const & mediaType_,
693     sal_Bool bRemoved, OUString const & identifier,
694     Reference<XCommandEnvironment> const & xCmdEnv )
695 {
696     OUString mediaType(mediaType_);
697     if (mediaType.getLength() == 0 ||
698         mediaType.equalsAsciiL(
699             RTL_CONSTASCII_STRINGPARAM(
700                 "application/vnd.sun.star.uno-component") ) ||
701         mediaType.equalsAsciiL(
702             RTL_CONSTASCII_STRINGPARAM(
703                 "application/vnd.sun.star.uno-typelibrary") ))
704     {
705         // detect exact media-type:
706         ::ucbhelper::Content ucbContent;
707         if (create_ucb_content( &ucbContent, url, xCmdEnv )) {
708             const OUString title( ucbContent.getPropertyValue(
709                                       StrTitle::get() ).get<OUString>() );
710             if (title.endsWithIgnoreAsciiCaseAsciiL(
711                     RTL_CONSTASCII_STRINGPARAM(SAL_DLLEXTENSION) ))
712             {
713                 mediaType = OUSTR("application/vnd.sun.star.uno-component;"
714                                   "type=native;platform=") +
715                     getPlatformString();
716             }
717             else if (title.endsWithIgnoreAsciiCaseAsciiL(
718                          RTL_CONSTASCII_STRINGPARAM(".jar") ))
719             {
720                 if (jarManifestHeaderPresent(
721                         url, OUSTR("RegistrationClassName"), xCmdEnv ))
722                     mediaType = OUSTR(
723                         "application/vnd.sun.star.uno-component;type=Java");
724                 if (mediaType.getLength() == 0)
725                     mediaType = OUSTR(
726                         "application/vnd.sun.star.uno-typelibrary;type=Java");
727             }
728             else if (title.endsWithIgnoreAsciiCaseAsciiL(
729                          RTL_CONSTASCII_STRINGPARAM(".py") ))
730                 mediaType =
731                     OUSTR("application/vnd.sun.star.uno-component;type=Python");
732             else if (title.endsWithIgnoreAsciiCaseAsciiL(
733                          RTL_CONSTASCII_STRINGPARAM(".rdb") ))
734                 mediaType =
735                     OUSTR("application/vnd.sun.star.uno-typelibrary;type=RDB");
736         }
737         if (mediaType.getLength() == 0)
738             throw lang::IllegalArgumentException(
739                 StrCannotDetectMediaType::get() + url,
740                 static_cast<OWeakObject *>(this), static_cast<sal_Int16>(-1) );
741     }
742 
743     String type, subType;
744     INetContentTypeParameterList params;
745     if (INetContentTypes::parse( mediaType, type, subType, &params ))
746     {
747         if (type.EqualsIgnoreCaseAscii("application"))
748         {
749             OUString name;
750             if (!bRemoved)
751             {
752                 ::ucbhelper::Content ucbContent( url, xCmdEnv );
753                 name = ucbContent.getPropertyValue(
754                     StrTitle::get() ).get<OUString>();
755             }
756 
757             if (subType.EqualsIgnoreCaseAscii("vnd.sun.star.uno-component"))
758             {
759                 // xxx todo: probe and evaluate component xml description
760 
761                 INetContentTypeParameter const * param = params.find(
762                     ByteString("platform") );
763                 if (param == 0 || platform_fits( param->m_sValue )) {
764                     param = params.find( ByteString("type") );
765                     if (param != 0)
766                     {
767                         String const & value = param->m_sValue;
768                         if (value.EqualsIgnoreCaseAscii("native")) {
769                             return new BackendImpl::ComponentPackageImpl(
770                                 this, url, name, m_xDynComponentTypeInfo,
771                                 OUSTR("com.sun.star.loader.SharedLibrary"),
772                                 bRemoved, identifier);
773                         }
774                         if (value.EqualsIgnoreCaseAscii("Java")) {
775                             return new BackendImpl::ComponentPackageImpl(
776                                 this, url, name, m_xJavaComponentTypeInfo,
777                                 OUSTR("com.sun.star.loader.Java2"),
778                                 bRemoved, identifier);
779                         }
780                         if (value.EqualsIgnoreCaseAscii("Python")) {
781                             return new BackendImpl::ComponentPackageImpl(
782                                 this, url, name, m_xPythonComponentTypeInfo,
783                                 OUSTR("com.sun.star.loader.Python"),
784                                 bRemoved, identifier);
785                         }
786                     }
787                 }
788             }
789             else if (subType.EqualsIgnoreCaseAscii(
790                          "vnd.sun.star.uno-components"))
791             {
792                 INetContentTypeParameter const * param = params.find(
793                     ByteString("platform") );
794                 if (param == 0 || platform_fits( param->m_sValue )) {
795                     return new BackendImpl::ComponentsPackageImpl(
796                         this, url, name, m_xComponentsTypeInfo, bRemoved,
797                         identifier);
798                 }
799             }
800             else if (subType.EqualsIgnoreCaseAscii(
801                          "vnd.sun.star.uno-typelibrary"))
802             {
803                 INetContentTypeParameter const * param = params.find(
804                     ByteString("type") );
805                 if (param != 0) {
806                     String const & value = param->m_sValue;
807                     if (value.EqualsIgnoreCaseAscii("RDB"))
808                     {
809                         return new BackendImpl::TypelibraryPackageImpl(
810                             this, url, name, m_xRDBTypelibTypeInfo,
811                             false /* rdb */, bRemoved, identifier);
812                     }
813                     if (value.EqualsIgnoreCaseAscii("Java")) {
814                         return new BackendImpl::TypelibraryPackageImpl(
815                             this, url, name, m_xJavaTypelibTypeInfo,
816                             true /* jar */, bRemoved, identifier);
817                     }
818                 }
819             }
820         }
821     }
822     throw lang::IllegalArgumentException(
823         StrUnsupportedMediaType::get() + mediaType,
824         static_cast<OWeakObject *>(this),
825         static_cast<sal_Int16>(-1) );
826 }
827 
828 //##############################################################################
829 
830 //______________________________________________________________________________
unorc_verify_init(Reference<XCommandEnvironment> const & xCmdEnv)831 void BackendImpl::unorc_verify_init(
832     Reference<XCommandEnvironment> const & xCmdEnv )
833 {
834     if (transientMode())
835         return;
836     const ::osl::MutexGuard guard( getMutex() );
837     if (! m_unorc_inited)
838     {
839         // common rc:
840         ::ucbhelper::Content ucb_content;
841         if (create_ucb_content(
842                 &ucb_content,
843                 makeURL( getCachePath(), OUSTR("unorc") ),
844                 xCmdEnv, false /* no throw */ ))
845         {
846             OUString line;
847             if (readLine( &line, OUSTR("UNO_JAVA_CLASSPATH="), ucb_content,
848                           RTL_TEXTENCODING_UTF8 ))
849             {
850                 sal_Int32 index = sizeof ("UNO_JAVA_CLASSPATH=") - 1;
851                 do {
852                     OUString token( line.getToken( 0, ' ', index ).trim() );
853                     if (token.getLength() > 0)
854                     {
855                         if (create_ucb_content(
856                                 0, expandUnoRcTerm(token), xCmdEnv,
857                                 false /* no throw */ ))
858                         {
859                             //The jar file may not exist anymore if a shared or bundled
860                             //extension was removed, but it can still be in the unorc
861                             //After running XExtensionManager::synchronize, the unorc is
862                             //cleaned up
863                             m_jar_typelibs.push_back( token );
864                         }
865                     }
866                 }
867                 while (index >= 0);
868             }
869             if (readLine( &line, OUSTR("UNO_TYPES="), ucb_content,
870                           RTL_TEXTENCODING_UTF8 )) {
871                 sal_Int32 index = sizeof ("UNO_TYPES=") - 1;
872                 do {
873                     OUString token( line.getToken( 0, ' ', index ).trim() );
874                     if (token.getLength() > 0)
875                     {
876                         if (token[ 0 ] == '?')
877                             token = token.copy( 1 );
878                          if (create_ucb_content(
879                                 0, expandUnoRcTerm(token), xCmdEnv,
880                                 false /* no throw */ ))
881                          {
882                              //The RDB file may not exist anymore if a shared or bundled
883                              //extension was removed, but it can still be in the unorc.
884                              //After running XExtensionManager::synchronize, the unorc is
885                              //cleaned up
886                              m_rdb_typelibs.push_back( token );
887                          }
888                     }
889                 }
890                 while (index >= 0);
891             }
892             if (readLine( &line, OUSTR("UNO_SERVICES="), ucb_content,
893                           RTL_TEXTENCODING_UTF8 ))
894             {
895                 // The UNO_SERVICES line always has the BNF form
896                 //  "UNO_SERVICES="
897                 //  ("?$ORIGIN/" <common-rdb>)?                        -- first
898                 //  "${$ORIGIN/${_OS}_${_ARCH}rc:UNO_SERVICES}"?       -- second
899                 //  ("?" ("BUNDLED_EXTENSIONS" |                       -- third
900                 //   "UNO_SHARED_PACKAGES_CACHE" | "UNO_USER_PACKAGES_CACHE")
901                 //   ...)*
902                 // so can unambiguously be split into its thre parts:
903                 int state = 1;
904                 for (sal_Int32 i = RTL_CONSTASCII_LENGTH("UNO_SERVICES=");
905                      i >= 0;)
906                 {
907                     rtl::OUString token(line.getToken(0, ' ', i));
908                     if (token.getLength() != 0)
909                     {
910                         if (state == 1 &&
911                             token.matchAsciiL(
912                                 RTL_CONSTASCII_STRINGPARAM("?$ORIGIN/")))
913                         {
914                             m_commonRDB_RO = token.copy(
915                                 RTL_CONSTASCII_LENGTH("?$ORIGIN/"));
916                             state = 2;
917                         }
918                         else if (state <= 2 &&
919                                  token.equalsAsciiL(
920                                      RTL_CONSTASCII_STRINGPARAM(
921                                          "${$ORIGIN/${_OS}_${_ARCH}rc:"
922                                          "UNO_SERVICES}")))
923                         {
924                             state = 3;
925                         }
926                         else
927                         {
928                             if (token[0] == '?')
929                             {
930                                 token = token.copy(1);
931                             }
932                             m_components.push_back(token);
933                             state = 3;
934                         }
935                     }
936                 }
937             }
938 
939             // native rc:
940             if (create_ucb_content(
941                     &ucb_content,
942                     makeURL( getCachePath(), getPlatformString() + OUSTR("rc")),
943                     xCmdEnv, false /* no throw */ )) {
944                 if (readLine( &line, OUSTR("UNO_SERVICES="), ucb_content,
945                               RTL_TEXTENCODING_UTF8 )) {
946                     m_nativeRDB_RO = line.copy(
947                         sizeof ("UNO_SERVICES=?$ORIGIN/") - 1 );
948                 }
949             }
950         }
951         m_unorc_modified = false;
952         m_unorc_inited = true;
953     }
954 }
955 
956 //______________________________________________________________________________
unorc_flush(Reference<XCommandEnvironment> const & xCmdEnv)957 void BackendImpl::unorc_flush( Reference<XCommandEnvironment> const & xCmdEnv )
958 {
959     if (transientMode())
960         return;
961     if (!m_unorc_inited || !m_unorc_modified)
962         return;
963 
964     ::rtl::OStringBuffer buf;
965 
966     buf.append(RTL_CONSTASCII_STRINGPARAM("ORIGIN="));
967     OUString sOrigin = dp_misc::makeRcTerm(m_cachePath);
968     ::rtl::OString osOrigin = ::rtl::OUStringToOString(sOrigin, RTL_TEXTENCODING_UTF8);
969     buf.append(osOrigin);
970     buf.append(LF);
971 
972     if (! m_jar_typelibs.empty())
973     {
974         t_stringlist::const_iterator iPos( m_jar_typelibs.begin() );
975         t_stringlist::const_iterator const iEnd( m_jar_typelibs.end() );
976         buf.append( RTL_CONSTASCII_STRINGPARAM("UNO_JAVA_CLASSPATH=") );
977         while (iPos != iEnd) {
978             // encoded ASCII file-urls:
979             const ::rtl::OString item(
980                 ::rtl::OUStringToOString( *iPos, RTL_TEXTENCODING_ASCII_US ) );
981             buf.append( item );
982             ++iPos;
983             if (iPos != iEnd)
984                 buf.append( ' ' );
985         }
986         buf.append(LF);
987     }
988     if (! m_rdb_typelibs.empty())
989     {
990         t_stringlist::const_iterator iPos( m_rdb_typelibs.begin() );
991         t_stringlist::const_iterator const iEnd( m_rdb_typelibs.end() );
992         buf.append( RTL_CONSTASCII_STRINGPARAM("UNO_TYPES=") );
993         while (iPos != iEnd) {
994             buf.append( '?' );
995             // encoded ASCII file-urls:
996             const ::rtl::OString item(
997                 ::rtl::OUStringToOString( *iPos, RTL_TEXTENCODING_ASCII_US ) );
998             buf.append( item );
999             ++iPos;
1000             if (iPos != iEnd)
1001                 buf.append( ' ' );
1002         }
1003         buf.append(LF);
1004     }
1005 
1006     // If we duplicated the common or native rdb then we must use those urls
1007     //otherwise we use those of the original files. That is, m_commonRDB_RO and
1008     //m_nativeRDB_RO;
1009     OUString sCommonRDB(m_commonRDB.getLength() > 0 ? m_commonRDB : m_commonRDB_RO);
1010     OUString sNativeRDB(m_nativeRDB.getLength() > 0 ? m_nativeRDB : m_nativeRDB_RO);
1011 
1012     if (sCommonRDB.getLength() > 0 || sNativeRDB.getLength() > 0 ||
1013         !m_components.empty())
1014     {
1015         buf.append( RTL_CONSTASCII_STRINGPARAM("UNO_SERVICES=") );
1016         bool space = false;
1017         if (sCommonRDB.getLength() > 0)
1018         {
1019             buf.append( RTL_CONSTASCII_STRINGPARAM("?$ORIGIN/") );
1020             buf.append( ::rtl::OUStringToOString(
1021                             sCommonRDB, RTL_TEXTENCODING_ASCII_US ) );
1022             space = true;
1023         }
1024         if (sNativeRDB.getLength() > 0)
1025         {
1026             if (space)
1027             {
1028                 buf.append(' ');
1029             }
1030             buf.append( RTL_CONSTASCII_STRINGPARAM(
1031                             "${$ORIGIN/${_OS}_${_ARCH}rc:UNO_SERVICES}") );
1032             space = true;
1033 
1034             // write native rc:
1035             ::rtl::OStringBuffer buf2;
1036             buf2.append(RTL_CONSTASCII_STRINGPARAM("ORIGIN="));
1037             buf2.append(osOrigin);
1038             buf2.append(LF);
1039             buf2.append( RTL_CONSTASCII_STRINGPARAM("UNO_SERVICES=?$ORIGIN/") );
1040             buf2.append( ::rtl::OUStringToOString(
1041                              sNativeRDB, RTL_TEXTENCODING_ASCII_US ) );
1042             buf2.append(LF);
1043 
1044             const Reference<io::XInputStream> xData(
1045                 ::xmlscript::createInputStream(
1046                     ::rtl::ByteSequence(
1047                         reinterpret_cast<sal_Int8 const *>(buf2.getStr()),
1048                         buf2.getLength() ) ) );
1049             ::ucbhelper::Content ucb_content(
1050                 makeURL( getCachePath(), getPlatformString() + OUSTR("rc") ),
1051                 xCmdEnv );
1052             ucb_content.writeStream( xData, true /* replace existing */ );
1053         }
1054         for (t_stringlist::iterator i(m_components.begin());
1055              i != m_components.end(); ++i)
1056         {
1057             if (space)
1058             {
1059                 buf.append(' ');
1060             }
1061             buf.append('?');
1062             buf.append(rtl::OUStringToOString(*i, RTL_TEXTENCODING_UTF8));
1063             space = true;
1064         }
1065         buf.append(LF);
1066     }
1067 
1068     // write unorc:
1069     const Reference<io::XInputStream> xData(
1070         ::xmlscript::createInputStream(
1071             ::rtl::ByteSequence(
1072                 reinterpret_cast<sal_Int8 const *>(buf.getStr()),
1073                 buf.getLength() ) ) );
1074     ::ucbhelper::Content ucb_content(
1075         makeURL( getCachePath(), OUSTR("unorc") ), xCmdEnv );
1076     ucb_content.writeStream( xData, true /* replace existing */ );
1077 
1078     m_unorc_modified = false;
1079 }
1080 
1081 //______________________________________________________________________________
addToUnoRc(RcItem kind,OUString const & url_,Reference<XCommandEnvironment> const & xCmdEnv)1082 bool BackendImpl::addToUnoRc( RcItem kind, OUString const & url_,
1083                               Reference<XCommandEnvironment> const & xCmdEnv )
1084 {
1085     const OUString rcterm( dp_misc::makeRcTerm(url_) );
1086     const ::osl::MutexGuard guard( getMutex() );
1087     unorc_verify_init( xCmdEnv );
1088     t_stringlist & rSet = getRcItemList(kind);
1089     if (::std::find( rSet.begin(), rSet.end(), rcterm ) == rSet.end()) {
1090         rSet.push_front( rcterm ); // prepend to list, thus overriding
1091         // write immediately:
1092         m_unorc_modified = true;
1093         unorc_flush( xCmdEnv );
1094         return true;
1095     }
1096     else
1097         return false;
1098 }
1099 
1100 //______________________________________________________________________________
removeFromUnoRc(RcItem kind,OUString const & url_,Reference<XCommandEnvironment> const & xCmdEnv)1101 bool BackendImpl::removeFromUnoRc(
1102     RcItem kind, OUString const & url_,
1103     Reference<XCommandEnvironment> const & xCmdEnv )
1104 {
1105     const OUString rcterm( dp_misc::makeRcTerm(url_) );
1106     const ::osl::MutexGuard guard( getMutex() );
1107     unorc_verify_init( xCmdEnv );
1108     getRcItemList(kind).remove( rcterm );
1109     // write immediately:
1110     m_unorc_modified = true;
1111     unorc_flush( xCmdEnv );
1112     return true;
1113 }
1114 
1115 //______________________________________________________________________________
hasInUnoRc(RcItem kind,OUString const & url_)1116 bool BackendImpl::hasInUnoRc(
1117     RcItem kind, OUString const & url_ )
1118 {
1119     const OUString rcterm( dp_misc::makeRcTerm(url_) );
1120     const ::osl::MutexGuard guard( getMutex() );
1121     t_stringlist const & rSet = getRcItemList(kind);
1122     return ::std::find( rSet.begin(), rSet.end(), rcterm ) != rSet.end();
1123 }
1124 
openRegistryKey(css::uno::Reference<css::registry::XRegistryKey> const & base,rtl::OUString const & path)1125 css::uno::Reference< css::registry::XRegistryKey > BackendImpl::openRegistryKey(
1126     css::uno::Reference< css::registry::XRegistryKey > const & base,
1127     rtl::OUString const & path)
1128 {
1129     OSL_ASSERT(base.is());
1130     css::uno::Reference< css::registry::XRegistryKey > key(base->openKey(path));
1131     if (!key.is()) {
1132         throw css::deployment::DeploymentException(
1133             (rtl::OUString(
1134                 RTL_CONSTASCII_USTRINGPARAM("missing registry entry ")) +
1135              path + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" under ")) +
1136              base->getKeyName()),
1137             static_cast< OWeakObject * >(this), Any());
1138     }
1139     return key;
1140 }
1141 
extractComponentData(css::uno::Reference<css::uno::XComponentContext> const & context,css::uno::Reference<css::registry::XRegistryKey> const & registry,ComponentBackendDb::Data * data,std::vector<css::uno::Reference<css::uno::XInterface>> * factories,css::uno::Reference<css::loader::XImplementationLoader> const * componentLoader,rtl::OUString const * componentUrl)1142 void BackendImpl::extractComponentData(
1143     css::uno::Reference< css::uno::XComponentContext > const & context,
1144     css::uno::Reference< css::registry::XRegistryKey > const & registry,
1145     ComponentBackendDb::Data * data,
1146     std::vector< css::uno::Reference< css::uno::XInterface > > * factories,
1147     css::uno::Reference< css::loader::XImplementationLoader > const *
1148         componentLoader,
1149     rtl::OUString const * componentUrl)
1150 {
1151     OSL_ASSERT(context.is() && registry.is() && data != 0 && factories != 0);
1152     rtl::OUString registryName(registry->getKeyName());
1153     sal_Int32 prefix = registryName.getLength();
1154     if (!registryName.endsWithAsciiL(RTL_CONSTASCII_STRINGPARAM("/"))) {
1155         prefix += RTL_CONSTASCII_LENGTH("/");
1156     }
1157     css::uno::Sequence< css::uno::Reference< css::registry::XRegistryKey > >
1158         keys(registry->openKeys());
1159     css::uno::Reference< css::lang::XMultiComponentFactory > smgr(
1160         context->getServiceManager(), css::uno::UNO_QUERY_THROW);
1161     for (sal_Int32 i = 0; i < keys.getLength(); ++i) {
1162         rtl::OUString name(keys[i]->getKeyName().copy(prefix));
1163         data->implementationNames.push_back(name);
1164         css::uno::Reference< css::registry::XRegistryKey > singletons(
1165             keys[i]->openKey(
1166                 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("UNO/SINGLETONS"))));
1167         if (singletons.is()) {
1168             sal_Int32 prefix2 = keys[i]->getKeyName().getLength() +
1169                 RTL_CONSTASCII_LENGTH("/UNO/SINGLETONS/");
1170             css::uno::Sequence<
1171                 css::uno::Reference< css::registry::XRegistryKey > >
1172                 singletonKeys(singletons->openKeys());
1173             for (sal_Int32 j = 0; j < singletonKeys.getLength(); ++j) {
1174                 data->singletons.push_back(
1175                     std::pair< rtl::OUString, rtl::OUString >(
1176                         singletonKeys[j]->getKeyName().copy(prefix2), name));
1177             }
1178         }
1179         css::uno::Reference< css::loader::XImplementationLoader > loader;
1180         if (componentLoader == 0) {
1181             rtl::OUString activator(
1182                 openRegistryKey(
1183                     keys[i],
1184                     rtl::OUString(
1185                         RTL_CONSTASCII_USTRINGPARAM("UNO/ACTIVATOR")))->
1186                 getAsciiValue());
1187             loader.set(
1188                 smgr->createInstanceWithContext(activator, context),
1189                 css::uno::UNO_QUERY);
1190             if (!loader.is()) {
1191                 throw css::deployment::DeploymentException(
1192                     (rtl::OUString(
1193                         RTL_CONSTASCII_USTRINGPARAM(
1194                             "cannot instantiate loader ")) +
1195                      activator),
1196                     static_cast< OWeakObject * >(this), Any());
1197             }
1198         } else {
1199             OSL_ASSERT(componentLoader->is());
1200             loader = *componentLoader;
1201         }
1202         factories->push_back(
1203             loader->activate(
1204                 name, rtl::OUString(),
1205                 (componentUrl == 0
1206                  ? (openRegistryKey(
1207                         keys[i],
1208                         rtl::OUString(
1209                             RTL_CONSTASCII_USTRINGPARAM("UNO/LOCATION")))->
1210                     getAsciiValue())
1211                  : *componentUrl),
1212                 keys[i]));
1213     }
1214 }
1215 
componentLiveInsertion(ComponentBackendDb::Data const & data,std::vector<css::uno::Reference<css::uno::XInterface>> const & factories)1216 void BackendImpl::componentLiveInsertion(
1217     ComponentBackendDb::Data const & data,
1218     std::vector< css::uno::Reference< css::uno::XInterface > > const &
1219         factories)
1220 {
1221     css::uno::Reference< css::container::XSet > set(
1222         getComponentContext()->getServiceManager(), css::uno::UNO_QUERY_THROW);
1223     std::vector< css::uno::Reference< css::uno::XInterface > >::const_iterator
1224         factory(factories.begin());
1225     for (t_stringlist::const_iterator i(data.implementationNames.begin());
1226          i != data.implementationNames.end(); ++i)
1227     {
1228         try {
1229             set->insert(css::uno::Any(*factory++));
1230         } catch (container::ElementExistException &) {
1231             OSL_TRACE(
1232                 "implementation %s already registered",
1233                 rtl::OUStringToOString(*i, RTL_TEXTENCODING_UTF8).getStr());
1234         }
1235     }
1236     if (!data.singletons.empty()) {
1237         css::uno::Reference< css::container::XNameContainer >
1238             rootContext(
1239                 getComponentContext()->getValueByName(
1240                     rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("_root"))),
1241                 css::uno::UNO_QUERY);
1242         if (rootContext.is()) {
1243             for (t_stringpairvec::const_iterator i(data.singletons.begin());
1244                  i != data.singletons.end(); ++i)
1245             {
1246                 rtl::OUString name(
1247                     rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/singletons/")) +
1248                     i->first);
1249                 try {
1250                     rootContext->removeByName(
1251                         name +
1252                         rtl::OUString(
1253                             RTL_CONSTASCII_USTRINGPARAM("/arguments")));
1254                 } catch (container::NoSuchElementException &) {}
1255                 try {
1256                     rootContext->insertByName(
1257                         (name +
1258                          rtl::OUString(
1259                              RTL_CONSTASCII_USTRINGPARAM("/service"))),
1260                         css::uno::Any(i->second));
1261                 } catch (container::ElementExistException &) {
1262                     rootContext->replaceByName(
1263                         (name +
1264                          rtl::OUString(
1265                              RTL_CONSTASCII_USTRINGPARAM("/service"))),
1266                         css::uno::Any(i->second));
1267                 }
1268                 try {
1269                     rootContext->insertByName(name, css::uno::Any());
1270                 } catch (container::ElementExistException &) {
1271                     OSL_TRACE(
1272                         "singleton %s already registered",
1273                         rtl::OUStringToOString(
1274                             i->first, RTL_TEXTENCODING_UTF8).getStr());
1275                     rootContext->replaceByName(name, css::uno::Any());
1276                 }
1277             }
1278         }
1279     }
1280 }
1281 
componentLiveRemoval(ComponentBackendDb::Data const & data)1282 void BackendImpl::componentLiveRemoval(ComponentBackendDb::Data const & data) {
1283     css::uno::Reference< css::container::XSet > set(
1284         getComponentContext()->getServiceManager(), css::uno::UNO_QUERY_THROW);
1285     for (t_stringlist::const_iterator i(data.implementationNames.begin());
1286          i != data.implementationNames.end(); ++i)
1287     {
1288         try {
1289             set->remove(css::uno::Any(*i));
1290         } catch (css::container::NoSuchElementException &) {
1291             // ignore if factory has not been live deployed
1292         }
1293     }
1294     if (!data.singletons.empty()) {
1295         css::uno::Reference< css::container::XNameContainer > rootContext(
1296             getComponentContext()->getValueByName(
1297                 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("_root"))),
1298             css::uno::UNO_QUERY);
1299         if (rootContext.is()) {
1300             for (t_stringpairvec::const_iterator i(data.singletons.begin());
1301                  i != data.singletons.end(); ++i)
1302             {
1303                 rtl::OUString name(
1304                     rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/singletons/")) +
1305                     i->first);
1306                 try {
1307                     rootContext->removeByName(
1308                         name +
1309                         rtl::OUString(
1310                             RTL_CONSTASCII_USTRINGPARAM("/arguments")));
1311                     rootContext->removeByName(
1312                         name +
1313                         rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/service")));
1314                     rootContext->removeByName(name);
1315                 } catch (container::NoSuchElementException &) {}
1316             }
1317         }
1318     }
1319 }
1320 
1321 //______________________________________________________________________________
releaseObject(OUString const & id)1322 void BackendImpl::releaseObject( OUString const & id )
1323 {
1324     const ::osl::MutexGuard guard( getMutex() );
1325     m_backendObjects.erase( id );
1326 }
1327 
1328 //______________________________________________________________________________
getObject(OUString const & id)1329 Reference<XInterface> BackendImpl::getObject( OUString const & id )
1330 {
1331     const ::osl::MutexGuard guard( getMutex() );
1332     const t_string2object::const_iterator iFind( m_backendObjects.find( id ) );
1333     if (iFind == m_backendObjects.end())
1334         return Reference<XInterface>();
1335     else
1336         return iFind->second;
1337 }
1338 
1339 //______________________________________________________________________________
insertObject(OUString const & id,Reference<XInterface> const & xObject)1340 Reference<XInterface> BackendImpl::insertObject(
1341     OUString const & id, Reference<XInterface> const & xObject )
1342 {
1343     const ::osl::MutexGuard guard( getMutex() );
1344     const ::std::pair<t_string2object::iterator, bool> insertion(
1345         m_backendObjects.insert( t_string2object::value_type(
1346                                      id, xObject ) ) );
1347     return insertion.first->second;
1348 }
1349 
1350 //------------------------------------------------------------------------------
raise_uno_process(Reference<XComponentContext> const & xContext,::rtl::Reference<AbortChannel> const & abortChannel)1351 Reference<XComponentContext> raise_uno_process(
1352     Reference<XComponentContext> const & xContext,
1353     ::rtl::Reference<AbortChannel> const & abortChannel )
1354 {
1355     OSL_ASSERT( xContext.is() );
1356 
1357     ::rtl::OUString url(
1358         Reference<util::XMacroExpander>(
1359             xContext->getValueByName(
1360                 OUSTR("/singletons/com.sun.star.util.theMacroExpander") ),
1361             UNO_QUERY_THROW )->
1362         expandMacros( OUSTR("$URE_BIN_DIR/uno") ) );
1363 
1364     ::rtl::OUStringBuffer buf;
1365     buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("uno:pipe,name=") );
1366     OUString pipeId( generateRandomPipeId() );
1367     buf.append( pipeId );
1368     buf.appendAscii(
1369         RTL_CONSTASCII_STRINGPARAM(";urp;uno.ComponentContext") );
1370     const OUString connectStr( buf.makeStringAndClear() );
1371 
1372     // raise core UNO process to register/run a component,
1373     // javavm service uses unorc next to executable to retrieve deployed
1374     // jar typelibs
1375 
1376     ::std::vector<OUString> args;
1377 #if OSL_DEBUG_LEVEL <= 1
1378     args.push_back( OUSTR("--quiet") );
1379 #endif
1380     args.push_back( OUSTR("--singleaccept") );
1381     args.push_back( OUSTR("-u") );
1382     args.push_back( connectStr );
1383     // don't inherit from unorc:
1384     args.push_back( OUSTR("-env:INIFILENAME=") );
1385 
1386     //now add the bootstrap variables which were supplied on the command line
1387     ::std::vector<OUString> bootvars = getCmdBootstrapVariables();
1388     args.insert(args.end(), bootvars.begin(), bootvars.end());
1389 
1390     oslProcess hProcess = raiseProcess(
1391         url, comphelper::containerToSequence(args) );
1392     try {
1393         return Reference<XComponentContext>(
1394             resolveUnoURL( connectStr, xContext, abortChannel.get() ),
1395             UNO_QUERY_THROW );
1396     }
1397     catch (...) {
1398         // try to terminate process:
1399         if ( osl_terminateProcess( hProcess ) != osl_Process_E_None )
1400         {
1401             OSL_ASSERT( false );
1402         }
1403         throw;
1404     }
1405 }
1406 
1407 //------------------------------------------------------------------------------
getComponentInfo(ComponentBackendDb::Data * data,std::vector<css::uno::Reference<css::uno::XInterface>> * factories,Reference<XComponentContext> const & xContext)1408 void BackendImpl::ComponentPackageImpl::getComponentInfo(
1409     ComponentBackendDb::Data * data,
1410     std::vector< css::uno::Reference< css::uno::XInterface > > * factories,
1411     Reference<XComponentContext> const & xContext )
1412 {
1413     const Reference<loader::XImplementationLoader> xLoader(
1414         xContext->getServiceManager()->createInstanceWithContext(
1415             m_loader, xContext ), UNO_QUERY );
1416     if (! xLoader.is())
1417     {
1418         throw css::deployment::DeploymentException(
1419             (rtl::OUString(
1420                 RTL_CONSTASCII_USTRINGPARAM("cannot instantiate loader ")) +
1421              m_loader),
1422             static_cast< OWeakObject * >(this), Any());
1423     }
1424 
1425     // HACK: highly dependent on stoc/source/servicemanager
1426     //       and stoc/source/implreg implementation which rely on the same
1427     //       services.rdb format!
1428     //       .../UNO/LOCATION and .../UNO/ACTIVATOR appear not to be written by
1429     //       writeRegistryInfo, however, but are knwon, fixed values here, so
1430     //       can be passed into extractComponentData
1431     rtl::OUString url(getURL());
1432     const Reference<registry::XSimpleRegistry> xMemReg(
1433         xContext->getServiceManager()->createInstanceWithContext(
1434             OUSTR("com.sun.star.registry.SimpleRegistry"), xContext ),
1435         UNO_QUERY_THROW );
1436     xMemReg->open( OUString() /* in mem */, false, true );
1437     xLoader->writeRegistryInfo( xMemReg->getRootKey(), OUString(), url );
1438     getMyBackend()->extractComponentData(
1439         xContext, xMemReg->getRootKey(), data, factories, &xLoader, &url);
1440 }
1441 
1442 // Package
1443 //______________________________________________________________________________
1444 //We could use here BackendImpl::hasActiveEntry. However, this check is just as well.
1445 //And it also shows the problem if another extension has overwritten an implementation
1446 //entry, because it contains the same service implementation
1447 beans::Optional< beans::Ambiguous<sal_Bool> >
isRegistered_(::osl::ResettableMutexGuard &,::rtl::Reference<AbortChannel> const & abortChannel,Reference<XCommandEnvironment> const &)1448 BackendImpl::ComponentPackageImpl::isRegistered_(
1449     ::osl::ResettableMutexGuard &,
1450     ::rtl::Reference<AbortChannel> const & abortChannel,
1451     Reference<XCommandEnvironment> const & )
1452 {
1453     if (m_registered == REG_UNINIT)
1454     {
1455         m_registered = REG_NOT_REGISTERED;
1456         bool bAmbiguousComponentName = false;
1457         const Reference<registry::XSimpleRegistry> xRDB( getRDB_RO() );
1458         if (xRDB.is())
1459         {
1460             // lookup rdb for location URL:
1461             const Reference<registry::XRegistryKey> xRootKey(
1462                 xRDB->getRootKey() );
1463             const Reference<registry::XRegistryKey> xImplKey(
1464                 xRootKey->openKey( OUSTR("IMPLEMENTATIONS") ) );
1465             Sequence<OUString> implNames;
1466             if (xImplKey.is() && xImplKey->isValid())
1467                 implNames = xImplKey->getKeyNames();
1468             OUString const * pImplNames = implNames.getConstArray();
1469             sal_Int32 pos = implNames.getLength();
1470             for ( ; pos--; )
1471             {
1472                 checkAborted( abortChannel );
1473                 const OUString key(
1474                     pImplNames[ pos ] + OUSTR("/UNO/LOCATION") );
1475                 const Reference<registry::XRegistryKey> xKey(
1476                     xRootKey->openKey(key) );
1477                 if (xKey.is() && xKey->isValid())
1478                 {
1479                     const OUString location( xKey->getAsciiValue() );
1480                     if (location.equalsIgnoreAsciiCase( getURL() ))
1481                     {
1482                         break;
1483                     }
1484                     else
1485                     {
1486                         //try to match only the file name
1487                         OUString thisUrl(getURL());
1488                         OUString thisFileName(thisUrl.copy(thisUrl.lastIndexOf('/')));
1489 
1490                         OUString locationFileName(location.copy(location.lastIndexOf('/')));
1491                         if (locationFileName.equalsIgnoreAsciiCase(thisFileName))
1492                             bAmbiguousComponentName = true;
1493                     }
1494                 }
1495             }
1496             if (pos >= 0)
1497                 m_registered = REG_REGISTERED;
1498             else if (bAmbiguousComponentName)
1499                 m_registered = REG_MAYBE_REGISTERED;
1500         }
1501     }
1502 
1503     //Different extensions can use the same service implementations. Then the extensions
1504     //which was installed last will overwrite the one from the other extension. That is
1505     //the registry will contain the path (the location) of the library or jar of the
1506     //second extension. In this case isRegistered called for the lib of the first extension
1507     //would return "not registered". That would mean that during uninstallation
1508     //XPackage::registerPackage is not called, because it just was not registered. This is,
1509     //however, necessary for jar files. Registering and unregistering update
1510     //uno_packages/cache/registry/com.sun.star.comp.deployment.component.PackageRegistryBackend/unorc
1511     //Therefore, we will return always "is ambiguous" if the path of this component cannot
1512     //be found in the registry and if there is another path and both have the same file name (but
1513     //the rest of the path is different).
1514     //If the caller cannot precisely determine that this package was registered, then it must
1515     //call registerPackage.
1516     sal_Bool bAmbiguous = m_registered == REG_VOID // REG_VOID == we are in the progress of unregistration
1517         || m_registered == REG_MAYBE_REGISTERED;
1518     return beans::Optional< beans::Ambiguous<sal_Bool> >(
1519         true /* IsPresent */,
1520         beans::Ambiguous<sal_Bool>(
1521             m_registered == REG_REGISTERED, bAmbiguous) );
1522 }
1523 
1524 //______________________________________________________________________________
processPackage_(::osl::ResettableMutexGuard &,bool doRegisterPackage,bool startup,::rtl::Reference<AbortChannel> const & abortChannel,Reference<XCommandEnvironment> const & xCmdEnv)1525 void BackendImpl::ComponentPackageImpl::processPackage_(
1526     ::osl::ResettableMutexGuard &,
1527     bool doRegisterPackage,
1528     bool startup,
1529     ::rtl::Reference<AbortChannel> const & abortChannel,
1530     Reference<XCommandEnvironment> const & xCmdEnv )
1531 {
1532     BackendImpl * that = getMyBackend();
1533     rtl::OUString url(getURL());
1534     if (doRegisterPackage) {
1535         ComponentBackendDb::Data data;
1536         css::uno::Reference< css::uno::XComponentContext > context;
1537         if (startup) {
1538             context = that->getComponentContext();
1539         } else {
1540             context.set(that->getObject(url), css::uno::UNO_QUERY);
1541             if (!context.is()) {
1542                 context.set(
1543                     that->insertObject(
1544                         url,
1545                         raise_uno_process(
1546                             that->getComponentContext(), abortChannel)),
1547                     css::uno::UNO_QUERY_THROW);
1548             }
1549         }
1550         css::uno::Reference< css::registry::XImplementationRegistration>(
1551             context->getServiceManager()->createInstanceWithContext(
1552                 rtl::OUString(
1553                     RTL_CONSTASCII_USTRINGPARAM(
1554                         "com.sun.star.registry.ImplementationRegistration")),
1555                 context),
1556             css::uno::UNO_QUERY_THROW)->registerImplementation(
1557                 m_loader, url, getRDB());
1558         // Only write to unorc after successful registration; it may fail if
1559         // there is no suitable java
1560         if (m_loader.equalsAsciiL(
1561                 RTL_CONSTASCII_STRINGPARAM("com.sun.star.loader.Java2")) &&
1562             !jarManifestHeaderPresent(url, OUSTR("UNO-Type-Path"), xCmdEnv))
1563         {
1564             that->addToUnoRc(RCITEM_JAR_TYPELIB, url, xCmdEnv);
1565             data.javaTypeLibrary = true;
1566         }
1567         std::vector< css::uno::Reference< css::uno::XInterface > > factories;
1568         getComponentInfo(&data, &factories, context);
1569         if (!startup) {
1570             that->componentLiveInsertion(data, factories);
1571         }
1572         m_registered = REG_REGISTERED;
1573         that->addDataToDb(url, data);
1574     } else { // revoke
1575         m_registered = REG_VOID;
1576         ComponentBackendDb::Data data(that->readDataFromDb(url));
1577         css::uno::Reference< css::uno::XComponentContext > context(
1578             that->getObject(url), css::uno::UNO_QUERY);
1579         bool remoteContext = context.is();
1580         if (!remoteContext) {
1581             context = that->getComponentContext();
1582         }
1583         if (!startup) {
1584             that->componentLiveRemoval(data);
1585         }
1586         css::uno::Reference< css::registry::XImplementationRegistration >(
1587             context->getServiceManager()->createInstanceWithContext(
1588                 rtl::OUString(
1589                     RTL_CONSTASCII_USTRINGPARAM(
1590                         "com.sun.star.registry.ImplementationRegistration")),
1591                 context),
1592             css::uno::UNO_QUERY_THROW)->revokeImplementation(url, getRDB());
1593         if (data.javaTypeLibrary) {
1594             that->removeFromUnoRc(RCITEM_JAR_TYPELIB, url, xCmdEnv);
1595         }
1596         if (remoteContext) {
1597             that->releaseObject(url);
1598         }
1599         m_registered = REG_NOT_REGISTERED;
1600         getMyBackend()->revokeEntryFromDb(url);
1601     }
1602 }
1603 
1604 //##############################################################################
TypelibraryPackageImpl(::rtl::Reference<PackageRegistryBackend> const & myBackend,OUString const & url,OUString const & name,Reference<deployment::XPackageTypeInfo> const & xPackageType,bool jarFile,bool bRemoved,OUString const & identifier)1605 BackendImpl::TypelibraryPackageImpl::TypelibraryPackageImpl(
1606     ::rtl::Reference<PackageRegistryBackend> const & myBackend,
1607     OUString const & url, OUString const & name,
1608     Reference<deployment::XPackageTypeInfo> const & xPackageType,
1609     bool jarFile, bool bRemoved, OUString const & identifier)
1610     : Package( myBackend, url, name, name /* display-name */,
1611                xPackageType, bRemoved, identifier),
1612       m_jarFile( jarFile )
1613 {
1614 }
1615 
1616 // Package
getMyBackend() const1617 BackendImpl * BackendImpl::TypelibraryPackageImpl::getMyBackend() const
1618 {
1619     BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get());
1620     if (NULL == pBackend)
1621     {
1622         //May throw a DisposedException
1623         check();
1624         //We should never get here...
1625         throw RuntimeException(
1626             OUSTR("Failed to get the BackendImpl"),
1627             static_cast<OWeakObject*>(const_cast<TypelibraryPackageImpl *>(this)));
1628     }
1629     return pBackend;
1630 }
1631 //______________________________________________________________________________
1632 beans::Optional< beans::Ambiguous<sal_Bool> >
isRegistered_(::osl::ResettableMutexGuard &,::rtl::Reference<AbortChannel> const &,Reference<XCommandEnvironment> const &)1633 BackendImpl::TypelibraryPackageImpl::isRegistered_(
1634     ::osl::ResettableMutexGuard &,
1635     ::rtl::Reference<AbortChannel> const &,
1636     Reference<XCommandEnvironment> const & )
1637 {
1638     BackendImpl * that = getMyBackend();
1639     return beans::Optional< beans::Ambiguous<sal_Bool> >(
1640         true /* IsPresent */,
1641         beans::Ambiguous<sal_Bool>(
1642             that->hasInUnoRc(
1643                 m_jarFile ? RCITEM_JAR_TYPELIB : RCITEM_RDB_TYPELIB, getURL() ),
1644             false /* IsAmbiguous */ ) );
1645 }
1646 
1647 //______________________________________________________________________________
processPackage_(::osl::ResettableMutexGuard &,bool doRegisterPackage,bool,::rtl::Reference<AbortChannel> const &,Reference<XCommandEnvironment> const & xCmdEnv)1648 void BackendImpl::TypelibraryPackageImpl::processPackage_(
1649     ::osl::ResettableMutexGuard &,
1650     bool doRegisterPackage,
1651     bool /*startup*/,
1652     ::rtl::Reference<AbortChannel> const &,
1653     Reference<XCommandEnvironment> const & xCmdEnv )
1654 {
1655     BackendImpl * that = getMyBackend();
1656     const OUString url( getURL() );
1657 
1658     if (doRegisterPackage)
1659     {
1660         // live insertion:
1661         if (m_jarFile) {
1662             // xxx todo add to classpath at runtime: ???
1663             //SB: It is probably not worth it to add the live inserted type
1664             // library JAR to the UnoClassLoader in the soffice process.  Any
1665             // live inserted component JAR that might reference this type
1666             // library JAR runs in its own uno process, so there is probably no
1667             // Java code in the soffice process that would see any UNO types
1668             // introduced by this type library JAR.
1669         }
1670         else // RDB:
1671         {
1672             Reference<XComponentContext> const & xContext =
1673                 that->getComponentContext();
1674             if (! m_xTDprov.is())
1675             {
1676                 m_xTDprov.set( that->getObject( url ), UNO_QUERY );
1677                 if (! m_xTDprov.is())
1678                 {
1679                     const Reference<registry::XSimpleRegistry> xReg(
1680                         xContext->getServiceManager()
1681                         ->createInstanceWithContext(
1682                             OUSTR("com.sun.star.registry.SimpleRegistry"),
1683                             xContext ), UNO_QUERY_THROW );
1684                     xReg->open( expandUnoRcUrl(url),
1685                                 true /* read-only */, false /* ! create */ );
1686                     const Any arg(xReg);
1687                     Reference<container::XHierarchicalNameAccess> xTDprov(
1688                         xContext->getServiceManager()
1689                         ->createInstanceWithArgumentsAndContext(
1690                             OUSTR("com.sun.star.comp.stoc."
1691                                   "RegistryTypeDescriptionProvider"),
1692                             Sequence<Any>( &arg, 1 ), xContext ), UNO_QUERY );
1693                     OSL_ASSERT( xTDprov.is() );
1694                     if (xTDprov.is())
1695                         m_xTDprov.set( that->insertObject( url, xTDprov ),
1696                                        UNO_QUERY_THROW );
1697                 }
1698             }
1699             if (m_xTDprov.is()) {
1700                 Reference<container::XSet> xSet(
1701                     xContext->getValueByName(
1702                         OUSTR("/singletons/com.sun.star."
1703                               "reflection.theTypeDescriptionManager") ),
1704                     UNO_QUERY_THROW );
1705                 xSet->insert( Any(m_xTDprov) );
1706             }
1707         }
1708 
1709         that->addToUnoRc( m_jarFile ? RCITEM_JAR_TYPELIB : RCITEM_RDB_TYPELIB,
1710                           url, xCmdEnv );
1711     }
1712     else // revokePackage()
1713     {
1714         that->removeFromUnoRc(
1715             m_jarFile ? RCITEM_JAR_TYPELIB : RCITEM_RDB_TYPELIB, url, xCmdEnv );
1716 
1717         // revoking types at runtime, possible, sensible?
1718         if (!m_xTDprov.is())
1719             m_xTDprov.set( that->getObject( url ), UNO_QUERY );
1720         if (m_xTDprov.is()) {
1721             // remove live:
1722             const Reference<container::XSet> xSet(
1723                 that->getComponentContext()->getValueByName(
1724                     OUSTR("/singletons/com.sun.star."
1725                           "reflection.theTypeDescriptionManager") ),
1726                 UNO_QUERY_THROW );
1727             xSet->remove( Any(m_xTDprov) );
1728 
1729             that->releaseObject( url );
1730             m_xTDprov.clear();
1731         }
1732     }
1733 }
1734 
getMyBackend() const1735 BackendImpl * BackendImpl::ComponentsPackageImpl::getMyBackend() const
1736 {
1737     BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get());
1738     if (NULL == pBackend)
1739     {
1740         //Throws a DisposedException
1741         check();
1742         //We should never get here...
1743         throw RuntimeException(
1744             OUSTR("Failed to get the BackendImpl"),
1745             static_cast<OWeakObject*>(const_cast<ComponentsPackageImpl *>(this)));
1746     }
1747     return pBackend;
1748 }
1749 
1750 beans::Optional< beans::Ambiguous<sal_Bool> >
isRegistered_(::osl::ResettableMutexGuard &,::rtl::Reference<AbortChannel> const &,Reference<XCommandEnvironment> const &)1751 BackendImpl::ComponentsPackageImpl::isRegistered_(
1752     ::osl::ResettableMutexGuard &,
1753     ::rtl::Reference<AbortChannel> const &,
1754     Reference<XCommandEnvironment> const & )
1755 {
1756     return beans::Optional< beans::Ambiguous<sal_Bool> >(
1757         true,
1758         beans::Ambiguous<sal_Bool>(
1759             getMyBackend()->hasInUnoRc(RCITEM_COMPONENTS, getURL()), false));
1760 }
1761 
processPackage_(::osl::ResettableMutexGuard &,bool doRegisterPackage,bool startup,::rtl::Reference<AbortChannel> const & abortChannel,Reference<XCommandEnvironment> const & xCmdEnv)1762 void BackendImpl::ComponentsPackageImpl::processPackage_(
1763     ::osl::ResettableMutexGuard &,
1764     bool doRegisterPackage,
1765     bool startup,
1766     ::rtl::Reference<AbortChannel> const & abortChannel,
1767     Reference<XCommandEnvironment> const & xCmdEnv )
1768 {
1769     BackendImpl * that = getMyBackend();
1770     rtl::OUString url(getURL());
1771     if (doRegisterPackage) {
1772         ComponentBackendDb::Data data;
1773         data.javaTypeLibrary = false;
1774                 css::uno::Reference< css::uno::XComponentContext > context;
1775         if (startup) {
1776             context = that->getComponentContext();
1777         } else {
1778             context.set(that->getObject(url), css::uno::UNO_QUERY);
1779             if (!context.is()) {
1780                 context.set(
1781                     that->insertObject(
1782                         url,
1783                         raise_uno_process(
1784                             that->getComponentContext(), abortChannel)),
1785                     css::uno::UNO_QUERY_THROW);
1786             }
1787         }
1788 
1789         std::vector< css::uno::Reference< css::uno::XInterface > > factories;
1790 
1791         css::uno::Reference< css::registry::XSimpleRegistry > registry(
1792             css::uno::Reference< css::lang::XMultiComponentFactory >(
1793                 that->getComponentContext()->getServiceManager(),
1794                 css::uno::UNO_SET_THROW)->createInstanceWithContext(
1795                     rtl::OUString(
1796                         RTL_CONSTASCII_USTRINGPARAM(
1797                             "com.sun.star.registry.SimpleRegistry")),
1798                     that->getComponentContext()),
1799             css::uno::UNO_QUERY_THROW);
1800         registry->open(expandUnoRcUrl(url), true, false);
1801         getMyBackend()->extractComponentData(
1802             context,
1803             that->openRegistryKey(
1804                 registry->getRootKey(),
1805                 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("IMPLEMENTATIONS"))),
1806             &data, &factories, 0, 0);
1807         registry->close();
1808         if (!startup) {
1809             that->componentLiveInsertion(data, factories);
1810         }
1811         that->addDataToDb(url, data);
1812         that->addToUnoRc(RCITEM_COMPONENTS, url, xCmdEnv);
1813     } else { // revoke
1814         that->removeFromUnoRc(RCITEM_COMPONENTS, url, xCmdEnv);
1815         if (!startup) {
1816             that->componentLiveRemoval(that->readDataFromDb(url));
1817         }
1818         that->releaseObject(url);
1819         that->revokeEntryFromDb(url);
1820     }
1821 }
1822 
ComponentsPackageImpl(::rtl::Reference<PackageRegistryBackend> const & myBackend,OUString const & url,OUString const & name,Reference<deployment::XPackageTypeInfo> const & xPackageType,bool bRemoved,OUString const & identifier)1823 BackendImpl::ComponentsPackageImpl::ComponentsPackageImpl(
1824     ::rtl::Reference<PackageRegistryBackend> const & myBackend,
1825     OUString const & url, OUString const & name,
1826     Reference<deployment::XPackageTypeInfo> const & xPackageType,
1827     bool bRemoved, OUString const & identifier)
1828     : Package( myBackend, url, name, name /* display-name */,
1829                xPackageType, bRemoved, identifier)
1830 {}
1831 
1832 } // anon namespace
1833 
1834 namespace sdecl = comphelper::service_decl;
1835 sdecl::class_<BackendImpl, sdecl::with_args<true> > serviceBI;
1836 extern sdecl::ServiceDecl const serviceDecl(
1837     serviceBI,
1838     IMPLEMENTATION_NAME,
1839     BACKEND_SERVICE_NAME );
1840 
1841 } // namespace component
1842 } // namespace backend
1843 } // namespace dp_registry
1844