1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_desktop.hxx"
30 
31 #include "dp_manager.h"
32 #include "dp_resource.h"
33 #include "cppuhelper/compbase1.hxx"
34 #include "comphelper/servicedecl.hxx"
35 #include "com/sun/star/deployment/thePackageManagerFactory.hpp"
36 
37 
38 using namespace ::dp_misc;
39 using namespace ::com::sun::star;
40 using namespace ::com::sun::star::uno;
41 using ::rtl::OUString;
42 
43 namespace dp_manager {
44 namespace factory {
45 
46 typedef ::cppu::WeakComponentImplHelper1<
47     deployment::XPackageManagerFactory > t_pmfac_helper;
48 
49 //==============================================================================
50 class PackageManagerFactoryImpl : private MutexHolder, public t_pmfac_helper
51 {
52     Reference<XComponentContext> m_xComponentContext;
53 
54     Reference<deployment::XPackageManager> m_xUserMgr;
55     Reference<deployment::XPackageManager> m_xSharedMgr;
56     Reference<deployment::XPackageManager> m_xBundledMgr;
57     Reference<deployment::XPackageManager> m_xTmpMgr;
58     Reference<deployment::XPackageManager> m_xBakMgr;
59     typedef ::std::hash_map<
60         OUString, WeakReference<deployment::XPackageManager>,
61         ::rtl::OUStringHash > t_string2weakref;
62     t_string2weakref m_managers;
63 
64 protected:
65     inline void check();
66     virtual void SAL_CALL disposing();
67 
68 public:
69     virtual ~PackageManagerFactoryImpl();
70     PackageManagerFactoryImpl(
71         Reference<XComponentContext> const & xComponentContext );
72 
73     // XPackageManagerFactory
74     virtual Reference<deployment::XPackageManager> SAL_CALL getPackageManager(
75         OUString const & context ) throw (RuntimeException);
76 };
77 
78 //==============================================================================
79 namespace sdecl = comphelper::service_decl;
80 sdecl::class_<PackageManagerFactoryImpl> servicePMFI;
81 extern sdecl::ServiceDecl const serviceDecl(
82     servicePMFI,
83     // a private one:
84     "com.sun.star.comp.deployment.PackageManagerFactory",
85     "com.sun.star.comp.deployment.PackageManagerFactory" );
86 
87 //==============================================================================
88 bool singleton_entries(
89     Reference<registry::XRegistryKey> const & xRegistryKey )
90 {
91     try {
92         Reference<registry::XRegistryKey> xKey(
93             xRegistryKey->createKey(
94                 serviceDecl.getImplementationName() +
95                 // xxx todo: use future generated function to get singleton name
96                 OUSTR("/UNO/SINGLETONS/"
97                       "com.sun.star.deployment.thePackageManagerFactory") ) );
98         xKey->setStringValue( serviceDecl.getSupportedServiceNames()[0] );
99         return true;
100     }
101     catch (registry::InvalidRegistryException & exc) {
102         (void) exc; // avoid warnings
103         OSL_ENSURE( 0, ::rtl::OUStringToOString(
104                         exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() );
105         return false;
106     }
107 }
108 
109 //______________________________________________________________________________
110 PackageManagerFactoryImpl::PackageManagerFactoryImpl(
111     Reference<XComponentContext> const & xComponentContext )
112     : t_pmfac_helper( getMutex() ),
113       m_xComponentContext( xComponentContext )
114 {
115 }
116 
117 //______________________________________________________________________________
118 PackageManagerFactoryImpl::~PackageManagerFactoryImpl()
119 {
120 }
121 
122 //______________________________________________________________________________
123 inline void PackageManagerFactoryImpl::check()
124 {
125     ::osl::MutexGuard guard( getMutex() );
126     if (rBHelper.bInDispose || rBHelper.bDisposed)
127     {
128         throw lang::DisposedException(
129             OUSTR("PackageManagerFactory instance has already been disposed!"),
130             static_cast<OWeakObject *>(this) );
131     }
132 }
133 
134 //______________________________________________________________________________
135 void PackageManagerFactoryImpl::disposing()
136 {
137     // dispose all managers:
138     ::osl::MutexGuard guard( getMutex() );
139     t_string2weakref::const_iterator iPos( m_managers.begin() );
140     t_string2weakref::const_iterator const iEnd( m_managers.end() );
141     for ( ; iPos != iEnd; ++iPos )
142         try_dispose( iPos->second );
143     m_managers = t_string2weakref();
144     // the below are already disposed:
145     m_xUserMgr.clear();
146     m_xSharedMgr.clear();
147     m_xBundledMgr.clear();
148     m_xTmpMgr.clear();
149     m_xBakMgr.clear();
150 }
151 
152 // XPackageManagerFactory
153 //______________________________________________________________________________
154 Reference<deployment::XPackageManager>
155 PackageManagerFactoryImpl::getPackageManager( OUString const & context )
156     throw (RuntimeException)
157 {
158     Reference< deployment::XPackageManager > xRet;
159     ::osl::ResettableMutexGuard guard( getMutex() );
160     check();
161     t_string2weakref::const_iterator const iFind( m_managers.find( context ) );
162     if (iFind != m_managers.end()) {
163         xRet = iFind->second;
164         if (xRet.is())
165             return xRet;
166     }
167 
168     guard.clear();
169     xRet.set( PackageManagerImpl::create( m_xComponentContext, context ) );
170     guard.reset();
171     ::std::pair< t_string2weakref::iterator, bool > insertion(
172         m_managers.insert( t_string2weakref::value_type( context, xRet ) ) );
173     if (insertion.second)
174     {
175         OSL_ASSERT( insertion.first->second.get() == xRet );
176         // hold user, shared mgrs for whole process: live deployment
177         if (context.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("user") ))
178             m_xUserMgr = xRet;
179         else if (context.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("shared") ))
180             m_xSharedMgr = xRet;
181         else if (context.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("bundled") ))
182             m_xBundledMgr = xRet;
183         else if (context.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("tmp") ))
184             m_xTmpMgr = xRet;
185         else if (context.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("bak") ))
186             m_xBakMgr = xRet;
187     }
188     else
189     {
190         Reference< deployment::XPackageManager > xAlreadyIn(
191             insertion.first->second );
192         if (xAlreadyIn.is())
193         {
194             guard.clear();
195             try_dispose( xRet );
196             xRet = xAlreadyIn;
197         }
198         else
199         {
200             insertion.first->second = xRet;
201         }
202     }
203     return xRet;
204 }
205 
206 } // namespace factory
207 } // namespace dp_manager
208 
209