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