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_ucb.hxx"
30 
31 /**************************************************************************
32                                 TODO
33  **************************************************************************
34 
35  *************************************************************************/
36 
37 #include <hash_map>
38 #include <osl/diagnose.h>
39 #include <cppuhelper/weak.hxx>
40 #include <ucbhelper/contentidentifier.hxx>
41 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
42 #include "pkgprovider.hxx"
43 #include "pkgcontent.hxx"
44 #include "pkguri.hxx"
45 
46 using namespace com::sun::star;
47 
48 namespace package_ucp
49 {
50 
51 //=========================================================================
52 //
53 // class Package.
54 //
55 //=========================================================================
56 
57 class Package : public cppu::OWeakObject,
58                 public container::XHierarchicalNameAccess
59 {
60     friend class ContentProvider;
61 
62     rtl::OUString                                        m_aName;
63     uno::Reference< container::XHierarchicalNameAccess > m_xNA;
64     ContentProvider*                                     m_pOwner;
65 
66 public:
67     Package( const rtl::OUString& rName,
68              const uno::Reference< container::XHierarchicalNameAccess > & xNA,
69              ContentProvider* pOwner )
70     : m_aName( rName ), m_xNA( xNA ), m_pOwner( pOwner ) {}
71     virtual ~Package() { m_pOwner->removePackage( m_aName ); }
72 
73     // XInterface
74     virtual uno::Any SAL_CALL
75     queryInterface( const uno::Type& aType )
76         throw( uno::RuntimeException )
77     { return m_xNA->queryInterface( aType ); }
78     virtual void SAL_CALL
79     acquire() throw()
80     { OWeakObject::acquire(); }
81     virtual void SAL_CALL
82     release() throw()
83     { OWeakObject::release(); }
84 
85     // XHierarchicalNameAccess
86     virtual uno::Any SAL_CALL
87     getByHierarchicalName( const rtl::OUString& aName )
88         throw( container::NoSuchElementException, uno::RuntimeException )
89     { return m_xNA->getByHierarchicalName( aName ); }
90     virtual sal_Bool SAL_CALL
91     hasByHierarchicalName( const rtl::OUString& aName )
92         throw( uno::RuntimeException )
93     { return m_xNA->hasByHierarchicalName( aName ); }
94 };
95 
96 //=========================================================================
97 //
98 // Packages.
99 //
100 //=========================================================================
101 
102 struct equalString
103 {
104     bool operator()(
105         const rtl::OUString& rKey1, const rtl::OUString& rKey2 ) const
106     {
107         return !!( rKey1 == rKey2 );
108     }
109 };
110 
111 struct hashString
112 {
113     size_t operator()( const rtl::OUString & rName ) const
114     {
115         return rName.hashCode();
116     }
117 };
118 
119 typedef std::hash_map
120 <
121     rtl::OUString,
122     Package*,
123     hashString,
124     equalString
125 >
126 PackageMap;
127 
128 class Packages : public PackageMap {};
129 
130 }
131 
132 using namespace package_ucp;
133 
134 //=========================================================================
135 //=========================================================================
136 //
137 // ContentProvider Implementation.
138 //
139 //=========================================================================
140 //=========================================================================
141 
142 ContentProvider::ContentProvider(
143             const uno::Reference< lang::XMultiServiceFactory >& rSMgr )
144 : ::ucbhelper::ContentProviderImplHelper( rSMgr ),
145   m_pPackages( 0 )
146 {
147 }
148 
149 //=========================================================================
150 // virtual
151 ContentProvider::~ContentProvider()
152 {
153     delete m_pPackages;
154 }
155 
156 //=========================================================================
157 //
158 // XInterface methods.
159 //
160 //=========================================================================
161 
162 XINTERFACE_IMPL_3( ContentProvider,
163                    lang::XTypeProvider,
164                    lang::XServiceInfo,
165                    ucb::XContentProvider );
166 
167 //=========================================================================
168 //
169 // XTypeProvider methods.
170 //
171 //=========================================================================
172 
173 XTYPEPROVIDER_IMPL_3( ContentProvider,
174                       lang::XTypeProvider,
175                       lang::XServiceInfo,
176                       ucb::XContentProvider );
177 
178 //=========================================================================
179 //
180 // XServiceInfo methods.
181 //
182 //=========================================================================
183 
184 XSERVICEINFO_IMPL_1( ContentProvider,
185                      rtl::OUString::createFromAscii(
186                         "com.sun.star.comp.ucb.PackageContentProvider" ),
187                      rtl::OUString::createFromAscii(
188                         PACKAGE_CONTENT_PROVIDER_SERVICE_NAME ) );
189 
190 //=========================================================================
191 //
192 // Service factory implementation.
193 //
194 //=========================================================================
195 
196 ONE_INSTANCE_SERVICE_FACTORY_IMPL( ContentProvider );
197 
198 //=========================================================================
199 //
200 // XContentProvider methods.
201 //
202 //=========================================================================
203 
204 // virtual
205 uno::Reference< ucb::XContent > SAL_CALL ContentProvider::queryContent(
206             const uno::Reference< ucb::XContentIdentifier >& Identifier )
207     throw( ucb::IllegalIdentifierException, uno::RuntimeException )
208 {
209     if ( !Identifier.is() )
210         return uno::Reference< ucb::XContent >();
211 
212     PackageUri aUri( Identifier->getContentIdentifier() );
213     if ( !aUri.isValid() )
214         throw ucb::IllegalIdentifierException();
215 
216     // Create a new identifier for the mormalized URL returned by
217     // PackageUri::getUri().
218     uno::Reference< ucb::XContentIdentifier > xId
219                 = new ::ucbhelper::ContentIdentifier( m_xSMgr, aUri.getUri() );
220 
221     osl::MutexGuard aGuard( m_aMutex );
222 
223     // Check, if a content with given id already exists...
224     uno::Reference< ucb::XContent > xContent
225         = queryExistingContent( xId ).get();
226     if ( xContent.is() )
227         return xContent;
228 
229     // Create a new content.
230 
231     xContent = Content::create( m_xSMgr, this, Identifier ); // not xId!!!
232     registerNewContent( xContent );
233 
234     if ( xContent.is() && !xContent->getIdentifier().is() )
235         throw ucb::IllegalIdentifierException();
236 
237     return xContent;
238 }
239 
240 //=========================================================================
241 //
242 // Other methods.
243 //
244 //=========================================================================
245 
246 uno::Reference< container::XHierarchicalNameAccess >
247 ContentProvider::createPackage( const rtl::OUString & rName, const rtl::OUString & rParam )
248 {
249     osl::MutexGuard aGuard( m_aMutex );
250 
251     if ( !rName.getLength() )
252     {
253         OSL_ENSURE( sal_False,
254                     "ContentProvider::createPackage - Invalid URL!" );
255         return uno::Reference< container::XHierarchicalNameAccess >();
256     }
257 
258 	rtl::OUString rURL = rName + rParam;
259 
260     if ( m_pPackages )
261     {
262         Packages::const_iterator it = m_pPackages->find( rURL );
263         if ( it != m_pPackages->end() )
264         {
265             // Already instanciated. Return package.
266             return (*it).second->m_xNA;
267         }
268     }
269     else
270         m_pPackages = new Packages;
271 
272     // Create new package...
273     try
274     {
275         uno::Sequence< uno::Any > aArguments( 1 );
276         aArguments[ 0 ] <<= rURL;
277 
278         uno::Reference< uno::XInterface > xIfc
279             = m_xSMgr->createInstanceWithArguments(
280                 rtl::OUString::createFromAscii(
281                                 "com.sun.star.packages.comp.ZipPackage" ),
282                 aArguments );
283 
284         if ( xIfc.is() )
285         {
286             uno::Reference<
287                 container::XHierarchicalNameAccess > xNameAccess(
288                                                         xIfc, uno::UNO_QUERY );
289 
290             OSL_ENSURE( xNameAccess.is(),
291                         "ContentProvider::createPackage - "
292                         "Got no hierarchical name access!" );
293 
294             rtl::Reference< Package> xPackage
295                 = new Package( rURL, xNameAccess, this );
296 
297             (*m_pPackages)[ rURL ] = xPackage.get();
298 
299             return xPackage.get();
300         }
301     }
302     catch ( uno::RuntimeException const & )
303     {
304         // createInstanceWithArguemts
305     }
306     catch ( uno::Exception const & )
307     {
308         // createInstanceWithArguemts
309     }
310 
311     return uno::Reference< container::XHierarchicalNameAccess >();
312 }
313 
314 //=========================================================================
315 sal_Bool ContentProvider::removePackage( const rtl::OUString & rName )
316 {
317     osl::MutexGuard aGuard( m_aMutex );
318 
319     if ( m_pPackages )
320     {
321         Packages::iterator it = m_pPackages->find( rName );
322         if ( it != m_pPackages->end() )
323         {
324             m_pPackages->erase( it );
325             return sal_True;
326         }
327     }
328     return sal_False;
329 }
330 
331