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 #include <osl/mutex.hxx>
25 #include <osl/diagnose.h>
26
27 #include "fileaccess/dllapi.h"
28
29 #include <uno/mapping.hxx>
30
31 #include <cppuhelper/factory.hxx>
32 #include <cppuhelper/implbase1.hxx>
33 #include <cppuhelper/implementationentry.hxx>
34
35 #include <tools/ref.hxx>
36 #include <tools/urlobj.hxx>
37 #include <ucbhelper/content.hxx>
38 #include <unotools/streamwrap.hxx>
39 #include <tools/stream.hxx>
40
41 #include <com/sun/star/beans/Property.hpp>
42 #include <com/sun/star/beans/XPropertySet.hpp>
43 #include <com/sun/star/container/XChild.hpp>
44 #include <com/sun/star/io/XActiveDataSink.hpp>
45 #include <com/sun/star/io/XActiveDataSource.hpp>
46 #include <com/sun/star/io/XActiveDataStreamer.hpp>
47 #include <com/sun/star/sdbc/XResultSet.hpp>
48 #include <com/sun/star/ucb/CommandFailedException.hpp>
49 #include <com/sun/star/ucb/ContentInfo.hpp>
50 #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
51 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
52 #include <com/sun/star/ucb/InteractiveIOException.hpp>
53 #include <com/sun/star/ucb/NameClash.hpp>
54 #include <com/sun/star/ucb/NameClashException.hpp>
55 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
56 #include <com/sun/star/ucb/OpenMode.hpp>
57 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
58 #include <com/sun/star/ucb/XContent.hpp>
59 #include <com/sun/star/ucb/XContentAccess.hpp>
60 #include <com/sun/star/ucb/XSimpleFileAccess3.hpp>
61 #include <com/sun/star/util/XMacroExpander.hpp>
62
63 using namespace ::com::sun::star::uno;
64 using namespace ::com::sun::star::lang;
65 using namespace ::com::sun::star::io;
66 using namespace ::com::sun::star::ucb;
67 using namespace ::com::sun::star::sdbc;
68 using namespace ::com::sun::star::task;
69 using namespace ::com::sun::star::util;
70 using namespace ::com::sun::star::beans;
71 using namespace ::com::sun::star::registry;
72 using namespace ::com::sun::star::container;
73
74 namespace io_FileAccess
75 {
76
77
78 //===========================================================================
79 // Implementation XSimpleFileAccess
80
81 typedef cppu::WeakImplHelper1< XSimpleFileAccess3 > FileAccessHelper;
82 class OCommandEnvironment;
83
84 class OFileAccess : public FileAccessHelper
85 {
86 Reference< XComponentContext > mxCtx;
87 Reference< XCommandEnvironment > mxEnvironment;
88 OCommandEnvironment* mpEnvironment;
89
90 void transferImpl( const rtl::OUString& rSource, const rtl::OUString& rDest, sal_Bool bMoveData );
91 bool createNewFile( const rtl::OUString & rParentURL,
92 const rtl::OUString & rTitle,
93 const Reference< XInputStream >& data );
94
95 public:
OFileAccess(const Reference<XComponentContext> & xCtx)96 OFileAccess( const Reference< XComponentContext > & xCtx )
97 : mxCtx( xCtx ), mpEnvironment( NULL ) {}
98
99 // Methods
100 virtual void SAL_CALL copy( const ::rtl::OUString& SourceURL, const ::rtl::OUString& DestURL );
101 virtual void SAL_CALL move( const ::rtl::OUString& SourceURL, const ::rtl::OUString& DestURL );
102 virtual void SAL_CALL kill( const ::rtl::OUString& FileURL );
103 virtual sal_Bool SAL_CALL isFolder( const ::rtl::OUString& FileURL );
104 virtual sal_Bool SAL_CALL isReadOnly( const ::rtl::OUString& FileURL );
105 virtual void SAL_CALL setReadOnly( const ::rtl::OUString& FileURL, sal_Bool bReadOnly );
106 virtual void SAL_CALL createFolder( const ::rtl::OUString& NewFolderURL );
107 virtual sal_Int32 SAL_CALL getSize( const ::rtl::OUString& FileURL );
108 virtual ::rtl::OUString SAL_CALL getContentType( const ::rtl::OUString& FileURL );
109 virtual ::com::sun::star::util::DateTime SAL_CALL getDateTimeModified( const ::rtl::OUString& FileURL );
110 virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getFolderContents( const ::rtl::OUString& FolderURL, sal_Bool bIncludeFolders );
111 virtual sal_Bool SAL_CALL exists( const ::rtl::OUString& FileURL );
112 virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL openFileRead( const ::rtl::OUString& FileURL );
113 virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream > SAL_CALL openFileWrite( const ::rtl::OUString& FileURL );
114 virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XStream > SAL_CALL openFileReadWrite( const ::rtl::OUString& FileURL );
115 virtual void SAL_CALL setInteractionHandler( const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& Handler );
116 virtual void SAL_CALL writeFile( const ::rtl::OUString& FileURL, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& data );
117 virtual sal_Bool SAL_CALL isHidden( const ::rtl::OUString& FileURL );
118 virtual void SAL_CALL setHidden( const ::rtl::OUString& FileURL, sal_Bool bHidden );
119 };
120
121
122 //===========================================================================
123 // Implementation XActiveDataSink
124
125 typedef cppu::WeakImplHelper1< XActiveDataSink > ActiveDataSinkHelper;
126
127 class OActiveDataSink : public ActiveDataSinkHelper
128 {
129 Reference< XInputStream > mxStream;
130
131 public:
132
133 // Methods
134 virtual void SAL_CALL setInputStream( const Reference< XInputStream >& aStream );
135 virtual Reference< XInputStream > SAL_CALL getInputStream( );
136 };
137
setInputStream(const Reference<XInputStream> & aStream)138 void OActiveDataSink::setInputStream( const Reference< XInputStream >& aStream )
139 {
140 mxStream = aStream;
141 }
142
getInputStream()143 Reference< XInputStream > OActiveDataSink::getInputStream()
144 {
145 return mxStream;
146 }
147
148
149 //===========================================================================
150 // Implementation XActiveDataSource
151
152 typedef cppu::WeakImplHelper1< XActiveDataSource > ActiveDataSourceHelper;
153
154 class OActiveDataSource : public ActiveDataSourceHelper
155 {
156 Reference< XOutputStream > mxStream;
157
158 public:
159
160 // Methods
161 virtual void SAL_CALL setOutputStream( const Reference< XOutputStream >& aStream );
162 virtual Reference< XOutputStream > SAL_CALL getOutputStream();
163 };
164
setOutputStream(const Reference<XOutputStream> & aStream)165 void OActiveDataSource::setOutputStream( const Reference< XOutputStream >& aStream )
166 {
167 mxStream = aStream;
168 }
169
getOutputStream()170 Reference< XOutputStream > OActiveDataSource::getOutputStream()
171 {
172 return mxStream;
173 }
174
175
176 //===========================================================================
177 // Implementation XActiveDataStreamer
178
179 typedef cppu::WeakImplHelper1< XActiveDataStreamer > ActiveDataStreamerHelper;
180
181 class OActiveDataStreamer : public ActiveDataStreamerHelper
182 {
183 Reference< XStream > mxStream;
184
185 public:
186
187 // Methods
188 virtual void SAL_CALL setStream( const Reference< XStream >& aStream );
189 virtual Reference< XStream > SAL_CALL getStream();
190 };
191
setStream(const Reference<XStream> & aStream)192 void OActiveDataStreamer::setStream( const Reference< XStream >& aStream )
193 {
194 mxStream = aStream;
195 }
196
getStream()197 Reference< XStream > OActiveDataStreamer::getStream()
198 {
199 return mxStream;
200 }
201
202
203
204 //===========================================================================
205 // Implementation XCommandEnvironment
206
207 typedef cppu::WeakImplHelper1< XCommandEnvironment > CommandEnvironmentHelper;
208
209 class OCommandEnvironment : public CommandEnvironmentHelper
210 {
211 Reference< XInteractionHandler > mxInteraction;
212
213 public:
setHandler(Reference<XInteractionHandler> xInteraction_)214 void setHandler( Reference< XInteractionHandler > xInteraction_ )
215 {
216 mxInteraction = xInteraction_;
217 }
218
219 // Methods
220 virtual Reference< XInteractionHandler > SAL_CALL getInteractionHandler();
221 virtual Reference< XProgressHandler > SAL_CALL getProgressHandler();
222 };
223
getInteractionHandler()224 Reference< XInteractionHandler > OCommandEnvironment::getInteractionHandler()
225 {
226 return mxInteraction;
227 }
228
getProgressHandler()229 Reference< XProgressHandler > OCommandEnvironment::getProgressHandler()
230 {
231 Reference< XProgressHandler > xRet;
232 return xRet;
233 }
234
235 //===========================================================================
236
transferImpl(const rtl::OUString & rSource,const rtl::OUString & rDest,sal_Bool bMoveData)237 void OFileAccess::transferImpl( const rtl::OUString& rSource,
238 const rtl::OUString& rDest,
239 sal_Bool bMoveData )
240 {
241 // SfxContentHelper::Transfer_Impl
242 INetURLObject aSourceObj( rSource, INET_PROT_FILE );
243 INetURLObject aDestObj( rDest, INET_PROT_FILE );
244 String aName = aDestObj.getName(
245 INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
246 String aDestURL;
247 String aSourceURL = aSourceObj.GetMainURL( INetURLObject::NO_DECODE );
248 if ( aDestObj.removeSegment() )
249 {
250 // hierarchical URL.
251
252 aDestObj.setFinalSlash();
253 aDestURL = aDestObj.GetMainURL( INetURLObject::NO_DECODE );
254 }
255 else
256 {
257 // non-hierachical URL
258
259 // #i29648#
260 //
261 #if 0
262 // Note: A hierarchical UCB content implements interface XChild, which
263 // has a method getParent(). Unfortunately this does not always help
264 // here, because it is not guaranteed that a content object for a
265 // non-existing resource can be created. Thus, it will happen that an
266 // exception is thrown when trying to create a UCB content for the
267 // destination URL.
268
269 try
270 {
271 ucbhelper::Content aFullDest(
272 aDestObj.GetMainURL(
273 INetURLObject::NO_DECODE ), mxEnvironment );
274
275 Reference< XChild > xChild( aFullDest.get(), UNO_QUERY_THROW );
276 Reference< com::sun::star::ucb::XContent >
277 xParent( xChild->getParent(), UNO_QUERY_THROW );
278 ucbhelper::Content aParent( xParent, mxEnvironment );
279
280 aDestURL = aParent.getURL();
281
282 rtl::OUString aNameTmp;
283 aFullDest.getPropertyValue(
284 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ) )
285 >>= aNameTmp;
286 aName = aNameTmp;
287 }
288 catch ( Exception const & )
289 {
290 throw RuntimeException(
291 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
292 "OFileAccess::transferrImpl - Unable to "
293 "obtain destination folder URL!" ) ),
294 static_cast< cppu::OWeakObject * >( this ) );
295 }
296 #else
297 if ( aDestObj.GetProtocol() == INET_PROT_VND_SUN_STAR_EXPAND )
298 {
299 // Hack: Expand destination URL using Macro Expander and try again
300 // with the hopefully hierarchical expanded URL...
301
302 try
303 {
304 Reference< XMacroExpander > xExpander;
305
306 mxCtx->getValueByName(
307 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
308 "/singletons/com.sun.star.util.theMacroExpander" ) ) )
309 >>= xExpander;
310
311 OSL_ENSURE( xExpander.is(),
312 "Unable to obtain macro expander singleton!" );
313
314 aDestURL = xExpander->expandMacros(
315 aDestObj.GetURLPath( INetURLObject::DECODE_WITH_CHARSET ) );
316 }
317 catch ( Exception const & )
318 {
319 throw RuntimeException(
320 rtl::OUString(
321 RTL_CONSTASCII_USTRINGPARAM(
322 "OFileAccess::transferrImpl - Unable to obtain "
323 "destination folder URL!" ) ),
324 static_cast< cppu::OWeakObject * >( this ) );
325 }
326
327 transferImpl( rSource, aDestURL, bMoveData );
328 return;
329 }
330
331 throw RuntimeException(
332 rtl::OUString(
333 RTL_CONSTASCII_USTRINGPARAM(
334 "OFileAccess::transferrImpl - Unable to obtain "
335 "destination folder URL!" ) ),
336 static_cast< cppu::OWeakObject * >( this ) );
337 #endif
338 }
339
340 ucbhelper::Content aDestPath( aDestURL, mxEnvironment );
341 ucbhelper::Content aSrc ( aSourceURL, mxEnvironment );
342
343 try
344 {
345 aDestPath.transferContent( aSrc,
346 bMoveData
347 ? ucbhelper::InsertOperation_MOVE
348 : ucbhelper::InsertOperation_COPY,
349 aName,
350 ::com::sun::star::ucb::NameClash::OVERWRITE );
351 }
352 catch ( ::com::sun::star::ucb::CommandFailedException const & )
353 {
354 // Interaction Handler already handled the error that has occurred...
355 }
356 }
357
copy(const rtl::OUString & SourceURL,const rtl::OUString & DestURL)358 void OFileAccess::copy( const rtl::OUString& SourceURL, const rtl::OUString& DestURL )
359 {
360 transferImpl( SourceURL, DestURL, sal_False );
361 }
362
move(const rtl::OUString & SourceURL,const rtl::OUString & DestURL)363 void OFileAccess::move( const rtl::OUString& SourceURL, const rtl::OUString& DestURL )
364 {
365 transferImpl( SourceURL, DestURL, sal_True );
366 }
367
kill(const rtl::OUString & FileURL)368 void OFileAccess::kill( const rtl::OUString& FileURL )
369 {
370 // SfxContentHelper::Kill
371 INetURLObject aDeleteObj( FileURL, INET_PROT_FILE );
372 ucbhelper::Content aCnt( aDeleteObj.GetMainURL( INetURLObject::NO_DECODE ), mxEnvironment );
373 try
374 {
375 aCnt.executeCommand( rtl::OUString::createFromAscii( "delete" ), makeAny( sal_Bool( sal_True ) ) );
376 }
377 catch ( ::com::sun::star::ucb::CommandFailedException const & )
378 {
379 // Interaction Handler already handled the error that has occurred...
380 }
381 }
382
isFolder(const rtl::OUString & FileURL)383 sal_Bool OFileAccess::isFolder( const rtl::OUString& FileURL )
384 {
385 sal_Bool bRet = sal_False;
386 try
387 {
388 INetURLObject aURLObj( FileURL, INET_PROT_FILE );
389 ucbhelper::Content aCnt( aURLObj.GetMainURL( INetURLObject::NO_DECODE ), mxEnvironment );
390 bRet = aCnt.isFolder();
391 }
392 catch (Exception &) {}
393 return bRet;
394 }
395
isReadOnly(const rtl::OUString & FileURL)396 sal_Bool OFileAccess::isReadOnly( const rtl::OUString& FileURL )
397 {
398 INetURLObject aURLObj( FileURL, INET_PROT_FILE );
399 ucbhelper::Content aCnt( aURLObj.GetMainURL( INetURLObject::NO_DECODE ), mxEnvironment );
400 Any aRetAny = aCnt.getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsReadOnly" ) ) );
401 sal_Bool bRet = sal_False;
402 aRetAny >>= bRet;
403 return bRet;
404 }
405
setReadOnly(const rtl::OUString & FileURL,sal_Bool bReadOnly)406 void OFileAccess::setReadOnly( const rtl::OUString& FileURL, sal_Bool bReadOnly )
407 {
408 INetURLObject aURLObj( FileURL, INET_PROT_FILE );
409 ucbhelper::Content aCnt( aURLObj.GetMainURL( INetURLObject::NO_DECODE ), mxEnvironment );
410 Any aAny;
411 aAny <<= bReadOnly;
412 aCnt.setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsReadOnly" ) ), aAny );
413 }
414
createFolder(const rtl::OUString & NewFolderURL)415 void OFileAccess::createFolder( const rtl::OUString& NewFolderURL )
416 {
417 // Does the folder already exist?
418 if( !NewFolderURL.getLength() || isFolder( NewFolderURL ) )
419 return;
420
421 // SfxContentHelper::MakeFolder
422 INetURLObject aURL( NewFolderURL, INET_PROT_FILE );
423 String aNewFolderURLStr = aURL.GetMainURL( INetURLObject::NO_DECODE );
424 String aTitle = aURL.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
425 if ( aTitle.Len() )
426 {
427 aURL.removeSegment();
428
429 // Does the base folder exist? Otherwise create it first
430 String aBaseFolderURLStr = aURL.GetMainURL( INetURLObject::NO_DECODE );
431 if( !isFolder( aBaseFolderURLStr ) )
432 {
433 createFolder( aBaseFolderURLStr );
434 }
435 }
436
437 ucbhelper::Content aCnt( aURL.GetMainURL( INetURLObject::NO_DECODE ), mxEnvironment );
438
439 Sequence< ContentInfo > aInfo = aCnt.queryCreatableContentsInfo();
440 sal_Int32 nCount = aInfo.getLength();
441 if ( nCount == 0 )
442 return;
443
444 for ( sal_Int32 i = 0; i < nCount; ++i )
445 {
446 // Simply look for the first KIND_FOLDER...
447 const ContentInfo & rCurr = aInfo[i];
448 if ( rCurr.Attributes & ContentInfoAttribute::KIND_FOLDER )
449 {
450 // Make sure the only required bootstrap property is "Title",
451 const Sequence< Property > & rProps = rCurr.Properties;
452 if ( rProps.getLength() != 1 )
453 continue;
454
455 if ( !rProps[ 0 ].Name.equalsAsciiL(
456 RTL_CONSTASCII_STRINGPARAM( "Title" ) ) )
457 continue;
458
459 Sequence<rtl::OUString> aNames(1);
460 rtl::OUString* pNames = aNames.getArray();
461 pNames[0] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) );
462 Sequence< Any > aValues(1);
463 Any* pValues = aValues.getArray();
464 pValues[0] = makeAny( rtl::OUString( aTitle ) );
465
466 ucbhelper::Content aNew;
467 try
468 {
469 if ( !aCnt.insertNewContent( rCurr.Type, aNames, aValues, aNew ) )
470 continue;
471
472 // Success. We're done.
473 return;
474 }
475 catch ( ::com::sun::star::ucb::CommandFailedException const & )
476 {
477 // Interaction Handler already handled the error that has occurred...
478 continue;
479 }
480 }
481 }
482 }
483
getSize(const rtl::OUString & FileURL)484 sal_Int32 OFileAccess::getSize( const rtl::OUString& FileURL )
485 {
486 // SfxContentHelper::GetSize
487 sal_Int32 nSize = 0;
488 sal_Int64 nTemp = 0;
489 INetURLObject aObj( FileURL, INET_PROT_FILE );
490 ucbhelper::Content aCnt( aObj.GetMainURL( INetURLObject::NO_DECODE ), mxEnvironment );
491 aCnt.getPropertyValue( rtl::OUString::createFromAscii( "Size" ) ) >>= nTemp;
492 nSize = (sal_Int32)nTemp;
493 return nSize;
494 }
495
getContentType(const rtl::OUString & FileURL)496 rtl::OUString OFileAccess::getContentType( const rtl::OUString& FileURL )
497 {
498 INetURLObject aObj( FileURL, INET_PROT_FILE );
499 ucbhelper::Content aCnt( aObj.GetMainURL( INetURLObject::NO_DECODE ), mxEnvironment );
500
501 Reference< XContent > xContent = aCnt.get();
502 rtl::OUString aTypeStr = xContent->getContentType();
503 return aTypeStr;
504 }
505
getDateTimeModified(const rtl::OUString & FileURL)506 DateTime OFileAccess::getDateTimeModified( const rtl::OUString& FileURL )
507 {
508 INetURLObject aFileObj( FileURL, INET_PROT_FILE );
509 DateTime aDateTime;
510
511 Reference< XCommandEnvironment > aCmdEnv;
512 ucbhelper::Content aYoung( aFileObj.GetMainURL( INetURLObject::NO_DECODE ), aCmdEnv );
513 aYoung.getPropertyValue( rtl::OUString::createFromAscii( "DateModified" ) ) >>= aDateTime;
514 return aDateTime;
515 }
516
517
DECLARE_LIST(StringList_Impl,rtl::OUString *)518 DECLARE_LIST( StringList_Impl, rtl::OUString* )
519
520 Sequence< rtl::OUString > OFileAccess::getFolderContents( const rtl::OUString& FolderURL, sal_Bool bIncludeFolders )
521 {
522 // SfxContentHelper::GetFolderContents
523
524 StringList_Impl* pFiles = NULL;
525 INetURLObject aFolderObj( FolderURL, INET_PROT_FILE );
526
527 ucbhelper::Content aCnt( aFolderObj.GetMainURL( INetURLObject::NO_DECODE ), mxEnvironment );
528 Reference< XResultSet > xResultSet;
529 Sequence< rtl::OUString > aProps(0);
530 //Sequence< rtl::OUString > aProps(1);
531 //rtl::OUString* pProps = aProps.getArray();
532 //pProps[0] == rtl::OUString::createFromAscii( "Url" );
533
534 ucbhelper::ResultSetInclude eInclude = bIncludeFolders ? ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS : ucbhelper::INCLUDE_DOCUMENTS_ONLY;
535
536 try
537 {
538 xResultSet = aCnt.createCursor( aProps, eInclude );
539 }
540 catch ( ::com::sun::star::ucb::CommandFailedException const & )
541 {
542 // Interaction Handler already handled the error that has occurred...
543 }
544
545 if ( xResultSet.is() )
546 {
547 pFiles = new StringList_Impl;
548 Reference< com::sun::star::ucb::XContentAccess > xContentAccess( xResultSet, UNO_QUERY );
549
550 while ( xResultSet->next() )
551 {
552 rtl::OUString aId = xContentAccess->queryContentIdentifierString();
553 INetURLObject aURL( aId, INET_PROT_FILE );
554 rtl::OUString* pFile = new rtl::OUString( aURL.GetMainURL( INetURLObject::NO_DECODE ) );
555 pFiles->Insert( pFile, LIST_APPEND );
556 }
557 }
558
559 if ( pFiles )
560 {
561 sal_uIntPtr nCount = pFiles->Count();
562 Sequence < rtl::OUString > aRet( nCount );
563 rtl::OUString* pRet = aRet.getArray();
564 for ( sal_uInt16 i = 0; i < nCount; ++i )
565 {
566 rtl::OUString* pFile = pFiles->GetObject(i);
567 pRet[i] = *( pFile );
568 delete pFile;
569 }
570 delete pFiles;
571 return aRet;
572 }
573 else
574 return Sequence < rtl::OUString > ();
575 }
576
exists(const rtl::OUString & FileURL)577 sal_Bool OFileAccess::exists( const rtl::OUString& FileURL )
578 {
579 sal_Bool bRet = sal_False;
580 try
581 {
582 bRet = isFolder( FileURL );
583 if( !bRet )
584 {
585 Reference< XInputStream > xStream = openFileRead( FileURL );
586 bRet = xStream.is();
587 if( bRet )
588 xStream->closeInput();
589 }
590 }
591 catch (Exception &) {}
592 return bRet;
593 }
594
openFileRead(const rtl::OUString & FileURL)595 Reference< XInputStream > OFileAccess::openFileRead( const rtl::OUString& FileURL )
596 {
597 Reference< XInputStream > xRet;
598 INetURLObject aObj( FileURL, INET_PROT_FILE );
599 ucbhelper::Content aCnt( aObj.GetMainURL( INetURLObject::NO_DECODE ), mxEnvironment );
600
601 Reference< XActiveDataSink > xSink = (XActiveDataSink*)(new OActiveDataSink());
602
603 try
604 {
605 sal_Bool bRet = aCnt.openStream( xSink );
606 if( bRet )
607 xRet = xSink->getInputStream();
608 }
609 catch ( ::com::sun::star::ucb::CommandFailedException const & )
610 {
611 // Interaction Handler already handled the error that has occurred...
612 }
613
614 return xRet;
615 }
616
openFileWrite(const rtl::OUString & FileURL)617 Reference< XOutputStream > OFileAccess::openFileWrite( const rtl::OUString& FileURL )
618 {
619 Reference< XOutputStream > xRet;
620 Reference< XStream > xStream = OFileAccess::openFileReadWrite( FileURL );
621 if( xStream.is() )
622 xRet = xStream->getOutputStream();
623 return xRet;
624 }
625
openFileReadWrite(const rtl::OUString & FileURL)626 Reference< XStream > OFileAccess::openFileReadWrite( const rtl::OUString& FileURL )
627 {
628 Reference< XActiveDataStreamer > xSink = (XActiveDataStreamer*)new OActiveDataStreamer();
629 Reference< XInterface > xSinkIface = Reference< XInterface >::query( xSink );
630
631 OpenCommandArgument2 aArg;
632 aArg.Mode = OpenMode::DOCUMENT;
633 aArg.Priority = 0; // unused
634 aArg.Sink = xSink;
635 aArg.Properties = Sequence< Property >( 0 ); // unused
636
637 Any aCmdArg;
638 aCmdArg <<= aArg;
639
640 INetURLObject aFileObj( FileURL, INET_PROT_FILE );
641 ucbhelper::Content aCnt( aFileObj.GetMainURL( INetURLObject::NO_DECODE ), mxEnvironment );
642
643 // Be silent...
644 Reference< XInteractionHandler > xIH;
645 if ( mpEnvironment )
646 {
647 xIH = mpEnvironment->getInteractionHandler();
648 mpEnvironment->setHandler( 0 );
649 }
650
651 try
652 {
653 aCnt.executeCommand( rtl::OUString::createFromAscii( "open" ), aCmdArg );
654 }
655 catch ( InteractiveIOException const & e )
656 {
657 if ( xIH.is() )
658 mpEnvironment->setHandler( xIH );
659
660 if ( e.Code == IOErrorCode_NOT_EXISTING )
661 {
662 // Create file...
663 SvMemoryStream aStream(0,0);
664 ::utl::OInputStreamWrapper* pInput = new ::utl::OInputStreamWrapper( aStream );
665 Reference< XInputStream > xInput( pInput );
666 InsertCommandArgument aInsertArg;
667 aInsertArg.Data = xInput;
668 aInsertArg.ReplaceExisting = sal_False;
669
670 aCmdArg <<= aInsertArg;
671 aCnt.executeCommand( rtl::OUString::createFromAscii( "insert" ), aCmdArg );
672
673 // Retry...
674 return openFileReadWrite( FileURL );
675 }
676
677 throw;
678 }
679
680 if ( xIH.is() )
681 mpEnvironment->setHandler( xIH );
682
683 Reference< XStream > xRet = xSink->getStream();
684 return xRet;
685 }
686
setInteractionHandler(const Reference<XInteractionHandler> & Handler)687 void OFileAccess::setInteractionHandler( const Reference< XInteractionHandler >& Handler )
688 {
689 if( !mpEnvironment )
690 {
691 mpEnvironment = new OCommandEnvironment();
692 mxEnvironment = (XCommandEnvironment*)mpEnvironment;
693 }
694 mpEnvironment->setHandler( Handler );
695 }
696
createNewFile(const rtl::OUString & rParentURL,const rtl::OUString & rTitle,const Reference<XInputStream> & data)697 bool OFileAccess::createNewFile( const rtl::OUString & rParentURL,
698 const rtl::OUString & rTitle,
699 const Reference< XInputStream >& data )
700 {
701 ucbhelper::Content aParentCnt( rParentURL, mxEnvironment );
702
703 Sequence< ContentInfo > aInfo = aParentCnt.queryCreatableContentsInfo();
704 sal_Int32 nCount = aInfo.getLength();
705 if ( nCount == 0 )
706 return false;
707
708 for ( sal_Int32 i = 0; i < nCount; ++i )
709 {
710 const ContentInfo & rCurr = aInfo[i];
711 if ( ( rCurr.Attributes
712 & ContentInfoAttribute::KIND_DOCUMENT ) &&
713 ( rCurr.Attributes
714 & ContentInfoAttribute::INSERT_WITH_INPUTSTREAM ) )
715 {
716 // Make sure the only required bootstrap property is
717 // "Title",
718 const Sequence< Property > & rProps = rCurr.Properties;
719 if ( rProps.getLength() != 1 )
720 continue;
721
722 if ( !rProps[ 0 ].Name.equalsAsciiL(
723 RTL_CONSTASCII_STRINGPARAM( "Title" ) ) )
724 continue;
725
726 Sequence<rtl::OUString> aNames(1);
727 rtl::OUString* pNames = aNames.getArray();
728 pNames[0] = rtl::OUString(
729 RTL_CONSTASCII_USTRINGPARAM( "Title" ) );
730 Sequence< Any > aValues(1);
731 Any* pValues = aValues.getArray();
732 pValues[0] = makeAny( rtl::OUString( rTitle ) );
733
734 try
735 {
736 ucbhelper::Content aNew;
737 if ( aParentCnt.insertNewContent(
738 rCurr.Type, aNames, aValues, data, aNew ) )
739 return true; // success.
740 else
741 continue;
742 }
743 catch ( CommandFailedException const & )
744 {
745 // Interaction Handler already handled the
746 // error that has occurred...
747 continue;
748 }
749 }
750 }
751
752 return false;
753 }
754
writeFile(const rtl::OUString & FileURL,const Reference<XInputStream> & data)755 void SAL_CALL OFileAccess::writeFile( const rtl::OUString& FileURL,
756 const Reference< XInputStream >& data )
757 {
758 INetURLObject aURL( FileURL, INET_PROT_FILE );
759 try
760 {
761 ucbhelper::Content aCnt(
762 aURL.GetMainURL( INetURLObject::NO_DECODE ), mxEnvironment );
763
764 try
765 {
766 aCnt.writeStream( data, sal_True /* bReplaceExisting */ );
767 }
768 catch ( CommandFailedException const & )
769 {
770 // Interaction Handler already handled the error that has occurred...
771 }
772 }
773 catch ( ContentCreationException const & e )
774 {
775 // Most probably file does not exist. Try to create.
776 if ( e.eError == ContentCreationError_CONTENT_CREATION_FAILED )
777 {
778 INetURLObject aParentURLObj( aURL );
779 if ( aParentURLObj.removeSegment() )
780 {
781 String aParentURL
782 = aParentURLObj.GetMainURL( INetURLObject::NO_DECODE );
783
784 // ensure all parent folders exist.
785 createFolder( aParentURL );
786
787 // create the new file...
788 String aTitle
789 = aURL.getName( INetURLObject::LAST_SEGMENT,
790 true,
791 INetURLObject::DECODE_WITH_CHARSET );
792 if ( createNewFile( aParentURL, aTitle, data ) )
793 {
794 // success
795 return;
796 }
797 }
798 }
799
800 throw;
801 }
802 }
803
isHidden(const::rtl::OUString & FileURL)804 sal_Bool OFileAccess::isHidden( const ::rtl::OUString& FileURL )
805 {
806 INetURLObject aURLObj( FileURL, INET_PROT_FILE );
807 ucbhelper::Content aCnt( aURLObj.GetMainURL( INetURLObject::NO_DECODE ), mxEnvironment );
808 Any aRetAny = aCnt.getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsHidden" ) ) );
809 sal_Bool bRet = sal_False;
810 aRetAny >>= bRet;
811 return bRet;
812 }
813
setHidden(const::rtl::OUString & FileURL,sal_Bool bHidden)814 void OFileAccess::setHidden( const ::rtl::OUString& FileURL, sal_Bool bHidden )
815 {
816 INetURLObject aURLObj( FileURL, INET_PROT_FILE );
817 ucbhelper::Content aCnt( aURLObj.GetMainURL( INetURLObject::NO_DECODE ), mxEnvironment );
818 Any aAny;
819 aAny <<= bHidden;
820 aCnt.setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsHidden" ) ), aAny );
821 }
822
823 //==================================================================================================
824 //==================================================================================================
825 //==================================================================================================
826
FileAccess_CreateInstance(const Reference<XComponentContext> & xCtx)827 Reference< XInterface > SAL_CALL FileAccess_CreateInstance( const Reference< XComponentContext > & xCtx )
828 {
829 return Reference < XInterface >( ( cppu::OWeakObject * ) new OFileAccess( xCtx ) );
830 }
831
FileAccess_getImplementationName()832 rtl::OUString FileAccess_getImplementationName()
833 {
834 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.ucb.SimpleFileAccess" ) );
835 }
836
FileAccess_getSupportedServiceNames()837 Sequence< rtl::OUString > FileAccess_getSupportedServiceNames()
838 {
839 static Sequence < rtl::OUString > *pNames = 0;
840 if( ! pNames )
841 {
842 osl::MutexGuard guard( osl::Mutex::getGlobalMutex() );
843 if( !pNames )
844 {
845 static Sequence< rtl::OUString > seqNames(1);
846 seqNames.getArray()[0] = rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" );
847 pNames = &seqNames;
848 }
849 }
850 return *pNames;
851 }
852
853 struct ::cppu::ImplementationEntry g_component_entries [] =
854 {
855 {
856 FileAccess_CreateInstance,
857 FileAccess_getImplementationName,
858 FileAccess_getSupportedServiceNames,
859 ::cppu::createSingleComponentFactory,
860 0,
861 0
862 },
863 { 0, 0, 0, 0, 0, 0 }
864 };
865
866 }
867
868 //==================================================================================================
869 // Component exports
870
871 extern "C"
872 {
873 //==================================================================================================
component_getImplementationEnvironment(const sal_Char ** ppEnvTypeName,uno_Environment **)874 FILEACCESS_DLLPUBLIC void SAL_CALL component_getImplementationEnvironment(
875 const sal_Char ** ppEnvTypeName, uno_Environment ** /*ppEnv*/ )
876 {
877 *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
878 }
879 //==================================================================================================
component_getFactory(const sal_Char * pImplName,void * pServiceManager,void * pRegistryKey)880 FILEACCESS_DLLPUBLIC void * SAL_CALL component_getFactory(
881 const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
882 {
883 return ::cppu::component_getFactoryHelper( pImplName, pServiceManager, pRegistryKey, ::io_FileAccess::g_component_entries );
884 }
885 }
886