1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
22 #include <sys/types.h>
23 #include <sal/macros.h>
26 #include <osl/diagnose.h>
27 #include <osl/doublecheckedlocking.h>
29 #include <com/sun/star/beans/PropertyValue.hpp>
30 #include <com/sun/star/beans/PropertyAttribute.hpp>
31 #include <com/sun/star/beans/PropertySetInfoChange.hpp>
32 #include <com/sun/star/beans/PropertySetInfoChangeEvent.hpp>
33 #include <com/sun/star/io/XActiveDataSink.hpp>
34 #include <com/sun/star/io/XOutputStream.hpp>
35 #include <com/sun/star/lang/IllegalAccessException.hpp>
36 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
37 #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
38 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
39 #include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp>
40 #include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
41 #include <com/sun/star/ucb/InteractiveNetworkWriteException.hpp>
42 #include <com/sun/star/ucb/InteractiveNetworkConnectException.hpp>
43 #include <com/sun/star/ucb/InteractiveNetworkGeneralException.hpp>
44 #include <com/sun/star/ucb/InteractiveNetworkReadException.hpp>
45 #include <com/sun/star/ucb/InteractiveNetworkResolveNameException.hpp>
46 #include <com/sun/star/ucb/NameClash.hpp>
47 #include <com/sun/star/ucb/NameClashException.hpp>
48 #include <com/sun/star/ucb/OpenMode.hpp>
49 #include <com/sun/star/ucb/PostCommandArgument2.hpp>
50 #include <com/sun/star/ucb/XCommandInfo.hpp>
51 #include <com/sun/star/ucb/XPersistentPropertySet.hpp>
52 #include <com/sun/star/ucb/MissingInputStreamException.hpp>
53 #include <com/sun/star/ucb/MissingPropertiesException.hpp>
54 #include <com/sun/star/ucb/UnsupportedCommandException.hpp>
55 #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
56 #include <com/sun/star/ucb/UnsupportedNameClashException.hpp>
57 #include <com/sun/star/ucb/UnsupportedOpenModeException.hpp>
58 #include <com/sun/star/ucb/XDynamicResultSet.hpp>
59 #include <com/sun/star/ucb/XContentCreator.hpp>
61 #include <comphelper/processfactory.hxx>
62 #include <comphelper/seekableinput.hxx>
63 #include <cppuhelper/exc_hlp.hxx>
64 #include <ucbhelper/contentidentifier.hxx>
65 #include <ucbhelper/propertyvalueset.hxx>
66 #include <ucbhelper/interactionrequest.hxx>
67 #include <ucbhelper/cancelcommandexecution.hxx>
68 #include <vcl/svapp.hxx>
70 #include <osl/conditn.hxx>
72 #include "gio_content.hxx"
73 #include "gio_provider.hxx"
74 #include "gio_resultset.hxx"
75 #include "gio_inputstream.hxx"
76 #include "gio_outputstream.hxx"
77 #include "gio_mount.hxx"
81 using namespace com::sun::star
;
87 const uno::Reference
< uno::XComponentContext
>& rxContext
,
88 ContentProvider
* pProvider
,
89 const uno::Reference
< ucb::XContentIdentifier
>& Identifier
)
90 throw ( ucb::ContentCreationException
)
91 : ContentImplHelper( rxContext
, pProvider
, Identifier
),
92 m_pProvider( pProvider
), mpFile (NULL
), mpInfo( NULL
), mbTransient(false)
94 SAL_INFO("ucb.ucp.gio", "New Content ('" << m_xIdentifier
->getContentIdentifier() << "')\n");
98 const uno::Reference
< uno::XComponentContext
>& rxContext
,
99 ContentProvider
* pProvider
,
100 const uno::Reference
< ucb::XContentIdentifier
>& Identifier
,
102 throw ( ucb::ContentCreationException
)
103 : ContentImplHelper( rxContext
, pProvider
, Identifier
),
104 m_pProvider( pProvider
), mpFile (NULL
), mpInfo( NULL
), mbTransient(true)
106 SAL_INFO("ucb.ucp.gio", "Create Content ('" << m_xIdentifier
->getContentIdentifier() << "')\n");
107 mpInfo
= g_file_info_new();
108 g_file_info_set_file_type(mpInfo
, bIsFolder
? G_FILE_TYPE_DIRECTORY
: G_FILE_TYPE_REGULAR
);
113 if (mpInfo
) g_object_unref(mpInfo
);
114 if (mpFile
) g_object_unref(mpFile
);
117 OUString
Content::getParentURL()
120 if (GFile
* pFile
= g_file_get_parent(getGFile()))
122 char* pPath
= g_file_get_uri(pFile
);
123 g_object_unref(pFile
);
124 sURL
= OUString::createFromAscii(pPath
);
130 void SAL_CALL
Content::abort( sal_Int32
/*CommandId*/ )
131 throw( uno::RuntimeException
, std::exception
)
134 //stick a map from each CommandId to a new GCancellable and propagate
135 //it throughout the g_file_* calls
138 OUString SAL_CALL
Content::getContentType() throw( uno::RuntimeException
, std::exception
)
140 return isFolder(uno::Reference
< ucb::XCommandEnvironment
>())
141 ? OUString( GIO_FOLDER_TYPE
)
142 : OUString( GIO_FILE_TYPE
);
145 #define EXCEPT(aExcept) \
147 if (bThrow) throw aExcept;\
148 aRet = uno::makeAny( aExcept );\
151 uno::Any
convertToException(GError
*pError
, const uno::Reference
< uno::XInterface
>& rContext
, bool bThrow
)
155 gint eCode
= pError
->code
;
156 OUString
sMessage(pError
->message
, strlen(pError
->message
), RTL_TEXTENCODING_UTF8
);
157 g_error_free(pError
);
162 uno::Sequence
< uno::Any
> aArgs( 1 );
163 aArgs
[ 0 ] <<= sName
;
167 case G_IO_ERROR_FAILED
:
168 { io::IOException
aExcept(sMessage
, rContext
);
171 case G_IO_ERROR_NOT_MOUNTED
:
172 { ucb::InteractiveAugmentedIOException
aExcept(sMessage
, rContext
,
173 task::InteractionClassification_ERROR
, ucb::IOErrorCode_NOT_EXISTING_PATH
, aArgs
);
176 case G_IO_ERROR_NOT_FOUND
:
177 { ucb::InteractiveAugmentedIOException
aExcept(sMessage
, rContext
,
178 task::InteractionClassification_ERROR
, ucb::IOErrorCode_NOT_EXISTING
, aArgs
);
181 case G_IO_ERROR_EXISTS
:
182 { ucb::NameClashException
aExcept(sMessage
, rContext
,
183 task::InteractionClassification_ERROR
, sName
);
186 case G_IO_ERROR_INVALID_ARGUMENT
:
187 { lang::IllegalArgumentException
aExcept(sMessage
, rContext
, -1 );
190 case G_IO_ERROR_PERMISSION_DENIED
:
191 { ucb::InteractiveAugmentedIOException
aExcept(sMessage
, rContext
,
192 task::InteractionClassification_ERROR
, ucb::IOErrorCode_ACCESS_DENIED
, aArgs
);
195 case G_IO_ERROR_IS_DIRECTORY
:
196 { ucb::InteractiveAugmentedIOException
aExcept(sMessage
, rContext
,
197 task::InteractionClassification_ERROR
, ucb::IOErrorCode_NO_FILE
, aArgs
);
200 case G_IO_ERROR_NOT_REGULAR_FILE
:
201 { ucb::InteractiveAugmentedIOException
aExcept(sMessage
, rContext
,
202 task::InteractionClassification_ERROR
, ucb::IOErrorCode_NO_FILE
, aArgs
);
205 case G_IO_ERROR_NOT_DIRECTORY
:
206 { ucb::InteractiveAugmentedIOException
aExcept(sMessage
, rContext
,
207 task::InteractionClassification_ERROR
, ucb::IOErrorCode_NO_DIRECTORY
, aArgs
);
210 case G_IO_ERROR_FILENAME_TOO_LONG
:
211 { ucb::InteractiveAugmentedIOException
aExcept(sMessage
, rContext
,
212 task::InteractionClassification_ERROR
, ucb::IOErrorCode_NAME_TOO_LONG
, aArgs
);
215 case G_IO_ERROR_PENDING
:
216 { ucb::InteractiveAugmentedIOException
aExcept(sMessage
, rContext
,
217 task::InteractionClassification_ERROR
, ucb::IOErrorCode_PENDING
, aArgs
);
220 case G_IO_ERROR_CLOSED
:
221 case G_IO_ERROR_CANCELLED
:
222 case G_IO_ERROR_TOO_MANY_LINKS
:
223 case G_IO_ERROR_WRONG_ETAG
:
224 { ucb::InteractiveAugmentedIOException
aExcept(sMessage
, rContext
,
225 task::InteractionClassification_ERROR
, ucb::IOErrorCode_GENERAL
, aArgs
);
228 case G_IO_ERROR_NOT_SUPPORTED
:
229 case G_IO_ERROR_CANT_CREATE_BACKUP
:
230 case G_IO_ERROR_WOULD_MERGE
:
231 { ucb::InteractiveAugmentedIOException
aExcept(sMessage
, rContext
,
232 task::InteractionClassification_ERROR
, ucb::IOErrorCode_NOT_SUPPORTED
, aArgs
);
235 case G_IO_ERROR_NO_SPACE
:
236 { ucb::InteractiveAugmentedIOException
aExcept(sMessage
, rContext
,
237 task::InteractionClassification_ERROR
, ucb::IOErrorCode_OUT_OF_DISK_SPACE
, aArgs
);
240 case G_IO_ERROR_INVALID_FILENAME
:
241 { ucb::InteractiveAugmentedIOException
aExcept(sMessage
, rContext
,
242 task::InteractionClassification_ERROR
, ucb::IOErrorCode_INVALID_CHARACTER
, aArgs
);
245 case G_IO_ERROR_READ_ONLY
:
246 { ucb::InteractiveAugmentedIOException
aExcept(sMessage
, rContext
,
247 task::InteractionClassification_ERROR
, ucb::IOErrorCode_WRITE_PROTECTED
, aArgs
);
250 case G_IO_ERROR_TIMED_OUT
:
251 { ucb::InteractiveAugmentedIOException
aExcept(sMessage
, rContext
,
252 task::InteractionClassification_ERROR
, ucb::IOErrorCode_DEVICE_NOT_READY
, aArgs
);
255 case G_IO_ERROR_WOULD_RECURSE
:
256 { ucb::InteractiveAugmentedIOException
aExcept(sMessage
, rContext
,
257 task::InteractionClassification_ERROR
, ucb::IOErrorCode_RECURSIVE
, aArgs
);
260 case G_IO_ERROR_BUSY
:
261 case G_IO_ERROR_WOULD_BLOCK
:
262 { ucb::InteractiveAugmentedIOException
aExcept(sMessage
, rContext
,
263 task::InteractionClassification_ERROR
, ucb::IOErrorCode_LOCKING_VIOLATION
, aArgs
);
266 case G_IO_ERROR_HOST_NOT_FOUND
:
267 { ucb::InteractiveNetworkResolveNameException
aExcept(sMessage
, rContext
,
268 task::InteractionClassification_ERROR
, sHost
);
272 case G_IO_ERROR_ALREADY_MOUNTED
:
273 case G_IO_ERROR_NOT_EMPTY
:
274 case G_IO_ERROR_NOT_SYMBOLIC_LINK
:
275 case G_IO_ERROR_NOT_MOUNTABLE_FILE
:
276 case G_IO_ERROR_FAILED_HANDLED
:
277 { ucb::InteractiveNetworkGeneralException
aExcept(sMessage
, rContext
,
278 task::InteractionClassification_ERROR
);
285 void convertToIOException(GError
*pError
, const uno::Reference
< uno::XInterface
>& rContext
)
286 throw( io::IOException
, uno::RuntimeException
, std::exception
)
290 convertToException(pError
, rContext
);
292 catch (const io::IOException
&)
296 catch (const uno::RuntimeException
&)
300 catch (const uno::Exception
& e
)
302 css::uno::Any
a(cppu::getCaughtException());
303 throw css::lang::WrappedTargetRuntimeException(
304 "wrapped Exception " + e
.Message
,
305 css::uno::Reference
<css::uno::XInterface
>(), a
);
309 uno::Any
Content::mapGIOError( GError
*pError
)
312 return getBadArgExcept();
314 return convertToException(pError
, static_cast< cppu::OWeakObject
* >(this), false);
317 uno::Any
Content::getBadArgExcept()
319 return uno::makeAny( lang::IllegalArgumentException(
320 OUString("Wrong argument type!"),
321 static_cast< cppu::OWeakObject
* >( this ), -1) );
327 GMountOperation
*mpAuthentication
;
329 static void Completed(GObject
*source
, GAsyncResult
*res
, gpointer user_data
);
331 MountOperation(const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
);
333 GError
*Mount(GFile
*pFile
);
336 MountOperation::MountOperation(const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
) : mpError(NULL
)
338 mpLoop
= g_main_loop_new(NULL
, FALSE
);
339 mpAuthentication
= ooo_mount_operation_new(xEnv
);
342 void MountOperation::Completed(GObject
*source
, GAsyncResult
*res
, gpointer user_data
)
344 MountOperation
*pThis
= static_cast<MountOperation
*>(user_data
);
345 g_file_mount_enclosing_volume_finish(G_FILE(source
), res
, &(pThis
->mpError
));
346 g_main_loop_quit(pThis
->mpLoop
);
349 GError
*MountOperation::Mount(GFile
*pFile
)
351 g_file_mount_enclosing_volume(pFile
, G_MOUNT_MOUNT_NONE
, mpAuthentication
, NULL
, MountOperation::Completed
, this);
353 //HACK: At least the gdk_threads_set_lock_functions(GdkThreadsEnter,
354 // GdkThreadsLeave) call in vcl/unx/gtk/app/gtkinst.cxx will lead to
355 // GdkThreadsLeave unlock the SolarMutex down to zero at the end of
356 // g_main_loop_run, so we need ~SolarMutexReleaser to raise it back to
357 // the original value again:
358 SolarMutexReleaser rel
;
359 g_main_loop_run(mpLoop
);
364 MountOperation::~MountOperation()
366 g_object_unref(mpAuthentication
);
367 g_main_loop_unref(mpLoop
);
370 GFileInfo
* Content::getGFileInfo(const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
, GError
**ppError
)
373 if (mpInfo
== 0 && !mbTransient
) {
374 for (bool retried
= false;; retried
= true) {
375 mpInfo
= g_file_query_info(
376 getGFile(), "*", G_FILE_QUERY_INFO_NONE
, 0, &err
);
381 if (err
->code
!= G_IO_ERROR_NOT_MOUNTED
|| retried
) {
386 "G_IO_ERROR_NOT_MOUNTED \"" << err
->message
387 << "\", trying to mount");
389 err
= MountOperation(xEnv
).Mount(getGFile());
397 } else if (err
!= 0) {
400 "ignoring GError \"" << err
->message
<< "\" for <"
401 << m_xIdentifier
->getContentIdentifier() << ">");
407 GFile
* Content::getGFile()
410 mpFile
= g_file_new_for_uri(OUStringToOString(m_xIdentifier
->getContentIdentifier(), RTL_TEXTENCODING_UTF8
).getStr());
414 bool Content::isFolder(const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
416 GFileInfo
*pInfo
= getGFileInfo(xEnv
);
417 return pInfo
&& (g_file_info_get_file_type(pInfo
) == G_FILE_TYPE_DIRECTORY
);
420 static util::DateTime
getDateFromUnix (time_t t
)
427 if ( osl_getDateTimeFromTimeValue( &tv
, &dt
) )
428 return util::DateTime( 0, dt
.Seconds
, dt
.Minutes
, dt
.Hours
,
429 dt
.Day
, dt
.Month
, dt
.Year
, false);
431 return util::DateTime();
434 uno::Reference
< sdbc::XRow
> Content::getPropertyValuesFromGFileInfo(GFileInfo
*pInfo
,
435 const uno::Reference
< uno::XComponentContext
>& rxContext
,
436 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
,
437 const uno::Sequence
< beans::Property
>& rProperties
)
439 rtl::Reference
< ::ucbhelper::PropertyValueSet
> xRow
= new ::ucbhelper::PropertyValueSet( rxContext
);
442 const beans::Property
* pProps
;
444 nProps
= rProperties
.getLength();
445 pProps
= rProperties
.getConstArray();
447 for( sal_Int32 n
= 0; n
< nProps
; ++n
)
449 const beans::Property
& rProp
= pProps
[ n
];
451 if ( rProp
.Name
== "IsDocument" )
453 if (pInfo
!= 0 && g_file_info_has_attribute(pInfo
, G_FILE_ATTRIBUTE_STANDARD_TYPE
))
454 xRow
->appendBoolean( rProp
, ( g_file_info_get_file_type( pInfo
) == G_FILE_TYPE_REGULAR
||
455 g_file_info_get_file_type( pInfo
) == G_FILE_TYPE_UNKNOWN
) );
457 xRow
->appendVoid( rProp
);
459 else if ( rProp
.Name
== "IsFolder" )
461 if (pInfo
!= 0 && g_file_info_has_attribute( pInfo
, G_FILE_ATTRIBUTE_STANDARD_TYPE
) )
462 xRow
->appendBoolean( rProp
, ( g_file_info_get_file_type( pInfo
) == G_FILE_TYPE_DIRECTORY
));
464 xRow
->appendVoid( rProp
);
466 else if ( rProp
.Name
== "Title" )
468 if (pInfo
!= 0 && g_file_info_has_attribute(pInfo
, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME
))
470 const char *pName
= g_file_info_get_display_name(pInfo
);
471 xRow
->appendString( rProp
, OUString(pName
, strlen(pName
), RTL_TEXTENCODING_UTF8
) );
474 xRow
->appendVoid(rProp
);
476 else if ( rProp
.Name
== "IsReadOnly" )
478 if (pInfo
!= 0 && g_file_info_has_attribute( pInfo
, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE
) )
479 xRow
->appendBoolean( rProp
, !g_file_info_get_attribute_boolean( pInfo
, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE
) );
481 xRow
->appendVoid( rProp
);
483 else if ( rProp
.Name
== "DateCreated" )
485 if (pInfo
!= 0 && g_file_info_has_attribute( pInfo
, G_FILE_ATTRIBUTE_TIME_CREATED
) )
486 xRow
->appendTimestamp( rProp
, getDateFromUnix(g_file_info_get_attribute_uint64(pInfo
, G_FILE_ATTRIBUTE_TIME_CREATED
)) );
488 xRow
->appendVoid( rProp
);
490 else if ( rProp
.Name
== "DateModified" )
492 if (pInfo
!= 0 && g_file_info_has_attribute( pInfo
, G_FILE_ATTRIBUTE_TIME_CHANGED
) )
493 xRow
->appendTimestamp( rProp
, getDateFromUnix(g_file_info_get_attribute_uint64(pInfo
, G_FILE_ATTRIBUTE_TIME_CHANGED
)) );
495 xRow
->appendVoid( rProp
);
497 else if ( rProp
.Name
== "Size" )
499 if (pInfo
!= 0 && g_file_info_has_attribute( pInfo
, G_FILE_ATTRIBUTE_STANDARD_SIZE
) )
500 xRow
->appendLong( rProp
, ( g_file_info_get_size( pInfo
) ));
502 xRow
->appendVoid( rProp
);
504 else if ( rProp
.Name
== "IsVolume" )
506 //What do we use this for ?
507 xRow
->appendBoolean( rProp
, false );
509 else if ( rProp
.Name
== "IsCompactDisc" )
511 if (pInfo
!= 0 && g_file_info_has_attribute( pInfo
, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_EJECT
) )
512 xRow
->appendBoolean( rProp
, g_file_info_get_attribute_boolean(pInfo
, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_EJECT
) );
514 xRow
->appendVoid( rProp
);
516 else if ( rProp
.Name
== "IsRemoveable" )
518 if (pInfo
!= 0 && g_file_info_has_attribute( pInfo
, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT
) )
519 xRow
->appendBoolean( rProp
, g_file_info_get_attribute_boolean(pInfo
, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT
) );
521 xRow
->appendVoid( rProp
);
523 else if ( rProp
.Name
== "IsFloppy" )
525 xRow
->appendBoolean( rProp
, false );
527 else if ( rProp
.Name
== "IsHidden" )
529 if (pInfo
!= 0 && g_file_info_has_attribute( pInfo
, G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN
) )
530 xRow
->appendBoolean( rProp
, ( g_file_info_get_is_hidden ( pInfo
) ) );
532 xRow
->appendVoid( rProp
);
534 else if ( rProp
.Name
== "CreatableContentsInfo" )
536 xRow
->appendObject( rProp
, uno::makeAny( queryCreatableContentsInfo( xEnv
) ) );
542 "Looking for unsupported property " << rProp
.Name
);
546 return uno::Reference
< sdbc::XRow
>( xRow
.get() );
549 uno::Reference
< sdbc::XRow
> Content::getPropertyValues(
550 const uno::Sequence
< beans::Property
>& rProperties
,
551 const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
553 GFileInfo
*pInfo
= getGFileInfo(xEnv
);
554 return getPropertyValuesFromGFileInfo(pInfo
, m_xContext
, xEnv
, rProperties
);
557 static lang::IllegalAccessException
558 getReadOnlyException( const uno::Reference
< uno::XInterface
>& rContext
)
560 return lang::IllegalAccessException ("Property is read-only!", rContext
);
563 void Content::queryChildren( ContentRefList
& rChildren
)
565 // Obtain a list with a snapshot of all currently instantiated contents
566 // from provider and extract the contents which are direct children
569 ucbhelper::ContentRefList aAllContents
;
570 m_xProvider
->queryExistingContents( aAllContents
);
572 OUString aURL
= m_xIdentifier
->getContentIdentifier();
573 sal_Int32 nURLPos
= aURL
.lastIndexOf( '/' );
575 if ( nURLPos
!= ( aURL
.getLength() - 1 ) )
578 sal_Int32 nLen
= aURL
.getLength();
580 ucbhelper::ContentRefList::const_iterator it
= aAllContents
.begin();
581 ucbhelper::ContentRefList::const_iterator end
= aAllContents
.end();
585 ucbhelper::ContentImplHelperRef xChild
= (*it
);
586 OUString aChildURL
= xChild
->getIdentifier()->getContentIdentifier();
588 // Is aURL a prefix of aChildURL?
589 if ( ( aChildURL
.getLength() > nLen
) && aChildURL
.startsWith( aURL
) )
591 sal_Int32 nPos
= nLen
;
592 nPos
= aChildURL
.indexOf( '/', nPos
);
594 if ( ( nPos
== -1 ) || ( nPos
== ( aChildURL
.getLength() - 1 ) ) )
596 // No further slashes / only a final slash. It's a child!
597 rChildren
.push_back( ::gio::Content::ContentRef (static_cast< ::gio::Content
* >(xChild
.get() ) ) );
604 bool Content::exchangeIdentity( const uno::Reference
< ucb::XContentIdentifier
>& xNewId
)
609 uno::Reference
< ucb::XContent
> xThis
= this;
613 m_xIdentifier
= xNewId
;
617 OUString aOldURL
= m_xIdentifier
->getContentIdentifier();
619 // Exchange own identitity.
620 if ( exchange( xNewId
) )
622 // Process instantiated children...
623 ContentRefList aChildren
;
624 queryChildren( aChildren
);
626 ContentRefList::const_iterator it
= aChildren
.begin();
627 ContentRefList::const_iterator end
= aChildren
.end();
631 ContentRef xChild
= (*it
);
633 // Create new content identifier for the child...
634 uno::Reference
< ucb::XContentIdentifier
> xOldChildId
= xChild
->getIdentifier();
635 OUString aOldChildURL
= xOldChildId
->getContentIdentifier();
636 OUString aNewChildURL
= aOldChildURL
.replaceAt(
637 0, aOldURL
.getLength(), xNewId
->getContentIdentifier() );
639 uno::Reference
< ucb::XContentIdentifier
> xNewChildId
640 = new ::ucbhelper::ContentIdentifier( aNewChildURL
);
642 if ( !xChild
->exchangeIdentity( xNewChildId
) )
653 uno::Sequence
< uno::Any
> Content::setPropertyValues(
654 const uno::Sequence
< beans::PropertyValue
>& rValues
,
655 const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
658 GFileInfo
*pNewInfo
=NULL
;
659 GFileInfo
*pInfo
= getGFileInfo(xEnv
, &pError
);
661 pNewInfo
= g_file_info_dup(pInfo
);
665 ucbhelper::cancelCommandExecution(mapGIOError(pError
), xEnv
);
669 g_error_free(pError
);
670 pNewInfo
= g_file_info_new();
674 sal_Int32 nCount
= rValues
.getLength();
676 beans::PropertyChangeEvent aEvent
;
677 aEvent
.Source
= static_cast< cppu::OWeakObject
* >( this );
678 aEvent
.Further
= sal_False
;
679 aEvent
.PropertyHandle
= -1;
681 sal_Int32 nChanged
= 0, nTitlePos
= -1;
682 const char *newName
= NULL
;
683 uno::Sequence
< beans::PropertyChangeEvent
> aChanges(nCount
);
685 uno::Sequence
< uno::Any
> aRet( nCount
);
686 const beans::PropertyValue
* pValues
= rValues
.getConstArray();
687 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
689 const beans::PropertyValue
& rValue
= pValues
[ n
];
690 #if OSL_DEBUG_LEVEL > 1
691 g_warning("Set prop '%s'", OUStringToOString(rValue
.Name
, RTL_TEXTENCODING_UTF8
).getStr());
693 if ( rValue
.Name
== "ContentType" ||
694 rValue
.Name
== "MediaType" ||
695 rValue
.Name
== "IsDocument" ||
696 rValue
.Name
== "IsFolder" ||
697 rValue
.Name
== "Size" ||
698 rValue
.Name
== "CreatableContentsInfo" )
700 aRet
[ n
] <<= getReadOnlyException( static_cast< cppu::OWeakObject
* >(this) );
702 else if ( rValue
.Name
== "Title" )
705 if (!( rValue
.Value
>>= aNewTitle
))
707 aRet
[ n
] <<= beans::IllegalTypeException
708 ( OUString("Property value has wrong type!"),
709 static_cast< cppu::OWeakObject
* >( this ) );
713 if ( aNewTitle
.getLength() <= 0 )
715 aRet
[ n
] <<= lang::IllegalArgumentException
716 ( OUString("Empty title not allowed!"),
717 static_cast< cppu::OWeakObject
* >( this ), -1 );
722 OString sNewTitle
= OUStringToOString(aNewTitle
, RTL_TEXTENCODING_UTF8
);
723 newName
= sNewTitle
.getStr();
724 const char *oldName
= g_file_info_get_name( pInfo
);
726 if (!newName
|| !oldName
|| strcmp(newName
, oldName
))
728 #if OSL_DEBUG_LEVEL > 1
729 g_warning ("Set new name to '%s'", newName
);
732 aEvent
.PropertyName
= "Title";
734 aEvent
.OldValue
= uno::makeAny(OUString(oldName
, strlen(oldName
), RTL_TEXTENCODING_UTF8
));
735 aEvent
.NewValue
= uno::makeAny(aNewTitle
);
736 aChanges
.getArray()[ nChanged
] = aEvent
;
737 nTitlePos
= nChanged
++;
739 g_file_info_set_name(pNewInfo
, newName
);
744 SAL_WARN("ucb.ucp.gio", "Unknown property " << rValue
.Name
<< "\n");
745 aRet
[ n
] <<= getReadOnlyException( static_cast< cppu::OWeakObject
* >(this) );
755 if ((bOk
= doSetFileInfo(pNewInfo
)))
757 for (sal_Int32 i
= 0; i
< nChanged
; ++i
)
758 aRet
[ i
] <<= getBadArgExcept();
766 OUString aNewURL
= getParentURL();
767 aNewURL
+= OUString( newName
, strlen(newName
), RTL_TEXTENCODING_UTF8
);
768 uno::Reference
< ucb::XContentIdentifier
> xNewId
769 = new ::ucbhelper::ContentIdentifier( aNewURL
);
771 if (!exchangeIdentity( xNewId
) )
773 aRet
[ nTitlePos
] <<= uno::Exception
774 ( OUString("Exchange failed!"),
775 static_cast< cppu::OWeakObject
* >( this ) );
779 if (!mbTransient
) //Discard and refetch
781 g_object_unref(mpInfo
);
787 g_file_info_copy_into(pNewInfo
, mpInfo
);
788 g_object_unref(pNewInfo
);
793 if (mpFile
) //Discard and refetch
795 g_object_unref(mpFile
);
800 aChanges
.realloc( nChanged
);
801 notifyPropertiesChange( aChanges
);
807 bool Content::doSetFileInfo(GFileInfo
*pNewInfo
)
809 g_assert (!mbTransient
);
812 GFile
*pFile
= getGFile();
813 if(!g_file_set_attributes_from_info(pFile
, pNewInfo
, G_FILE_QUERY_INFO_NONE
, NULL
, NULL
))
818 const int TRANSFER_BUFFER_SIZE
= 65536;
820 void Content::copyData( uno::Reference
< io::XInputStream
> xIn
,
821 uno::Reference
< io::XOutputStream
> xOut
)
823 uno::Sequence
< sal_Int8
> theData( TRANSFER_BUFFER_SIZE
);
825 g_return_if_fail( xIn
.is() && xOut
.is() );
827 while ( xIn
->readBytes( theData
, TRANSFER_BUFFER_SIZE
) > 0 )
828 xOut
->writeBytes( theData
);
833 bool Content::feedSink( uno::Reference
< uno::XInterface
> xSink
,
834 const uno::Reference
< ucb::XCommandEnvironment
>& /*xEnv*/ )
839 uno::Reference
< io::XOutputStream
> xOut
= uno::Reference
< io::XOutputStream
>(xSink
, uno::UNO_QUERY
);
840 uno::Reference
< io::XActiveDataSink
> xDataSink
= uno::Reference
< io::XActiveDataSink
>(xSink
, uno::UNO_QUERY
);
842 if ( !xOut
.is() && !xDataSink
.is() )
846 GFileInputStream
*pStream
= g_file_read(getGFile(), NULL
, &pError
);
848 convertToException(pError
, static_cast< cppu::OWeakObject
* >(this));
850 uno::Reference
< io::XInputStream
> xIn(
851 new comphelper::OSeekableInputWrapper(
852 new ::gio::InputStream(pStream
), m_xContext
));
855 copyData( xIn
, xOut
);
857 if ( xDataSink
.is() )
858 xDataSink
->setInputStream( xIn
);
863 uno::Any
Content::open(const ucb::OpenCommandArgument2
& rOpenCommand
,
864 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
865 throw( uno::Exception
)
867 bool bIsFolder
= isFolder(xEnv
);
869 if (!g_file_query_exists(getGFile(), NULL
))
871 uno::Sequence
< uno::Any
> aArgs( 1 );
872 aArgs
[ 0 ] <<= m_xIdentifier
->getContentIdentifier();
873 uno::Any aErr
= uno::makeAny(
874 ucb::InteractiveAugmentedIOException(OUString(), static_cast< cppu::OWeakObject
* >( this ),
875 task::InteractionClassification_ERROR
,
876 bIsFolder
? ucb::IOErrorCode_NOT_EXISTING_PATH
: ucb::IOErrorCode_NOT_EXISTING
, aArgs
)
879 ucbhelper::cancelCommandExecution(aErr
, xEnv
);
885 ( rOpenCommand
.Mode
== ucb::OpenMode::ALL
) ||
886 ( rOpenCommand
.Mode
== ucb::OpenMode::FOLDERS
) ||
887 ( rOpenCommand
.Mode
== ucb::OpenMode::DOCUMENTS
)
890 if ( bOpenFolder
&& bIsFolder
)
892 uno::Reference
< ucb::XDynamicResultSet
> xSet
893 = new DynamicResultSet( m_xContext
, this, rOpenCommand
, xEnv
);
896 else if ( rOpenCommand
.Sink
.is() )
899 ( rOpenCommand
.Mode
== ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE
) ||
900 ( rOpenCommand
.Mode
== ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE
)
903 ucbhelper::cancelCommandExecution(
904 uno::makeAny ( ucb::UnsupportedOpenModeException
905 ( OUString(), static_cast< cppu::OWeakObject
* >( this ),
906 sal_Int16( rOpenCommand
.Mode
) ) ),
910 if ( !feedSink( rOpenCommand
.Sink
, xEnv
) )
912 // Note: rOpenCommand.Sink may contain an XStream
913 // implementation. Support for this type of
914 // sink is optional...
916 g_warning ("Failed to load data from '%s'",
917 OUStringToOString(m_xIdentifier
->getContentIdentifier(), RTL_TEXTENCODING_UTF8
).getStr());
920 ucbhelper::cancelCommandExecution(
921 uno::makeAny (ucb::UnsupportedDataSinkException
922 ( OUString(), static_cast< cppu::OWeakObject
* >( this ),
923 rOpenCommand
.Sink
) ),
928 g_warning ("Open falling through ...");
932 uno::Any SAL_CALL
Content::execute(
933 const ucb::Command
& aCommand
,
934 sal_Int32
/*CommandId*/,
935 const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
936 throw( uno::Exception
,
937 ucb::CommandAbortedException
,
938 uno::RuntimeException
, std::exception
)
940 SAL_INFO("ucb.ucp.gio", "Content::execute " << aCommand
.Name
<< "\n");
943 if ( aCommand
.Name
== "getPropertyValues" )
945 uno::Sequence
< beans::Property
> Properties
;
946 if ( !( aCommand
.Argument
>>= Properties
) )
947 ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv
);
948 aRet
<<= getPropertyValues( Properties
, xEnv
);
950 else if ( aCommand
.Name
== "getPropertySetInfo" )
951 aRet
<<= getPropertySetInfo( xEnv
, false );
952 else if ( aCommand
.Name
== "getCommandInfo" )
953 aRet
<<= getCommandInfo( xEnv
, false );
954 else if ( aCommand
.Name
== "open" )
956 ucb::OpenCommandArgument2 aOpenCommand
;
957 if ( !( aCommand
.Argument
>>= aOpenCommand
) )
958 ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv
);
959 aRet
= open( aOpenCommand
, xEnv
);
961 else if ( aCommand
.Name
== "transfer" )
963 ucb::TransferInfo transferArgs
;
964 if ( !( aCommand
.Argument
>>= transferArgs
) )
965 ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv
);
966 transfer( transferArgs
, xEnv
);
968 else if ( aCommand
.Name
== "setPropertyValues" )
970 uno::Sequence
< beans::PropertyValue
> aProperties
;
971 if ( !( aCommand
.Argument
>>= aProperties
) || !aProperties
.getLength() )
972 ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv
);
973 aRet
<<= setPropertyValues( aProperties
, xEnv
);
975 else if (aCommand
.Name
== "createNewContent"
976 && isFolder( xEnv
) )
978 ucb::ContentInfo arg
;
979 if ( !( aCommand
.Argument
>>= arg
) )
980 ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv
);
981 aRet
<<= createNewContent( arg
);
983 else if ( aCommand
.Name
== "insert" )
985 ucb::InsertCommandArgument arg
;
986 if ( !( aCommand
.Argument
>>= arg
) )
987 ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv
);
988 insert( arg
.Data
, arg
.ReplaceExisting
, xEnv
);
990 else if ( aCommand
.Name
== "delete" )
992 bool bDeletePhysical
= false;
993 aCommand
.Argument
>>= bDeletePhysical
;
995 //If no delete physical, try and trashcan it, if that doesn't work go
996 //ahead and try and delete it anyway
997 if (!bDeletePhysical
&& !g_file_trash(getGFile(), NULL
, NULL
))
998 bDeletePhysical
= true;
1000 if (bDeletePhysical
)
1002 GError
*pError
= NULL
;
1003 if (!g_file_delete( getGFile(), NULL
, &pError
))
1004 ucbhelper::cancelCommandExecution(mapGIOError(pError
), xEnv
);
1007 destroy( bDeletePhysical
);
1011 SAL_WARN("ucb.ucp.gio", "Unknown command " << aCommand
.Name
<< "\n");
1013 ucbhelper::cancelCommandExecution
1014 ( uno::makeAny( ucb::UnsupportedCommandException
1016 static_cast< cppu::OWeakObject
* >( this ) ) ),
1023 void Content::destroy( bool bDeletePhysical
)
1024 throw( uno::Exception
)
1026 uno::Reference
< ucb::XContent
> xThis
= this;
1030 ::gio::Content::ContentRefList aChildren
;
1031 queryChildren( aChildren
);
1033 ContentRefList::const_iterator it
= aChildren
.begin();
1034 ContentRefList::const_iterator end
= aChildren
.end();
1038 (*it
)->destroy( bDeletePhysical
);
1043 void Content::insert(const uno::Reference
< io::XInputStream
> &xInputStream
,
1044 bool bReplaceExisting
, const uno::Reference
< ucb::XCommandEnvironment
> &xEnv
)
1045 throw( uno::Exception
)
1047 GError
*pError
= NULL
;
1048 GFileInfo
*pInfo
= getGFileInfo(xEnv
);
1051 g_file_info_has_attribute(pInfo
, G_FILE_ATTRIBUTE_STANDARD_TYPE
) &&
1052 g_file_info_get_file_type(pInfo
) == G_FILE_TYPE_DIRECTORY
)
1054 #if OSL_DEBUG_LEVEL > 1
1055 g_warning ("Make directory");
1057 if( !g_file_make_directory( getGFile(), NULL
, &pError
))
1058 ucbhelper::cancelCommandExecution(mapGIOError(pError
), xEnv
);
1062 if ( !xInputStream
.is() )
1064 ucbhelper::cancelCommandExecution( uno::makeAny
1065 ( ucb::MissingInputStreamException
1066 ( OUString(), static_cast< cppu::OWeakObject
* >( this ) ) ),
1070 GFileOutputStream
* pOutStream
= NULL
;
1071 if ( bReplaceExisting
)
1073 if (!(pOutStream
= g_file_replace(getGFile(), NULL
, false, G_FILE_CREATE_PRIVATE
, NULL
, &pError
)))
1074 ucbhelper::cancelCommandExecution(mapGIOError(pError
), xEnv
);
1078 if (!(pOutStream
= g_file_create (getGFile(), G_FILE_CREATE_PRIVATE
, NULL
, &pError
)))
1079 ucbhelper::cancelCommandExecution(mapGIOError(pError
), xEnv
);
1082 uno::Reference
< io::XOutputStream
> xOutput
= new ::gio::OutputStream(pOutStream
);
1083 copyData( xInputStream
, xOutput
);
1087 mbTransient
= false;
1092 const GFileCopyFlags DEFAULT_COPYDATA_FLAGS
=
1093 static_cast<GFileCopyFlags
>(G_FILE_COPY_OVERWRITE
|G_FILE_COPY_TARGET_DEFAULT_PERMS
);
1095 void Content::transfer( const ucb::TransferInfo
& aTransferInfo
, const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
1096 throw( uno::Exception
)
1098 OUString sDest
= m_xIdentifier
->getContentIdentifier();
1099 if (!sDest
.endsWith("/")) {
1102 if (aTransferInfo
.NewTitle
.getLength())
1103 sDest
+= aTransferInfo
.NewTitle
;
1105 sDest
+= OUString::createFromAscii(g_file_get_basename(getGFile()));
1107 GFile
*pDest
= g_file_new_for_uri(OUStringToOString(sDest
, RTL_TEXTENCODING_UTF8
).getStr());
1108 GFile
*pSource
= g_file_new_for_uri(OUStringToOString(aTransferInfo
.SourceURL
, RTL_TEXTENCODING_UTF8
).getStr());
1110 gboolean bSuccess
= false;
1111 GError
*pError
= NULL
;
1112 if (aTransferInfo
.MoveData
)
1113 bSuccess
= g_file_move(pSource
, pDest
, G_FILE_COPY_OVERWRITE
, NULL
, NULL
, 0, &pError
);
1115 bSuccess
= g_file_copy(pSource
, pDest
, DEFAULT_COPYDATA_FLAGS
, NULL
, NULL
, 0, &pError
);
1116 g_object_unref(pSource
);
1117 g_object_unref(pDest
);
1119 ucbhelper::cancelCommandExecution(mapGIOError(pError
), xEnv
);
1122 uno::Sequence
< ucb::ContentInfo
> Content::queryCreatableContentsInfo(
1123 const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
1124 throw( uno::RuntimeException
)
1126 if ( isFolder( xEnv
) )
1128 uno::Sequence
< ucb::ContentInfo
> seq(2);
1130 // Minimum set of props we really need
1131 uno::Sequence
< beans::Property
> props( 1 );
1132 props
[0] = beans::Property(
1135 cppu::UnoType
<OUString
>::get(),
1136 beans::PropertyAttribute::MAYBEVOID
| beans::PropertyAttribute::BOUND
);
1139 seq
[0].Type
= GIO_FILE_TYPE
;
1140 seq
[0].Attributes
= ( ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM
|
1141 ucb::ContentInfoAttribute::KIND_DOCUMENT
);
1142 seq
[0].Properties
= props
;
1145 seq
[1].Type
= GIO_FOLDER_TYPE
;
1146 seq
[1].Attributes
= ucb::ContentInfoAttribute::KIND_FOLDER
;
1147 seq
[1].Properties
= props
;
1153 return uno::Sequence
< ucb::ContentInfo
>();
1157 uno::Sequence
< ucb::ContentInfo
> SAL_CALL
Content::queryCreatableContentsInfo()
1158 throw( uno::RuntimeException
, std::exception
)
1160 return queryCreatableContentsInfo( uno::Reference
< ucb::XCommandEnvironment
>() );
1163 uno::Reference
< ucb::XContent
>
1164 SAL_CALL
Content::createNewContent( const ucb::ContentInfo
& Info
)
1165 throw( uno::RuntimeException
, std::exception
)
1167 bool create_document
;
1170 if ( Info
.Type
== GIO_FILE_TYPE
)
1171 create_document
= true;
1172 else if ( Info
.Type
== GIO_FOLDER_TYPE
)
1173 create_document
= false;
1177 g_warning( "Failed to create new content '%s'", OUStringToOString(Info
.Type
,
1178 RTL_TEXTENCODING_UTF8
).getStr() );
1180 return uno::Reference
< ucb::XContent
>();
1183 #if OSL_DEBUG_LEVEL > 1
1184 g_warning( "createNewContent (%d)", (int) create_document
);
1187 OUString aURL
= m_xIdentifier
->getContentIdentifier();
1189 if ( ( aURL
.lastIndexOf( '/' ) + 1 ) != aURL
.getLength() )
1192 name
= create_document
? "[New_Content]" : "[New_Collection]";
1193 aURL
+= OUString::createFromAscii( name
);
1195 uno::Reference
< ucb::XContentIdentifier
> xId(new ::ucbhelper::ContentIdentifier(aURL
));
1199 return new ::gio::Content( m_xContext
, m_pProvider
, xId
, !create_document
);
1200 } catch ( ucb::ContentCreationException
& )
1202 return uno::Reference
< ucb::XContent
>();
1206 uno::Sequence
< uno::Type
> SAL_CALL
Content::getTypes()
1207 throw( uno::RuntimeException
, std::exception
)
1209 if ( isFolder( uno::Reference
< ucb::XCommandEnvironment
>() ) )
1211 static cppu::OTypeCollection aFolderCollection
1212 (CPPU_TYPE_REF( lang::XTypeProvider
),
1213 CPPU_TYPE_REF( lang::XServiceInfo
),
1214 CPPU_TYPE_REF( lang::XComponent
),
1215 CPPU_TYPE_REF( ucb::XContent
),
1216 CPPU_TYPE_REF( ucb::XCommandProcessor
),
1217 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier
),
1218 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier
),
1219 CPPU_TYPE_REF( beans::XPropertyContainer
),
1220 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier
),
1221 CPPU_TYPE_REF( container::XChild
),
1222 CPPU_TYPE_REF( ucb::XContentCreator
) );
1223 return aFolderCollection
.getTypes();
1227 static cppu::OTypeCollection aFileCollection
1228 (CPPU_TYPE_REF( lang::XTypeProvider
),
1229 CPPU_TYPE_REF( lang::XServiceInfo
),
1230 CPPU_TYPE_REF( lang::XComponent
),
1231 CPPU_TYPE_REF( ucb::XContent
),
1232 CPPU_TYPE_REF( ucb::XCommandProcessor
),
1233 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier
),
1234 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier
),
1235 CPPU_TYPE_REF( beans::XPropertyContainer
),
1236 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier
),
1237 CPPU_TYPE_REF( container::XChild
) );
1239 return aFileCollection
.getTypes();
1243 uno::Sequence
< beans::Property
> Content::getProperties(
1244 const uno::Reference
< ucb::XCommandEnvironment
> & /*xEnv*/ )
1246 static const beans::Property aGenericProperties
[] =
1248 beans::Property( OUString( "IsDocument" ),
1249 -1, cppu::UnoType
<bool>::get(),
1250 beans::PropertyAttribute::BOUND
| beans::PropertyAttribute::READONLY
),
1251 beans::Property( OUString( "IsFolder" ),
1252 -1, cppu::UnoType
<bool>::get(),
1253 beans::PropertyAttribute::BOUND
| beans::PropertyAttribute::READONLY
),
1254 beans::Property( OUString( "Title" ),
1255 -1, cppu::UnoType
<OUString
>::get(),
1256 beans::PropertyAttribute::BOUND
),
1257 beans::Property( OUString( "IsReadOnly" ),
1258 -1, cppu::UnoType
<bool>::get(),
1259 beans::PropertyAttribute::BOUND
| beans::PropertyAttribute::READONLY
),
1260 beans::Property( OUString( "DateCreated" ),
1261 -1, cppu::UnoType
<util::DateTime
>::get(),
1262 beans::PropertyAttribute::BOUND
| beans::PropertyAttribute::READONLY
),
1263 beans::Property( OUString( "DateModified" ),
1264 -1, cppu::UnoType
<util::DateTime
>::get(),
1265 beans::PropertyAttribute::BOUND
| beans::PropertyAttribute::READONLY
),
1266 beans::Property( OUString( "Size" ),
1267 -1, cppu::UnoType
<sal_Int64
>::get(),
1268 beans::PropertyAttribute::BOUND
| beans::PropertyAttribute::READONLY
),
1269 beans::Property( OUString( "IsVolume" ),
1270 1, cppu::UnoType
<bool>::get(),
1271 beans::PropertyAttribute::BOUND
| beans::PropertyAttribute::READONLY
),
1272 beans::Property( OUString( "IsCompactDisc" ),
1273 -1, cppu::UnoType
<bool>::get(),
1274 beans::PropertyAttribute::BOUND
| beans::PropertyAttribute::READONLY
),
1275 beans::Property( OUString( "IsRemoveable" ),
1276 -1, cppu::UnoType
<bool>::get(),
1277 beans::PropertyAttribute::BOUND
| beans::PropertyAttribute::READONLY
),
1278 beans::Property( OUString( "IsHidden" ),
1279 -1, cppu::UnoType
<bool>::get(),
1280 beans::PropertyAttribute::BOUND
| beans::PropertyAttribute::READONLY
),
1281 beans::Property( OUString( "CreatableContentsInfo" ),
1282 -1, cppu::UnoType
<uno::Sequence
< ucb::ContentInfo
>>::get(),
1283 beans::PropertyAttribute::BOUND
| beans::PropertyAttribute::READONLY
)
1286 const int nProps
= sizeof (aGenericProperties
) / sizeof (aGenericProperties
[0]);
1287 return uno::Sequence
< beans::Property
> ( aGenericProperties
, nProps
);
1290 uno::Sequence
< ucb::CommandInfo
> Content::getCommands( const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
1292 static const ucb::CommandInfo aCommandInfoTable
[] =
1294 // Required commands
1296 ( OUString( "getCommandInfo" ),
1297 -1, cppu::UnoType
<void>::get() ),
1299 ( OUString( "getPropertySetInfo" ),
1300 -1, cppu::UnoType
<void>::get() ),
1302 ( OUString( "getPropertyValues" ),
1303 -1, cppu::UnoType
<uno::Sequence
< beans::Property
>>::get() ),
1305 ( OUString( "setPropertyValues" ),
1306 -1, cppu::UnoType
<uno::Sequence
< beans::PropertyValue
>>::get() ),
1308 // Optional standard commands
1310 ( OUString( "delete" ),
1311 -1, cppu::UnoType
<bool>::get() ),
1313 ( OUString( "insert" ),
1314 -1, cppu::UnoType
<ucb::InsertCommandArgument
>::get() ),
1316 ( OUString( "open" ),
1317 -1, cppu::UnoType
<ucb::OpenCommandArgument2
>::get() ),
1319 // Folder Only, omitted if not a folder
1321 ( OUString( "transfer" ),
1322 -1, cppu::UnoType
<ucb::TransferInfo
>::get() ),
1324 ( OUString( "createNewContent" ),
1325 -1, cppu::UnoType
<ucb::ContentInfo
>::get() )
1328 const int nProps
= sizeof (aCommandInfoTable
) / sizeof (aCommandInfoTable
[0]);
1329 return uno::Sequence
< ucb::CommandInfo
>(aCommandInfoTable
, isFolder(xEnv
) ? nProps
: nProps
- 2);
1332 XTYPEPROVIDER_COMMON_IMPL( Content
);
1334 void SAL_CALL
Content::acquire() throw()
1336 ContentImplHelper::acquire();
1339 void SAL_CALL
Content::release() throw()
1341 ContentImplHelper::release();
1344 uno::Any SAL_CALL
Content::queryInterface( const uno::Type
& rType
) throw ( uno::RuntimeException
, std::exception
)
1346 uno::Any aRet
= cppu::queryInterface( rType
, static_cast< ucb::XContentCreator
* >( this ) );
1347 return aRet
.hasValue() ? aRet
: ContentImplHelper::queryInterface(rType
);
1350 OUString SAL_CALL
Content::getImplementationName() throw( uno::RuntimeException
, std::exception
)
1352 return OUString("com.sun.star.comp.GIOContent");
1355 uno::Sequence
< OUString
> SAL_CALL
Content::getSupportedServiceNames()
1356 throw( uno::RuntimeException
, std::exception
)
1358 uno::Sequence
< OUString
> aSNS( 1 );
1359 aSNS
.getArray()[ 0 ] = "com.sun.star.ucb.GIOContent";
1365 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */