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