xref: /trunk/main/ucb/source/ucp/file/prov.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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 #include <osl/security.hxx>
31 #include <osl/file.hxx>
32 #include <osl/socket.h>
33 #include <cppuhelper/factory.hxx>
34 #ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBBUTE_HPP_
35 #include <com/sun/star/beans/PropertyAttribute.hpp>
36 #endif
37 #include <com/sun/star/ucb/FileSystemNotation.hpp>
38 #include <com/sun/star/beans/PropertyState.hpp>
39 #include "filglob.hxx"
40 #include "filid.hxx"
41 #include "shell.hxx"
42 #include "bc.hxx"
43 #include "prov.hxx"
44 
45 
46 using namespace fileaccess;
47 using namespace com::sun::star;
48 using namespace com::sun::star::uno;
49 using namespace com::sun::star::lang;
50 using namespace com::sun::star::beans;
51 using namespace com::sun::star::ucb;
52 using namespace com::sun::star::container;
53 
54 //=========================================================================
55 extern "C" void SAL_CALL component_getImplementationEnvironment(
56     const sal_Char ** ppEnvTypeName, uno_Environment ** )
57 {
58     *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
59 }
60 
61 //=========================================================================
62 extern "C" void * SAL_CALL component_getFactory(
63     const sal_Char * pImplName, void * pServiceManager, void * )
64 {
65     void * pRet = 0;
66 
67     Reference< XMultiServiceFactory > xSMgr(
68             reinterpret_cast< XMultiServiceFactory * >( pServiceManager ) );
69     Reference< XSingleServiceFactory > xFactory;
70 
71     //////////////////////////////////////////////////////////////////////
72     // File Content Provider.
73     //////////////////////////////////////////////////////////////////////
74 
75     if ( fileaccess::shell::getImplementationName_static().
76             compareToAscii( pImplName ) == 0 )
77     {
78         xFactory = FileProvider::createServiceFactory( xSMgr );
79     }
80 
81     //////////////////////////////////////////////////////////////////////
82 
83     if ( xFactory.is() )
84     {
85         xFactory->acquire();
86         pRet = xFactory.get();
87     }
88 
89     return pRet;
90 }
91 
92 /****************************************************************************/
93 /*                                                                          */
94 /*                                                                          */
95 /*                        FileProvider                                      */
96 /*                                                                          */
97 /*                                                                          */
98 /****************************************************************************/
99 
100 
101 
102 FileProvider::FileProvider( const Reference< XMultiServiceFactory >& xMultiServiceFactory )
103     : m_xMultiServiceFactory( xMultiServiceFactory ),
104       m_pMyShell( 0 )
105 {
106 }
107 
108 
109 FileProvider::~FileProvider()
110 {
111     if( m_pMyShell )
112         delete m_pMyShell;
113 }
114 
115 
116 //////////////////////////////////////////////////////////////////////////
117 // XInterface
118 //////////////////////////////////////////////////////////////////////////
119 
120 void SAL_CALL
121 FileProvider::acquire(
122     void )
123     throw()
124 {
125   OWeakObject::acquire();
126 }
127 
128 
129 void SAL_CALL
130 FileProvider::release(
131     void )
132   throw()
133 {
134   OWeakObject::release();
135 }
136 
137 
138 Any SAL_CALL
139 FileProvider::queryInterface(
140     const Type& rType )
141     throw( RuntimeException )
142 {
143     Any aRet = cppu::queryInterface(
144         rType,
145         SAL_STATIC_CAST( XContentProvider*, this ),
146         SAL_STATIC_CAST( XInitialization*, this ),
147         SAL_STATIC_CAST( XContentIdentifierFactory*, this ),
148         SAL_STATIC_CAST( XServiceInfo*,     this ),
149         SAL_STATIC_CAST( XTypeProvider*,    this ),
150         SAL_STATIC_CAST( XFileIdentifierConverter*,this ),
151         SAL_STATIC_CAST( XPropertySet*, this ) );
152     return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
153 }
154 
155 ///////////////////////////////////////////////////////////////////////////////
156 // XInitialization
157 
158 void SAL_CALL FileProvider::init()
159 {
160     if( ! m_pMyShell )
161         m_pMyShell = new shell( m_xMultiServiceFactory, this, sal_True );
162 }
163 
164 
165 void SAL_CALL
166 FileProvider::initialize(
167     const Sequence< Any >& aArguments )
168     throw (Exception, RuntimeException)
169 {
170     if( ! m_pMyShell ) {
171         rtl::OUString config;
172         if( aArguments.getLength() > 0 &&
173             (aArguments[0] >>= config) &&
174             config.compareToAscii("NoConfig") == 0 )
175             m_pMyShell = new shell( m_xMultiServiceFactory, this, sal_False );
176         else
177             m_pMyShell = new shell( m_xMultiServiceFactory, this, sal_True );
178     }
179 }
180 
181 
182 ////////////////////////////////////////////////////////////////////////////////
183 //
184 // XTypeProvider methods.
185 
186 
187 XTYPEPROVIDER_IMPL_7( FileProvider,
188                       XTypeProvider,
189                       XServiceInfo,
190                       XInitialization,
191                       XContentIdentifierFactory,
192                       XPropertySet,
193                       XFileIdentifierConverter,
194                       XContentProvider )
195 
196 
197 ////////////////////////////////////////////////////////////////////////////////
198 // XServiceInfo methods.
199 
200 rtl::OUString SAL_CALL
201 FileProvider::getImplementationName()
202     throw( RuntimeException )
203 {
204     return fileaccess::shell::getImplementationName_static();
205 }
206 
207 
208 sal_Bool SAL_CALL
209 FileProvider::supportsService(
210                   const rtl::OUString& ServiceName )
211   throw( RuntimeException )
212 {
213   return ServiceName == rtl::OUString::createFromAscii( "com.sun.star.ucb.FileContentProvider" );
214 }
215 
216 
217 Sequence< rtl::OUString > SAL_CALL
218 FileProvider::getSupportedServiceNames(
219                        void )
220   throw( RuntimeException )
221 {
222     return fileaccess::shell::getSupportedServiceNames_static();
223 }
224 
225 
226 
227 Reference< XSingleServiceFactory > SAL_CALL
228 FileProvider::createServiceFactory(
229                    const Reference< XMultiServiceFactory >& rxServiceMgr )
230 {
231   /**
232    * Create a single service factory.<BR>
233    * Note: The function pointer ComponentInstantiation points to a function throws Exception.
234    *
235    * @param rServiceManager     the service manager used by the implementation.
236    * @param rImplementationName the implementation name. An empty string is possible.
237    * @param ComponentInstantiation the function pointer to create an object.
238    * @param rServiceNames           the service supported by the implementation.
239    * @return a factory that support the interfaces XServiceProvider, XServiceInfo
240    *            XSingleServiceFactory and XComponent.
241    *
242    * @see createOneInstanceFactory
243    */
244   /*
245    *  Reference< ::com::sun::star::XSingleServiceFactory > createSingleFactory
246    *  (
247    *  const ::com::sun::star::Reference< ::com::sun::star::XMultiServiceFactory > & rServiceManager,
248    *  const ::rtl::OUString & rImplementationName,
249    *  ComponentInstantiation pCreateFunction,
250 
251    *  const ::com::sun::star::Sequence< ::rtl::OUString > & rServiceNames
252    *  );
253    */
254 
255     return Reference< XSingleServiceFactory > ( cppu::createSingleFactory(
256         rxServiceMgr,
257         fileaccess::shell::getImplementationName_static(),
258         FileProvider::CreateInstance,
259         fileaccess::shell::getSupportedServiceNames_static() ) );
260 }
261 
262 Reference< XInterface > SAL_CALL
263 FileProvider::CreateInstance(
264     const Reference< XMultiServiceFactory >& xMultiServiceFactory )
265 {
266     XServiceInfo* xP = (XServiceInfo*) new FileProvider( xMultiServiceFactory );
267     return Reference< XInterface >::query( xP );
268 }
269 
270 
271 
272 ////////////////////////////////////////////////////////////////////////////////
273 // XContent
274 ////////////////////////////////////////////////////////////////////////////////
275 
276 
277 Reference< XContent > SAL_CALL
278 FileProvider::queryContent(
279     const Reference< XContentIdentifier >& xIdentifier )
280     throw( IllegalIdentifierException,
281            RuntimeException)
282 {
283     init();
284     rtl::OUString aUnc;
285     sal_Bool err = m_pMyShell->getUnqFromUrl( xIdentifier->getContentIdentifier(),
286                                               aUnc );
287 
288     if(  err )
289         throw IllegalIdentifierException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
290 
291     return Reference< XContent >( new BaseContent( m_pMyShell,xIdentifier,aUnc ) );
292 }
293 
294 
295 
296 sal_Int32 SAL_CALL
297 FileProvider::compareContentIds(
298                 const Reference< XContentIdentifier >& Id1,
299                 const Reference< XContentIdentifier >& Id2 )
300   throw( RuntimeException )
301 {
302     init();
303     rtl::OUString aUrl1 = Id1->getContentIdentifier();
304     rtl::OUString aUrl2 = Id2->getContentIdentifier();
305 
306     sal_Int32   iComp = aUrl1.compareTo( aUrl2 );
307 
308     if ( 0 != iComp )
309     {
310         rtl::OUString aPath1, aPath2;
311 
312         m_pMyShell->getUnqFromUrl( aUrl1, aPath1 );
313         m_pMyShell->getUnqFromUrl( aUrl2, aPath2 );
314 
315         osl::FileBase::RC   error;
316         osl::DirectoryItem  aItem1, aItem2;
317 
318         error = osl::DirectoryItem::get( aPath1, aItem1 );
319         if ( error == osl::FileBase::E_None )
320             error = osl::DirectoryItem::get( aPath2, aItem2 );
321 
322         if ( error != osl::FileBase::E_None )
323             return iComp;
324 
325         osl::FileStatus aStatus1( FileStatusMask_FileURL );
326         osl::FileStatus aStatus2( FileStatusMask_FileURL );
327         error = aItem1.getFileStatus( aStatus1 );
328         if ( error == osl::FileBase::E_None )
329             error = aItem2.getFileStatus( aStatus2 );
330 
331         if ( error == osl::FileBase::E_None )
332         {
333             iComp = aStatus1.getFileURL().compareTo( aStatus2.getFileURL() );
334 
335 // Quick hack for Windows to threat all file systems as case insensitive
336 #ifdef  WNT
337             if ( 0 != iComp )
338             {
339                 error = osl::FileBase::getSystemPathFromFileURL( aStatus1.getFileURL(), aPath1 );
340                 if ( error == osl::FileBase::E_None )
341                     error = osl::FileBase::getSystemPathFromFileURL( aStatus2.getFileURL(), aPath2 );
342 
343                 if ( error == osl::FileBase::E_None )
344                     iComp = rtl_ustr_compareIgnoreAsciiCase( aPath1.getStr(), aPath2.getStr() );
345             }
346 #endif
347         }
348     }
349 
350     return iComp;
351 }
352 
353 
354 
355 Reference< XContentIdentifier > SAL_CALL
356 FileProvider::createContentIdentifier(
357                       const rtl::OUString& ContentId )
358   throw( RuntimeException )
359 {
360     init();
361     FileContentIdentifier* p = new FileContentIdentifier( m_pMyShell,ContentId,false );
362     return Reference< XContentIdentifier >( p );
363 }
364 
365 
366 
367 //XPropertySetInfoImpl
368 
369 class XPropertySetInfoImpl2
370     : public cppu::OWeakObject,
371       public XPropertySetInfo
372 {
373 public:
374     XPropertySetInfoImpl2();
375     ~XPropertySetInfoImpl2();
376 
377     // XInterface
378     virtual Any SAL_CALL
379     queryInterface(
380         const Type& aType )
381         throw( RuntimeException);
382 
383     virtual void SAL_CALL
384     acquire(
385         void )
386         throw();
387 
388     virtual void SAL_CALL
389     release(
390         void )
391         throw();
392 
393 
394     virtual Sequence< Property > SAL_CALL
395     getProperties(
396         void )
397         throw( RuntimeException );
398 
399     virtual Property SAL_CALL
400     getPropertyByName(
401         const rtl::OUString& aName )
402         throw( UnknownPropertyException,
403                RuntimeException);
404 
405     virtual sal_Bool SAL_CALL
406     hasPropertyByName( const rtl::OUString& Name )
407         throw( RuntimeException );
408 
409 
410 private:
411     Sequence< Property > m_seq;
412 };
413 
414 
415 XPropertySetInfoImpl2::XPropertySetInfoImpl2()
416     : m_seq( 3 )
417 {
418     m_seq[0] = Property( rtl::OUString::createFromAscii( "HostName" ),
419                          -1,
420                          getCppuType( static_cast< rtl::OUString* >( 0 ) ),
421                          PropertyAttribute::READONLY );
422 
423     m_seq[1] = Property( rtl::OUString::createFromAscii( "HomeDirectory" ),
424                          -1,
425                          getCppuType( static_cast< rtl::OUString* >( 0 ) ),
426                          PropertyAttribute::READONLY );
427 
428     m_seq[2] = Property( rtl::OUString::createFromAscii( "FileSystemNotation" ),
429                          -1,
430                          getCppuType( static_cast< sal_Int32* >( 0 ) ),
431                          PropertyAttribute::READONLY );
432 }
433 
434 
435 XPropertySetInfoImpl2::~XPropertySetInfoImpl2()
436 {
437     // nothing
438 }
439 
440 
441 void SAL_CALL
442 XPropertySetInfoImpl2::acquire(
443     void )
444     throw()
445 {
446     OWeakObject::acquire();
447 }
448 
449 
450 void SAL_CALL
451 XPropertySetInfoImpl2::release(
452     void )
453     throw()
454 {
455     OWeakObject::release();
456 }
457 
458 
459 Any SAL_CALL
460 XPropertySetInfoImpl2::queryInterface(
461     const Type& rType )
462     throw( RuntimeException )
463 {
464     Any aRet = cppu::queryInterface( rType,
465                                           SAL_STATIC_CAST( XPropertySetInfo*,this) );
466     return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
467 }
468 
469 
470 Property SAL_CALL
471 XPropertySetInfoImpl2::getPropertyByName(
472     const rtl::OUString& aName )
473     throw( UnknownPropertyException,
474            RuntimeException)
475 {
476     for( sal_Int32 i = 0; i < m_seq.getLength(); ++i )
477         if( m_seq[i].Name == aName )
478             return m_seq[i];
479 
480     throw UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
481 }
482 
483 
484 
485 Sequence< Property > SAL_CALL
486 XPropertySetInfoImpl2::getProperties(
487     void )
488     throw( RuntimeException )
489 {
490     return m_seq;
491 }
492 
493 
494 sal_Bool SAL_CALL
495 XPropertySetInfoImpl2::hasPropertyByName(
496     const rtl::OUString& aName )
497     throw( RuntimeException )
498 {
499     for( sal_Int32 i = 0; i < m_seq.getLength(); ++i )
500         if( m_seq[i].Name == aName )
501             return true;
502     return false;
503 }
504 
505 
506 
507 
508 
509 void SAL_CALL FileProvider::initProperties( void )
510 {
511     osl::MutexGuard aGuard( m_aMutex );
512     if( ! m_xPropertySetInfo.is() )
513     {
514         osl_getLocalHostname( &m_HostName.pData );
515 
516 #if defined ( UNX )
517         m_FileSystemNotation = FileSystemNotation::UNIX_NOTATION;
518 #elif defined( WNT ) || defined( OS2 )
519         m_FileSystemNotation = FileSystemNotation::DOS_NOTATION;
520 #else
521         m_FileSystemNotation = FileSystemNotation::UNKNOWN_NOTATION;
522 #endif
523         osl::Security aSecurity;
524         aSecurity.getHomeDir( m_HomeDirectory );
525 
526         // static const sal_Int32 UNKNOWN_NOTATION = (sal_Int32)0;
527         // static const sal_Int32 UNIX_NOTATION = (sal_Int32)1;
528         // static const sal_Int32 DOS_NOTATION = (sal_Int32)2;
529         // static const sal_Int32 MAC_NOTATION = (sal_Int32)3;
530 
531         XPropertySetInfoImpl2* p = new XPropertySetInfoImpl2();
532         m_xPropertySetInfo = Reference< XPropertySetInfo >( p );
533     }
534 }
535 
536 
537 // XPropertySet
538 
539 Reference< XPropertySetInfo > SAL_CALL
540 FileProvider::getPropertySetInfo(  )
541     throw( RuntimeException )
542 {
543     initProperties();
544     return m_xPropertySetInfo;
545 }
546 
547 
548 void SAL_CALL
549 FileProvider::setPropertyValue( const rtl::OUString& aPropertyName,
550                                 const Any& )
551     throw( UnknownPropertyException,
552            PropertyVetoException,
553            IllegalArgumentException,
554            WrappedTargetException,
555            RuntimeException )
556 {
557     if( aPropertyName.compareToAscii( "FileSystemNotation" ) == 0 ||
558         aPropertyName.compareToAscii( "HomeDirectory" ) == 0      ||
559         aPropertyName.compareToAscii( "HostName" ) == 0 )
560         return;
561     else
562         throw UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
563 }
564 
565 
566 
567 Any SAL_CALL
568 FileProvider::getPropertyValue(
569     const rtl::OUString& aPropertyName )
570     throw( UnknownPropertyException,
571            WrappedTargetException,
572            RuntimeException )
573 {
574     initProperties();
575     if( aPropertyName.compareToAscii( "FileSystemNotation" ) == 0 )
576     {
577         Any aAny;
578         aAny <<= m_FileSystemNotation;
579         return aAny;
580     }
581     else if( aPropertyName.compareToAscii( "HomeDirectory" ) == 0 )
582     {
583         Any aAny;
584         aAny <<= m_HomeDirectory;
585         return aAny;
586     }
587     else if( aPropertyName.compareToAscii( "HostName" ) == 0 )
588     {
589         Any aAny;
590         aAny <<= m_HostName;
591         return aAny;
592     }
593     else
594         throw UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
595 }
596 
597 
598 void SAL_CALL
599 FileProvider::addPropertyChangeListener(
600     const rtl::OUString&,
601     const Reference< XPropertyChangeListener >& )
602     throw( UnknownPropertyException,
603            WrappedTargetException,
604            RuntimeException)
605 {
606     return;
607 }
608 
609 
610 void SAL_CALL
611 FileProvider::removePropertyChangeListener(
612     const rtl::OUString&,
613     const Reference< XPropertyChangeListener >& )
614     throw( UnknownPropertyException,
615            WrappedTargetException,
616            RuntimeException )
617 {
618     return;
619 }
620 
621 void SAL_CALL
622 FileProvider::addVetoableChangeListener(
623     const rtl::OUString&,
624     const Reference< XVetoableChangeListener >& )
625     throw( UnknownPropertyException,
626            WrappedTargetException,
627            RuntimeException )
628 {
629     return;
630 }
631 
632 
633 void SAL_CALL
634 FileProvider::removeVetoableChangeListener(
635     const rtl::OUString&,
636     const Reference< XVetoableChangeListener >& )
637     throw( UnknownPropertyException,
638            WrappedTargetException,
639            RuntimeException)
640 {
641     return;
642 }
643 
644 
645 
646 // XFileIdentifierConverter
647 
648 sal_Int32 SAL_CALL
649 FileProvider::getFileProviderLocality( const rtl::OUString& BaseURL )
650     throw( RuntimeException )
651 {
652     // If the base URL is a 'file' URL, return 10 (very 'local'), otherwise
653     // return -1 (missmatch).  What is missing is a fast comparison to ASCII,
654     // ignoring case:
655     return BaseURL.getLength() >= 5
656            && (BaseURL[0] == 'F' || BaseURL[0] == 'f')
657            && (BaseURL[1] == 'I' || BaseURL[1] == 'i')
658            && (BaseURL[2] == 'L' || BaseURL[2] == 'l')
659            && (BaseURL[3] == 'E' || BaseURL[3] == 'e')
660            && BaseURL[4] == ':' ?
661                10 : -1;
662 }
663 
664 rtl::OUString SAL_CALL FileProvider::getFileURLFromSystemPath( const rtl::OUString&,
665                                                                const rtl::OUString& SystemPath )
666     throw( RuntimeException )
667 {
668     rtl::OUString aNormalizedPath;
669     if ( osl::FileBase::getFileURLFromSystemPath( SystemPath,aNormalizedPath ) != osl::FileBase::E_None )
670         return rtl::OUString();
671 
672     return aNormalizedPath;
673 }
674 
675 rtl::OUString SAL_CALL FileProvider::getSystemPathFromFileURL( const rtl::OUString& URL )
676     throw( RuntimeException )
677 {
678     rtl::OUString aSystemPath;
679     if (osl::FileBase::getSystemPathFromFileURL( URL,aSystemPath ) != osl::FileBase::E_None )
680         return rtl::OUString();
681 
682     return aSystemPath;
683 }
684 
685