summaryrefslogtreecommitdiff
path: root/ucb/source/ucp/gio/gio_content.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'ucb/source/ucp/gio/gio_content.cxx')
-rw-r--r--ucb/source/ucp/gio/gio_content.cxx1337
1 files changed, 1337 insertions, 0 deletions
diff --git a/ucb/source/ucp/gio/gio_content.cxx b/ucb/source/ucp/gio/gio_content.cxx
new file mode 100644
index 000000000000..c8c397853fb5
--- /dev/null
+++ b/ucb/source/ucp/gio/gio_content.cxx
@@ -0,0 +1,1337 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sal/macros.h>
+#include <osl/time.h>
+
+#include <osl/diagnose.h>
+#include <osl/doublecheckedlocking.h>
+
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/beans/PropertySetInfoChange.hpp>
+#include <com/sun/star/beans/PropertySetInfoChangeEvent.hpp>
+#include <com/sun/star/io/XActiveDataSink.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/lang/IllegalAccessException.hpp>
+#include <com/sun/star/ucb/ContentInfoAttribute.hpp>
+#include <com/sun/star/ucb/InsertCommandArgument.hpp>
+#include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp>
+#include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
+#include <com/sun/star/ucb/InteractiveNetworkWriteException.hpp>
+#include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
+#include <com/sun/star/ucb/InteractiveNetworkConnectException.hpp>
+#include <com/sun/star/ucb/InteractiveNetworkGeneralException.hpp>
+#include <com/sun/star/ucb/InteractiveNetworkReadException.hpp>
+#include <com/sun/star/ucb/InteractiveNetworkResolveNameException.hpp>
+#include <com/sun/star/ucb/InteractiveNetworkWriteException.hpp>
+#include <com/sun/star/ucb/NameClash.hpp>
+#include <com/sun/star/ucb/NameClashException.hpp>
+#include <com/sun/star/ucb/OpenMode.hpp>
+#include <com/sun/star/ucb/PostCommandArgument2.hpp>
+#include <com/sun/star/ucb/XCommandInfo.hpp>
+#include <com/sun/star/ucb/XPersistentPropertySet.hpp>
+#include <com/sun/star/ucb/MissingInputStreamException.hpp>
+#include <com/sun/star/ucb/MissingPropertiesException.hpp>
+#include <com/sun/star/ucb/UnsupportedCommandException.hpp>
+#include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
+#include <com/sun/star/ucb/UnsupportedNameClashException.hpp>
+#include <com/sun/star/ucb/UnsupportedOpenModeException.hpp>
+#include <com/sun/star/ucb/UnsupportedOpenModeException.hpp>
+#include <com/sun/star/ucb/NameClashException.hpp>
+#include <com/sun/star/ucb/XDynamicResultSet.hpp>
+#include <com/sun/star/ucb/XContentCreator.hpp>
+
+#include <ucbhelper/contentidentifier.hxx>
+#include <ucbhelper/propertyvalueset.hxx>
+#include <ucbhelper/interactionrequest.hxx>
+#include <ucbhelper/cancelcommandexecution.hxx>
+
+#include <osl/conditn.hxx>
+
+#include "gio_content.hxx"
+#include "gio_provider.hxx"
+#include "gio_resultset.hxx"
+#include "gio_inputstream.hxx"
+#include "gio_outputstream.hxx"
+#include "gio_mount.hxx"
+
+#include <stdio.h>
+
+using namespace com::sun::star;
+
+namespace gio
+{
+
+Content::Content(
+ const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
+ ContentProvider* pProvider,
+ const uno::Reference< ucb::XContentIdentifier >& Identifier)
+ throw ( ucb::ContentCreationException )
+ : ContentImplHelper( rxSMgr, pProvider, Identifier ),
+ m_pProvider( pProvider ), mpFile (NULL), mpInfo( NULL ), mbTransient(false)
+{
+#ifdef DEBUG
+ fprintf(stderr, "New Content ('%s')\n", rtl::OUStringToOString(m_xIdentifier->getContentIdentifier(), RTL_TEXTENCODING_UTF8).getStr());
+#endif
+}
+
+Content::Content(
+ const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
+ ContentProvider* pProvider,
+ const uno::Reference< ucb::XContentIdentifier >& Identifier,
+ sal_Bool bIsFolder)
+ throw ( ucb::ContentCreationException )
+ : ContentImplHelper( rxSMgr, pProvider, Identifier ),
+ m_pProvider( pProvider ), mpFile (NULL), mpInfo( NULL ), mbTransient(true)
+{
+#ifdef DEBUG
+ fprintf(stderr, "Create Content ('%s')\n", rtl::OUStringToOString(m_xIdentifier->getContentIdentifier(), RTL_TEXTENCODING_UTF8).getStr());
+#endif
+ mpInfo = g_file_info_new();
+ g_file_info_set_file_type(mpInfo, bIsFolder ? G_FILE_TYPE_DIRECTORY : G_FILE_TYPE_REGULAR);
+}
+
+Content::~Content()
+{
+ if (mpInfo) g_object_unref(mpInfo);
+ if (mpFile) g_object_unref(mpFile);
+}
+
+rtl::OUString Content::getParentURL()
+{
+ rtl::OUString sURL;
+ if (GFile* pFile = g_file_get_parent(getGFile()))
+ {
+ char* pPath = g_file_get_uri(pFile);
+ g_object_unref(pFile);
+ sURL = rtl::OUString::createFromAscii(pPath);
+ g_free(pPath);
+ }
+ return sURL;
+}
+
+void SAL_CALL Content::abort( sal_Int32 /*CommandId*/ )
+ throw( uno::RuntimeException )
+{
+ //TODO
+ //stick a map from each CommandId to a new GCancellable and propogate
+ //it throughout the g_file_* calls
+}
+
+rtl::OUString SAL_CALL Content::getContentType() throw( uno::RuntimeException )
+{
+ return isFolder(uno::Reference< ucb::XCommandEnvironment >())
+ ? rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( GIO_FOLDER_TYPE ))
+ : rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( GIO_FILE_TYPE ));
+}
+
+#define EXCEPT(aExcept) \
+do { \
+ if (bThrow) throw aExcept;\
+ aRet = uno::makeAny( aExcept );\
+} while(0)
+
+uno::Any convertToException(GError *pError, const uno::Reference< uno::XInterface >& rContext, bool bThrow)
+{
+ uno::Any aRet;
+
+ gint eCode = pError->code;
+ rtl::OUString sMessage(pError->message, strlen(pError->message), RTL_TEXTENCODING_UTF8);
+ g_error_free(pError);
+
+ rtl::OUString sName;
+ rtl::OUString sHost;
+
+ uno::Sequence< uno::Any > aArgs( 1 );
+ aArgs[ 0 ] <<= sName;
+
+ switch (eCode)
+ {
+ case G_IO_ERROR_FAILED:
+ { io::IOException aExcept(sMessage, rContext);
+ EXCEPT(aExcept); }
+ break;
+ case G_IO_ERROR_NOT_MOUNTED:
+ { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext,
+ task::InteractionClassification_ERROR, ucb::IOErrorCode_NOT_EXISTING_PATH, aArgs);
+ EXCEPT(aExcept); }
+ break;
+ case G_IO_ERROR_NOT_FOUND:
+ { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext,
+ task::InteractionClassification_ERROR, ucb::IOErrorCode_NOT_EXISTING, aArgs);
+ EXCEPT(aExcept); }
+ break;
+ case G_IO_ERROR_EXISTS:
+ { ucb::NameClashException aExcept(sMessage, rContext,
+ task::InteractionClassification_ERROR, sName);
+ EXCEPT(aExcept); }
+ break;
+ case G_IO_ERROR_INVALID_ARGUMENT:
+ { lang::IllegalArgumentException aExcept(sMessage, rContext, -1 );
+ EXCEPT(aExcept); }
+ break;
+ case G_IO_ERROR_PERMISSION_DENIED:
+ { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext,
+ task::InteractionClassification_ERROR, ucb::IOErrorCode_ACCESS_DENIED, aArgs);
+ EXCEPT(aExcept); }
+ break;
+ case G_IO_ERROR_IS_DIRECTORY:
+ { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext,
+ task::InteractionClassification_ERROR, ucb::IOErrorCode_NO_FILE, aArgs);
+ EXCEPT(aExcept); }
+ break;
+ case G_IO_ERROR_NOT_REGULAR_FILE:
+ { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext,
+ task::InteractionClassification_ERROR, ucb::IOErrorCode_NO_FILE, aArgs);
+ EXCEPT(aExcept); }
+ break;
+ case G_IO_ERROR_NOT_DIRECTORY:
+ { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext,
+ task::InteractionClassification_ERROR, ucb::IOErrorCode_NO_DIRECTORY, aArgs);
+ EXCEPT(aExcept); }
+ break;
+ case G_IO_ERROR_FILENAME_TOO_LONG:
+ { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext,
+ task::InteractionClassification_ERROR, ucb::IOErrorCode_NAME_TOO_LONG, aArgs);
+ EXCEPT(aExcept); }
+ break;
+ case G_IO_ERROR_PENDING:
+ { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext,
+ task::InteractionClassification_ERROR, ucb::IOErrorCode_PENDING, aArgs);
+ EXCEPT(aExcept); }
+ break;
+ case G_IO_ERROR_CLOSED:
+ case G_IO_ERROR_CANCELLED:
+ case G_IO_ERROR_TOO_MANY_LINKS:
+ case G_IO_ERROR_WRONG_ETAG:
+ { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext,
+ task::InteractionClassification_ERROR, ucb::IOErrorCode_GENERAL, aArgs);
+ EXCEPT(aExcept); }
+ break;
+ case G_IO_ERROR_NOT_SUPPORTED:
+ case G_IO_ERROR_CANT_CREATE_BACKUP:
+ case G_IO_ERROR_WOULD_MERGE:
+ { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext,
+ task::InteractionClassification_ERROR, ucb::IOErrorCode_NOT_SUPPORTED, aArgs);
+ EXCEPT(aExcept); }
+ break;
+ case G_IO_ERROR_NO_SPACE:
+ { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext,
+ task::InteractionClassification_ERROR, ucb::IOErrorCode_OUT_OF_DISK_SPACE, aArgs);
+ EXCEPT(aExcept); }
+ break;
+ case G_IO_ERROR_INVALID_FILENAME:
+ { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext,
+ task::InteractionClassification_ERROR, ucb::IOErrorCode_INVALID_CHARACTER, aArgs);
+ EXCEPT(aExcept); }
+ break;
+ case G_IO_ERROR_READ_ONLY:
+ { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext,
+ task::InteractionClassification_ERROR, ucb::IOErrorCode_WRITE_PROTECTED, aArgs);
+ EXCEPT(aExcept); }
+ break;
+ case G_IO_ERROR_TIMED_OUT:
+ { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext,
+ task::InteractionClassification_ERROR, ucb::IOErrorCode_DEVICE_NOT_READY, aArgs);
+ EXCEPT(aExcept); }
+ break;
+ case G_IO_ERROR_WOULD_RECURSE:
+ { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext,
+ task::InteractionClassification_ERROR, ucb::IOErrorCode_RECURSIVE, aArgs);
+ EXCEPT(aExcept); }
+ break;
+ case G_IO_ERROR_BUSY:
+ case G_IO_ERROR_WOULD_BLOCK:
+ { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext,
+ task::InteractionClassification_ERROR, ucb::IOErrorCode_LOCKING_VIOLATION, aArgs);
+ EXCEPT(aExcept); }
+ break;
+ case G_IO_ERROR_HOST_NOT_FOUND:
+ { ucb::InteractiveNetworkResolveNameException aExcept(sMessage, rContext,
+ task::InteractionClassification_ERROR, sHost);
+ EXCEPT(aExcept);}
+ break;
+ default:
+ case G_IO_ERROR_ALREADY_MOUNTED:
+ case G_IO_ERROR_NOT_EMPTY:
+ case G_IO_ERROR_NOT_SYMBOLIC_LINK:
+ case G_IO_ERROR_NOT_MOUNTABLE_FILE:
+ case G_IO_ERROR_FAILED_HANDLED:
+ { ucb::InteractiveNetworkGeneralException aExcept(sMessage, rContext,
+ task::InteractionClassification_ERROR);
+ EXCEPT(aExcept);}
+ break;
+ }
+ return aRet;
+}
+
+uno::Any Content::mapGIOError( GError *pError )
+{
+ if (!pError)
+ return getBadArgExcept();
+
+ return convertToException(pError, static_cast< cppu::OWeakObject * >(this), false);
+}
+
+uno::Any Content::getBadArgExcept()
+{
+ return uno::makeAny( lang::IllegalArgumentException(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Wrong argument type!")),
+ static_cast< cppu::OWeakObject * >( this ), -1) );
+}
+
+class MountOperation
+{
+ GMainLoop *mpLoop;
+ GMountOperation *mpAuthentication;
+ GError *mpError;
+ static void Completed(GObject *source, GAsyncResult *res, gpointer user_data);
+public:
+ MountOperation(const uno::Reference< ucb::XCommandEnvironment >& xEnv);
+ ~MountOperation();
+ GError *Mount(GFile *pFile);
+};
+
+MountOperation::MountOperation(const uno::Reference< ucb::XCommandEnvironment >& xEnv) : mpError(NULL)
+{
+ mpLoop = g_main_loop_new(NULL, FALSE);
+ mpAuthentication = ooo_mount_operation_new(xEnv);
+}
+
+void MountOperation::Completed(GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ MountOperation *pThis = (MountOperation*)user_data;
+ g_file_mount_enclosing_volume_finish(G_FILE(source), res, &(pThis->mpError));
+ g_main_loop_quit(pThis->mpLoop);
+}
+
+GError *MountOperation::Mount(GFile *pFile)
+{
+ g_file_mount_enclosing_volume(pFile, G_MOUNT_MOUNT_NONE, mpAuthentication, NULL, MountOperation::Completed, this);
+ g_main_loop_run(mpLoop);
+ return mpError;
+}
+
+MountOperation::~MountOperation()
+{
+ g_object_unref(mpAuthentication);
+ g_main_loop_unref(mpLoop);
+}
+
+GFileInfo* Content::getGFileInfo(const uno::Reference< ucb::XCommandEnvironment >& xEnv, GError **ppError)
+{
+ /*If we don't have it already, and we're not a "pre-creation" content then query for the info"*/
+ if (!mpInfo && !mbTransient)
+ {
+ if (!(mpInfo = g_file_query_info(getGFile(), "*", G_FILE_QUERY_INFO_NONE, NULL, ppError)))
+ {
+ //Try and mount if unmounted
+ if (ppError && (*ppError)->code == G_IO_ERROR_NOT_MOUNTED)
+ {
+ g_error_free(*ppError);
+
+ MountOperation aMounter(xEnv);
+ *ppError = aMounter.Mount(getGFile());
+
+ //No Mount error, reattempt query
+ if (!*ppError)
+ mpInfo = g_file_query_info(getGFile(), "*", G_FILE_QUERY_INFO_NONE, NULL, ppError);
+ }
+ }
+ }
+ return mpInfo;
+}
+
+GFile* Content::getGFile()
+{
+ if (!mpFile)
+ mpFile = g_file_new_for_uri(rtl::OUStringToOString(m_xIdentifier->getContentIdentifier(), RTL_TEXTENCODING_UTF8).getStr());
+ return mpFile;
+}
+
+bool Content::isFolder(const uno::Reference< ucb::XCommandEnvironment >& xEnv)
+{
+ GFileInfo *pInfo = getGFileInfo(xEnv);
+ return pInfo && (g_file_info_get_file_type(pInfo) == G_FILE_TYPE_DIRECTORY);
+}
+
+static util::DateTime getDateFromUnix (time_t t)
+{
+ TimeValue tv;
+ tv.Nanosec = 0;
+ tv.Seconds = t;
+ oslDateTime dt;
+
+ if ( osl_getDateTimeFromTimeValue( &tv, &dt ) )
+ return util::DateTime( 0, dt.Seconds, dt.Minutes, dt.Hours,
+ dt.Day, dt.Month, dt.Year);
+ else
+ return util::DateTime();
+}
+
+uno::Reference< sdbc::XRow > Content::getPropertyValuesFromGFileInfo(GFileInfo *pInfo,
+ const uno::Reference< lang::XMultiServiceFactory >& rSMgr,
+ const uno::Reference< ucb::XCommandEnvironment > & xEnv,
+ const uno::Sequence< beans::Property >& rProperties)
+{
+ rtl::Reference< ::ucbhelper::PropertyValueSet > xRow = new ::ucbhelper::PropertyValueSet( rSMgr );
+
+ sal_Int32 nProps;
+ const beans::Property* pProps;
+
+ nProps = rProperties.getLength();
+ pProps = rProperties.getConstArray();
+
+ for( sal_Int32 n = 0; n < nProps; ++n )
+ {
+ const beans::Property& rProp = pProps[ n ];
+
+ if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) )
+ {
+ if (g_file_info_has_attribute(pInfo, G_FILE_ATTRIBUTE_STANDARD_TYPE))
+ xRow->appendBoolean( rProp, ( g_file_info_get_file_type( pInfo ) == G_FILE_TYPE_REGULAR ||
+ g_file_info_get_file_type( pInfo ) == G_FILE_TYPE_UNKNOWN ) );
+ else
+ xRow->appendVoid( rProp );
+ }
+ else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) )
+ {
+ if( g_file_info_has_attribute( pInfo, G_FILE_ATTRIBUTE_STANDARD_TYPE) )
+ xRow->appendBoolean( rProp, ( g_file_info_get_file_type( pInfo ) == G_FILE_TYPE_DIRECTORY ));
+ else
+ xRow->appendVoid( rProp );
+ }
+ else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Title" ) ) )
+ {
+ if (g_file_info_has_attribute(pInfo, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME))
+ {
+ const char *pName = g_file_info_get_display_name(pInfo);
+ xRow->appendString( rProp, rtl::OUString(pName, strlen(pName), RTL_TEXTENCODING_UTF8) );
+ }
+ else
+ xRow->appendVoid( rProp );
+ }
+ else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsReadOnly" ) ) )
+ {
+ if( g_file_info_has_attribute( pInfo, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE ) )
+ xRow->appendBoolean( rProp, !g_file_info_get_attribute_boolean( pInfo, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE) );
+ else
+ xRow->appendVoid( rProp );
+ }
+ else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "DateCreated" ) ) )
+ {
+ if( g_file_info_has_attribute( pInfo, G_FILE_ATTRIBUTE_TIME_CREATED ) )
+ xRow->appendTimestamp( rProp, getDateFromUnix(g_file_info_get_attribute_uint64(pInfo, G_FILE_ATTRIBUTE_TIME_CREATED)) );
+ else
+ xRow->appendVoid( rProp );
+ }
+ else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "DateModified" ) ) )
+ {
+ if( g_file_info_has_attribute( pInfo, G_FILE_ATTRIBUTE_TIME_CHANGED ) )
+ xRow->appendTimestamp( rProp, getDateFromUnix(g_file_info_get_attribute_uint64(pInfo, G_FILE_ATTRIBUTE_TIME_CHANGED)) );
+ else
+ xRow->appendVoid( rProp );
+ }
+ else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Size" ) ) )
+ {
+ if( g_file_info_has_attribute( pInfo, G_FILE_ATTRIBUTE_STANDARD_SIZE) )
+ xRow->appendLong( rProp, ( g_file_info_get_size( pInfo ) ));
+ else
+ xRow->appendVoid( rProp );
+ }
+ else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsVolume" ) ) )
+ {
+ //What do we use this for ?
+ xRow->appendBoolean( rProp, sal_False );
+ }
+ else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsCompactDisc" ) ) )
+ {
+ if( g_file_info_has_attribute( pInfo, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_EJECT ) )
+ xRow->appendBoolean( rProp, g_file_info_get_attribute_boolean(pInfo, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_EJECT) );
+ else
+ xRow->appendVoid( rProp );
+ }
+ else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsRemoveable" ) ) )
+ {
+ if( g_file_info_has_attribute( pInfo, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT ) )
+ xRow->appendBoolean( rProp, g_file_info_get_attribute_boolean(pInfo, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT ) );
+ else
+ xRow->appendVoid( rProp );
+ }
+ else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsFloppy" ) ) )
+ {
+ xRow->appendBoolean( rProp, sal_False );
+ }
+ else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsHidden" ) ) )
+ {
+ if( g_file_info_has_attribute( pInfo, G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN) )
+ xRow->appendBoolean( rProp, ( g_file_info_get_is_hidden ( pInfo ) ) );
+ else
+ xRow->appendVoid( rProp );
+ }
+ else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "CreatableContentsInfo" ) ) )
+ {
+ xRow->appendObject( rProp, uno::makeAny( queryCreatableContentsInfo( xEnv ) ) );
+ }
+#ifdef DEBUG
+ else
+ {
+ fprintf(stderr, "Looking for unsupported property %s\n",
+ rtl::OUStringToOString(rProp.Name, RTL_TEXTENCODING_UTF8).getStr());
+ }
+#endif
+ }
+
+ return uno::Reference< sdbc::XRow >( xRow.get() );
+}
+
+uno::Reference< sdbc::XRow > Content::getPropertyValues(
+ const uno::Sequence< beans::Property >& rProperties,
+ const uno::Reference< ucb::XCommandEnvironment >& xEnv )
+{
+ GError *pError = NULL;
+ GFileInfo *pInfo = getGFileInfo(xEnv, &pError);
+ if (!pInfo)
+ ucbhelper::cancelCommandExecution(mapGIOError(pError), xEnv);
+
+ return getPropertyValuesFromGFileInfo(pInfo, m_xSMgr, xEnv, rProperties);
+}
+
+static lang::IllegalAccessException
+getReadOnlyException( const uno::Reference< uno::XInterface >& rContext )
+{
+ return lang::IllegalAccessException ( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Property is read-only!")), rContext );
+}
+
+void Content::queryChildren( ContentRefList& rChildren )
+{
+ // Obtain a list with a snapshot of all currently instanciated contents
+ // from provider and extract the contents which are direct children
+ // of this content.
+
+ ucbhelper::ContentRefList aAllContents;
+ m_xProvider->queryExistingContents( aAllContents );
+
+ rtl::OUString aURL = m_xIdentifier->getContentIdentifier();
+ sal_Int32 nURLPos = aURL.lastIndexOf( '/' );
+
+ if ( nURLPos != ( aURL.getLength() - 1 ) )
+ aURL += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/"));
+
+ sal_Int32 nLen = aURL.getLength();
+
+ ucbhelper::ContentRefList::const_iterator it = aAllContents.begin();
+ ucbhelper::ContentRefList::const_iterator end = aAllContents.end();
+
+ while ( it != end )
+ {
+ ucbhelper::ContentImplHelperRef xChild = (*it);
+ rtl::OUString aChildURL = xChild->getIdentifier()->getContentIdentifier();
+
+ // Is aURL a prefix of aChildURL?
+ if ( ( aChildURL.getLength() > nLen ) && ( aChildURL.compareTo( aURL, nLen ) == 0 ) )
+ {
+ sal_Int32 nPos = nLen;
+ nPos = aChildURL.indexOf( '/', nPos );
+
+ if ( ( nPos == -1 ) || ( nPos == ( aChildURL.getLength() - 1 ) ) )
+ {
+ // No further slashes / only a final slash. It's a child!
+ rChildren.push_back( ::gio::Content::ContentRef (static_cast< ::gio::Content * >(xChild.get() ) ) );
+ }
+ }
+ ++it;
+ }
+}
+
+sal_Bool Content::exchangeIdentity( const uno::Reference< ucb::XContentIdentifier >& xNewId )
+{
+ if ( !xNewId.is() )
+ return sal_False;
+
+ uno::Reference< ucb::XContent > xThis = this;
+
+ if ( mbTransient )
+ {
+ m_xIdentifier = xNewId;
+ return sal_False;
+ }
+
+ rtl::OUString aOldURL = m_xIdentifier->getContentIdentifier();
+
+ // Exchange own identitity.
+ if ( exchange( xNewId ) )
+ {
+ // Process instanciated children...
+ ContentRefList aChildren;
+ queryChildren( aChildren );
+
+ ContentRefList::const_iterator it = aChildren.begin();
+ ContentRefList::const_iterator end = aChildren.end();
+
+ while ( it != end )
+ {
+ ContentRef xChild = (*it);
+
+ // Create new content identifier for the child...
+ uno::Reference< ucb::XContentIdentifier > xOldChildId = xChild->getIdentifier();
+ rtl::OUString aOldChildURL = xOldChildId->getContentIdentifier();
+ rtl::OUString aNewChildURL = aOldChildURL.replaceAt(
+ 0, aOldURL.getLength(), xNewId->getContentIdentifier() );
+
+ uno::Reference< ucb::XContentIdentifier > xNewChildId
+ = new ::ucbhelper::ContentIdentifier( m_xSMgr, aNewChildURL );
+
+ if ( !xChild->exchangeIdentity( xNewChildId ) )
+ return sal_False;
+
+ ++it;
+ }
+ return sal_True;
+ }
+
+ return sal_False;
+}
+
+uno::Sequence< uno::Any > Content::setPropertyValues(
+ const uno::Sequence< beans::PropertyValue >& rValues,
+ const uno::Reference< ucb::XCommandEnvironment >& xEnv )
+{
+ GError *pError=NULL;
+ GFileInfo *pNewInfo=NULL;
+ GFileInfo *pInfo = getGFileInfo(xEnv, &pError);
+ if (pInfo)
+ pNewInfo = g_file_info_dup(pInfo);
+ else
+ {
+ if (!mbTransient)
+ ucbhelper::cancelCommandExecution(mapGIOError(pError), xEnv);
+ else
+ {
+ if (pError)
+ g_error_free(pError);
+ pNewInfo = g_file_info_new();
+ }
+ }
+
+ sal_Int32 nCount = rValues.getLength();
+
+ beans::PropertyChangeEvent aEvent;
+ aEvent.Source = static_cast< cppu::OWeakObject * >( this );
+ aEvent.Further = sal_False;
+ aEvent.PropertyHandle = -1;
+
+ sal_Int32 nChanged = 0, nTitlePos = -1;
+ const char *newName = NULL;
+ uno::Sequence< beans::PropertyChangeEvent > aChanges(nCount);
+
+ uno::Sequence< uno::Any > aRet( nCount );
+ const beans::PropertyValue* pValues = rValues.getConstArray();
+ for ( sal_Int32 n = 0; n < nCount; ++n )
+ {
+ const beans::PropertyValue& rValue = pValues[ n ];
+#ifdef DEBUG
+ g_warning("Set prop '%s'", rtl::OUStringToOString(rValue.Name, RTL_TEXTENCODING_UTF8).getStr());
+#endif
+ if ( rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) ||
+ rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "MediaType" ) ) ||
+ rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) ||
+ rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) ||
+ rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Size" ) ) ||
+ rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "CreatableContentsInfo" ) ) )
+ {
+ aRet[ n ] <<= getReadOnlyException( static_cast< cppu::OWeakObject * >(this) );
+ }
+ else if ( rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Title" ) ) )
+ {
+ rtl::OUString aNewTitle;
+ if (!( rValue.Value >>= aNewTitle ))
+ {
+ aRet[ n ] <<= beans::IllegalTypeException
+ ( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Property value has wrong type!")),
+ static_cast< cppu::OWeakObject * >( this ) );
+ continue;
+ }
+
+ if ( aNewTitle.getLength() <= 0 )
+ {
+ aRet[ n ] <<= lang::IllegalArgumentException
+ ( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Empty title not allowed!")),
+ static_cast< cppu::OWeakObject * >( this ), -1 );
+ continue;
+
+ }
+
+ rtl::OString sNewTitle = OUStringToOString(aNewTitle, RTL_TEXTENCODING_UTF8);
+ newName = sNewTitle.getStr();
+ const char *oldName = g_file_info_get_name( pInfo);
+
+ if (!newName || !oldName || strcmp(newName, oldName))
+ {
+#ifdef DEBUG
+ g_warning ("Set new name to '%s'", newName);
+#endif
+
+ aEvent.PropertyName = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Title"));
+ if (oldName)
+ aEvent.OldValue = uno::makeAny(rtl::OUString(oldName, strlen(oldName), RTL_TEXTENCODING_UTF8));
+ aEvent.NewValue = uno::makeAny(aNewTitle);
+ aChanges.getArray()[ nChanged ] = aEvent;
+ nTitlePos = nChanged++;
+
+ g_file_info_set_name(pNewInfo, newName);
+ }
+ }
+ else
+ {
+#ifdef DEBUG
+ fprintf(stderr, "Unknown property %s\n", rtl::OUStringToOString(rValue.Name, RTL_TEXTENCODING_UTF8).getStr());
+#endif
+ aRet[ n ] <<= getReadOnlyException( static_cast< cppu::OWeakObject * >(this) );
+ //TODO
+ }
+ }
+
+ if (nChanged)
+ {
+ bool bOk = true;
+ if (!mbTransient)
+ {
+ if ((bOk = doSetFileInfo(pNewInfo)))
+ {
+ for (sal_Int32 i = 0; i < nChanged; ++i)
+ aRet[ i ] <<= getBadArgExcept();
+ }
+ }
+
+ if (bOk)
+ {
+ if (nTitlePos > -1)
+ {
+ rtl::OUString aNewURL = getParentURL();
+ aNewURL += rtl::OUString( newName, strlen(newName), RTL_TEXTENCODING_UTF8 );
+ uno::Reference< ucb::XContentIdentifier > xNewId
+ = new ::ucbhelper::ContentIdentifier( m_xSMgr, aNewURL );
+
+ if (!exchangeIdentity( xNewId ) )
+ {
+ aRet[ nTitlePos ] <<= uno::Exception
+ ( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Exchange failed!")),
+ static_cast< cppu::OWeakObject * >( this ) );
+ }
+ }
+
+ if (!mbTransient) //Discard and refetch
+ {
+ g_object_unref(mpInfo);
+ mpInfo = NULL;
+ }
+
+ if (mpInfo)
+ {
+ g_file_info_copy_into(pNewInfo, mpInfo);
+ g_object_unref(pNewInfo);
+ }
+ else
+ mpInfo = pNewInfo;
+
+ if (mpFile) //Discard and refetch
+ {
+ g_object_unref(mpFile);
+ mpFile = NULL;
+ }
+ }
+
+ aChanges.realloc( nChanged );
+ notifyPropertiesChange( aChanges );
+ }
+
+ return aRet;
+}
+
+bool Content::doSetFileInfo(GFileInfo *pNewInfo)
+{
+ g_assert (!mbTransient);
+
+ bool bOk = true;
+ GFile *pFile = getGFile();
+ if(!g_file_set_attributes_from_info(pFile, pNewInfo, G_FILE_QUERY_INFO_NONE, NULL, NULL))
+ bOk = false;
+ return bOk;
+}
+
+const int TRANSFER_BUFFER_SIZE = 65536;
+
+void Content::copyData( uno::Reference< io::XInputStream > xIn,
+ uno::Reference< io::XOutputStream > xOut )
+{
+ uno::Sequence< sal_Int8 > theData( TRANSFER_BUFFER_SIZE );
+
+ g_return_if_fail( xIn.is() && xOut.is() );
+
+ while ( xIn->readBytes( theData, TRANSFER_BUFFER_SIZE ) > 0 )
+ xOut->writeBytes( theData );
+
+ xOut->closeOutput();
+}
+
+sal_Bool Content::feedSink( uno::Reference< uno::XInterface > xSink,
+ const uno::Reference< ucb::XCommandEnvironment >& /*xEnv*/ )
+{
+ if ( !xSink.is() )
+ return sal_False;
+
+ uno::Reference< io::XOutputStream > xOut = uno::Reference< io::XOutputStream >(xSink, uno::UNO_QUERY );
+ uno::Reference< io::XActiveDataSink > xDataSink = uno::Reference< io::XActiveDataSink >(xSink, uno::UNO_QUERY );
+
+ if ( !xOut.is() && !xDataSink.is() )
+ return sal_False;
+
+ GError *pError=NULL;
+ GFileInputStream *pStream = g_file_read(getGFile(), NULL, &pError);
+ if (!pStream)
+ convertToException(pError, static_cast< cppu::OWeakObject * >(this));
+
+ uno::Reference< io::XInputStream > xIn = new ::gio::InputStream(pStream);
+ if ( !xIn.is() )
+ return sal_False;
+
+ if ( xOut.is() )
+ copyData( xIn, xOut );
+
+ if ( xDataSink.is() )
+ xDataSink->setInputStream( xIn );
+
+ return sal_True;
+}
+
+uno::Any Content::open(const ucb::OpenCommandArgument2 & rOpenCommand,
+ const uno::Reference< ucb::XCommandEnvironment > & xEnv )
+ throw( uno::Exception )
+{
+ bool bIsFolder = isFolder(xEnv);
+
+ if (!g_file_query_exists(getGFile(), NULL))
+ {
+ uno::Sequence< uno::Any > aArgs( 1 );
+ aArgs[ 0 ] <<= m_xIdentifier->getContentIdentifier();
+ uno::Any aErr = uno::makeAny(
+ ucb::InteractiveAugmentedIOException(rtl::OUString(), static_cast< cppu::OWeakObject * >( this ),
+ task::InteractionClassification_ERROR,
+ bIsFolder ? ucb::IOErrorCode_NOT_EXISTING_PATH : ucb::IOErrorCode_NOT_EXISTING, aArgs)
+ );
+
+ ucbhelper::cancelCommandExecution(aErr, xEnv);
+ }
+
+ uno::Any aRet;
+
+ sal_Bool bOpenFolder = (
+ ( rOpenCommand.Mode == ucb::OpenMode::ALL ) ||
+ ( rOpenCommand.Mode == ucb::OpenMode::FOLDERS ) ||
+ ( rOpenCommand.Mode == ucb::OpenMode::DOCUMENTS )
+ );
+
+ if ( bOpenFolder && bIsFolder )
+ {
+ uno::Reference< ucb::XDynamicResultSet > xSet
+ = new DynamicResultSet(m_xSMgr, this, rOpenCommand, xEnv );
+ aRet <<= xSet;
+ }
+ else if ( rOpenCommand.Sink.is() )
+ {
+ if (
+ ( rOpenCommand.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE ) ||
+ ( rOpenCommand.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE )
+ )
+ {
+ ucbhelper::cancelCommandExecution(
+ uno::makeAny ( ucb::UnsupportedOpenModeException
+ ( rtl::OUString(), static_cast< cppu::OWeakObject * >( this ),
+ sal_Int16( rOpenCommand.Mode ) ) ),
+ xEnv );
+ }
+
+ if ( !feedSink( rOpenCommand.Sink, xEnv ) )
+ {
+ // Note: rOpenCommand.Sink may contain an XStream
+ // implementation. Support for this type of
+ // sink is optional...
+#ifdef DEBUG
+ g_warning ("Failed to load data from '%s'",
+ rtl::OUStringToOString(m_xIdentifier->getContentIdentifier(), RTL_TEXTENCODING_UTF8).getStr());
+#endif
+
+ ucbhelper::cancelCommandExecution(
+ uno::makeAny (ucb::UnsupportedDataSinkException
+ ( rtl::OUString(), static_cast< cppu::OWeakObject * >( this ),
+ rOpenCommand.Sink ) ),
+ xEnv );
+ }
+ }
+ else
+ g_warning ("Open falling through ...");
+ return aRet;
+}
+
+uno::Any SAL_CALL Content::execute(
+ const ucb::Command& aCommand,
+ sal_Int32 /*CommandId*/,
+ const uno::Reference< ucb::XCommandEnvironment >& xEnv )
+ throw( uno::Exception,
+ ucb::CommandAbortedException,
+ uno::RuntimeException )
+{
+#ifdef DEBUG
+ fprintf(stderr, "Content::execute %s\n", rtl::OUStringToOString(aCommand.Name, RTL_TEXTENCODING_UTF8).getStr());
+#endif
+ uno::Any aRet;
+
+ if (aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "getPropertyValues" ) ))
+ {
+ uno::Sequence< beans::Property > Properties;
+ if ( !( aCommand.Argument >>= Properties ) )
+ ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv );
+ aRet <<= getPropertyValues( Properties, xEnv );
+ }
+ else if (aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "getPropertySetInfo" ) ))
+ aRet <<= getPropertySetInfo( xEnv, sal_False );
+ else if (aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "getCommandInfo" ) ))
+ aRet <<= getCommandInfo( xEnv, sal_False );
+ else if (aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "open" ) ))
+ {
+ ucb::OpenCommandArgument2 aOpenCommand;
+ if ( !( aCommand.Argument >>= aOpenCommand ) )
+ ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv );
+ aRet = open( aOpenCommand, xEnv );
+ }
+ else if (aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "transfer" ) ))
+ {
+ ucb::TransferInfo transferArgs;
+ if ( !( aCommand.Argument >>= transferArgs ) )
+ ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv );
+ transfer( transferArgs, xEnv );
+ }
+ else if (aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "setPropertyValues" ) ))
+ {
+ uno::Sequence< beans::PropertyValue > aProperties;
+ if ( !( aCommand.Argument >>= aProperties ) || !aProperties.getLength() )
+ ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv );
+ aRet <<= setPropertyValues( aProperties, xEnv );
+ }
+ else if (aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "createNewContent" ) )
+ && isFolder( xEnv ) )
+ {
+ ucb::ContentInfo arg;
+ if ( !( aCommand.Argument >>= arg ) )
+ ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv );
+ aRet <<= createNewContent( arg );
+ }
+ else if (aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "insert" ) ))
+ {
+ ucb::InsertCommandArgument arg;
+ if ( !( aCommand.Argument >>= arg ) )
+ ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv );
+ insert( arg.Data, arg.ReplaceExisting, xEnv );
+ }
+ else if (aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "delete" ) ))
+ {
+ sal_Bool bDeletePhysical = sal_False;
+ aCommand.Argument >>= bDeletePhysical;
+
+ //If no delete physical, try and trashcan it, if that doesn't work go
+ //ahead and try and delete it anyway
+ if (!bDeletePhysical && !g_file_trash(getGFile(), NULL, NULL))
+ bDeletePhysical = true;
+
+ if (bDeletePhysical)
+ {
+ GError *pError = NULL;
+ if (!g_file_delete( getGFile(), NULL, &pError))
+ ucbhelper::cancelCommandExecution(mapGIOError(pError), xEnv);
+ }
+
+ destroy( bDeletePhysical );
+ }
+ else
+ {
+#ifdef DEBUG
+ fprintf(stderr, "UNKNOWN COMMAND\n");
+ //TODO
+#endif
+
+ ucbhelper::cancelCommandExecution
+ ( uno::makeAny( ucb::UnsupportedCommandException
+ ( rtl::OUString(),
+ static_cast< cppu::OWeakObject * >( this ) ) ),
+ xEnv );
+ }
+
+ return aRet;
+}
+
+void Content::destroy( sal_Bool bDeletePhysical )
+ throw( uno::Exception )
+{
+ uno::Reference< ucb::XContent > xThis = this;
+
+ deleted();
+
+ ::gio::Content::ContentRefList aChildren;
+ queryChildren( aChildren );
+
+ ContentRefList::const_iterator it = aChildren.begin();
+ ContentRefList::const_iterator end = aChildren.end();
+
+ while ( it != end )
+ {
+ (*it)->destroy( bDeletePhysical );
+ ++it;
+ }
+}
+
+void Content::insert(const uno::Reference< io::XInputStream > &xInputStream,
+ sal_Bool bReplaceExisting, const uno::Reference< ucb::XCommandEnvironment > &xEnv )
+ throw( uno::Exception )
+{
+ GError *pError = NULL;
+ GFileInfo *pInfo = getGFileInfo(xEnv);
+
+ if ( g_file_info_has_attribute(pInfo, G_FILE_ATTRIBUTE_STANDARD_TYPE) &&
+ g_file_info_get_file_type(pInfo) == G_FILE_TYPE_DIRECTORY )
+ {
+#ifdef DEBUG
+ g_warning ("Make directory");
+#endif
+ if( !g_file_make_directory( getGFile(), NULL, &pError))
+ ucbhelper::cancelCommandExecution(mapGIOError(pError), xEnv);
+ return;
+ }
+
+ if ( !xInputStream.is() )
+ {
+ ucbhelper::cancelCommandExecution( uno::makeAny
+ ( ucb::MissingInputStreamException
+ ( rtl::OUString(), static_cast< cppu::OWeakObject * >( this ) ) ),
+ xEnv );
+ }
+
+ GFileOutputStream* pOutStream = NULL;
+ if ( bReplaceExisting )
+ {
+ if (!(pOutStream = g_file_replace(getGFile(), NULL, false, G_FILE_CREATE_PRIVATE, NULL, &pError)))
+ ucbhelper::cancelCommandExecution(mapGIOError(pError), xEnv);
+ }
+ else
+ {
+ if (!(pOutStream = g_file_create (getGFile(), G_FILE_CREATE_PRIVATE, NULL, &pError)))
+ ucbhelper::cancelCommandExecution(mapGIOError(pError), xEnv);
+ }
+
+ uno::Reference < io::XOutputStream > xOutput = new ::gio::OutputStream(pOutStream);
+ copyData( xInputStream, xOutput );
+
+ if (mbTransient)
+ {
+ mbTransient = sal_False;
+ inserted();
+ }
+}
+
+void Content::transfer( const ucb::TransferInfo& aTransferInfo, const uno::Reference< ucb::XCommandEnvironment >& xEnv )
+ throw( uno::Exception )
+{
+ rtl::OUString sDest = m_xIdentifier->getContentIdentifier();
+ if (aTransferInfo.NewTitle.getLength())
+ sDest += aTransferInfo.NewTitle;
+ else
+ sDest += rtl::OUString::createFromAscii(g_file_get_basename(getGFile()));
+
+ GFile *pDest = g_file_new_for_uri(rtl::OUStringToOString(sDest, RTL_TEXTENCODING_UTF8).getStr());
+ GFile *pSource = g_file_new_for_uri(rtl::OUStringToOString(aTransferInfo.SourceURL, RTL_TEXTENCODING_UTF8).getStr());
+
+ gboolean bSuccess = false;
+ GError *pError = NULL;
+ if (aTransferInfo.MoveData)
+ bSuccess = g_file_move(pSource, pDest, G_FILE_COPY_OVERWRITE, NULL, NULL, 0, &pError);
+ else
+ bSuccess = g_file_copy(pSource, pDest, G_FILE_COPY_OVERWRITE, NULL, NULL, 0, &pError);
+ g_object_unref(pSource);
+ g_object_unref(pDest);
+ if (!bSuccess)
+ ucbhelper::cancelCommandExecution(mapGIOError(pError), xEnv);
+}
+
+uno::Sequence< ucb::ContentInfo > Content::queryCreatableContentsInfo(
+ const uno::Reference< ucb::XCommandEnvironment >& xEnv)
+ throw( uno::RuntimeException )
+{
+ if ( isFolder( xEnv ) )
+ {
+ uno::Sequence< ucb::ContentInfo > seq(2);
+
+ // Minimum set of props we really need
+ uno::Sequence< beans::Property > props( 1 );
+ props[0] = beans::Property(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Title")),
+ -1,
+ getCppuType( static_cast< rtl::OUString* >( 0 ) ),
+ beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND );
+
+ // file
+ seq[0].Type = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( GIO_FILE_TYPE ));
+ seq[0].Attributes = ( ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM |
+ ucb::ContentInfoAttribute::KIND_DOCUMENT );
+ seq[0].Properties = props;
+
+ // folder
+ seq[1].Type = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( GIO_FOLDER_TYPE ));
+ seq[1].Attributes = ucb::ContentInfoAttribute::KIND_FOLDER;
+ seq[1].Properties = props;
+
+ return seq;
+ }
+ else
+ {
+ return uno::Sequence< ucb::ContentInfo >();
+ }
+}
+
+uno::Sequence< ucb::ContentInfo > SAL_CALL Content::queryCreatableContentsInfo()
+ throw( uno::RuntimeException )
+{
+ return queryCreatableContentsInfo( uno::Reference< ucb::XCommandEnvironment >() );
+}
+
+uno::Reference< ucb::XContent >
+ SAL_CALL Content::createNewContent( const ucb::ContentInfo& Info )
+ throw( uno::RuntimeException )
+{
+ bool create_document;
+ const char *name;
+
+ if ( Info.Type.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( GIO_FILE_TYPE ) ) )
+ create_document = true;
+ else if ( Info.Type.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( GIO_FOLDER_TYPE ) ) )
+ create_document = false;
+ else
+ {
+#ifdef DEBUG
+ g_warning( "Failed to create new content '%s'", rtl::OUStringToOString(Info.Type,
+ RTL_TEXTENCODING_UTF8).getStr() );
+#endif
+ return uno::Reference< ucb::XContent >();
+ }
+
+#ifdef DEBUG
+ g_warning( "createNewContent (%d)", (int) create_document );
+#endif
+
+ rtl::OUString aURL = m_xIdentifier->getContentIdentifier();
+
+ if ( ( aURL.lastIndexOf( '/' ) + 1 ) != aURL.getLength() )
+ aURL += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/"));
+
+ name = create_document ? "[New_Content]" : "[New_Collection]";
+ aURL += rtl::OUString::createFromAscii( name );
+
+ uno::Reference< ucb::XContentIdentifier > xId(new ::ucbhelper::ContentIdentifier(m_xSMgr, aURL));
+
+ try
+ {
+ return new ::gio::Content( m_xSMgr, m_pProvider, xId, !create_document );
+ } catch ( ucb::ContentCreationException & )
+ {
+ return uno::Reference< ucb::XContent >();
+ }
+}
+
+uno::Sequence< uno::Type > SAL_CALL Content::getTypes()
+ throw( uno::RuntimeException )
+{
+ if ( isFolder( uno::Reference< ucb::XCommandEnvironment >() ) )
+ {
+ static cppu::OTypeCollection aFolderCollection
+ (CPPU_TYPE_REF( lang::XTypeProvider ),
+ CPPU_TYPE_REF( lang::XServiceInfo ),
+ CPPU_TYPE_REF( lang::XComponent ),
+ CPPU_TYPE_REF( ucb::XContent ),
+ CPPU_TYPE_REF( ucb::XCommandProcessor ),
+ CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
+ CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
+ CPPU_TYPE_REF( beans::XPropertyContainer ),
+ CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
+ CPPU_TYPE_REF( container::XChild ),
+ CPPU_TYPE_REF( ucb::XContentCreator ) );
+ return aFolderCollection.getTypes();
+ }
+ else
+ {
+ static cppu::OTypeCollection aFileCollection
+ (CPPU_TYPE_REF( lang::XTypeProvider ),
+ CPPU_TYPE_REF( lang::XServiceInfo ),
+ CPPU_TYPE_REF( lang::XComponent ),
+ CPPU_TYPE_REF( ucb::XContent ),
+ CPPU_TYPE_REF( ucb::XCommandProcessor ),
+ CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
+ CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
+ CPPU_TYPE_REF( beans::XPropertyContainer ),
+ CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
+ CPPU_TYPE_REF( container::XChild ) );
+
+ return aFileCollection.getTypes();
+ }
+}
+
+uno::Sequence< beans::Property > Content::getProperties(
+ const uno::Reference< ucb::XCommandEnvironment > & /*xEnv*/ )
+{
+ static const beans::Property aGenericProperties[] =
+ {
+ beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ),
+ -1, getCppuBooleanType(),
+ beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
+ beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ),
+ -1, getCppuBooleanType(),
+ beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
+ beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ),
+ -1, getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
+ beans::PropertyAttribute::BOUND ),
+ beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsReadOnly" ) ),
+ -1, getCppuBooleanType(),
+ beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
+ beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DateCreated" ) ),
+ -1, getCppuType( static_cast< const util::DateTime * >( 0 ) ),
+ beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
+ beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DateModified" ) ),
+ -1, getCppuType( static_cast< const util::DateTime * >( 0 ) ),
+ beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
+ beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Size" ) ),
+ -1, getCppuType( static_cast< const sal_Int64 * >( 0 ) ),
+ beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
+ beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsVolume" ) ),
+ -1, getCppuBooleanType(),
+ beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
+ beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsCompactDisc" ) ),
+ -1, getCppuBooleanType(),
+ beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
+ beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsRemoveable" ) ),
+ -1, getCppuBooleanType(),
+ beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
+ beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsHidden" ) ),
+ -1, getCppuBooleanType(),
+ beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
+ beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CreatableContentsInfo" ) ),
+ -1, getCppuType( static_cast< const uno::Sequence< ucb::ContentInfo > * >( 0 ) ),
+ beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY )
+ };
+
+ const int nProps = SAL_N_ELEMENTS(aGenericProperties);
+ return uno::Sequence< beans::Property > ( aGenericProperties, nProps );
+}
+
+uno::Sequence< ucb::CommandInfo > Content::getCommands( const uno::Reference< ucb::XCommandEnvironment > & xEnv)
+{
+ static ucb::CommandInfo aCommandInfoTable[] =
+ {
+ // Required commands
+ ucb::CommandInfo
+ ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ),
+ -1, getCppuVoidType() ),
+ ucb::CommandInfo
+ ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ),
+ -1, getCppuVoidType() ),
+ ucb::CommandInfo
+ ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ),
+ -1, getCppuType( static_cast<uno::Sequence< beans::Property > * >( 0 ) ) ),
+ ucb::CommandInfo
+ ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ),
+ -1, getCppuType( static_cast<uno::Sequence< beans::PropertyValue > * >( 0 ) ) ),
+
+ // Optional standard commands
+ ucb::CommandInfo
+ ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "delete" ) ),
+ -1, getCppuBooleanType() ),
+ ucb::CommandInfo
+ ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert" ) ),
+ -1, getCppuType( static_cast<ucb::InsertCommandArgument * >( 0 ) ) ),
+ ucb::CommandInfo
+ ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ),
+ -1, getCppuType( static_cast<ucb::OpenCommandArgument2 * >( 0 ) ) ),
+
+ // Folder Only, omitted if not a folder
+ ucb::CommandInfo
+ ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "transfer" ) ),
+ -1, getCppuType( static_cast<ucb::TransferInfo * >( 0 ) ) ),
+ ucb::CommandInfo
+ ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "createNewContent" ) ),
+ -1, getCppuType( static_cast<ucb::ContentInfo * >( 0 ) ) )
+ };
+
+ const int nProps = SAL_N_ELEMENTS(aCommandInfoTable);
+ return uno::Sequence< ucb::CommandInfo >(aCommandInfoTable, isFolder(xEnv) ? nProps : nProps - 2);
+}
+
+XTYPEPROVIDER_COMMON_IMPL( Content );
+
+void SAL_CALL Content::acquire() throw()
+{
+ ContentImplHelper::acquire();
+}
+
+void SAL_CALL Content::release() throw()
+{
+ ContentImplHelper::release();
+}
+
+uno::Any SAL_CALL Content::queryInterface( const uno::Type & rType ) throw ( uno::RuntimeException )
+{
+ uno::Any aRet = cppu::queryInterface( rType, static_cast< ucb::XContentCreator * >( this ) );
+ return aRet.hasValue() ? aRet : ContentImplHelper::queryInterface(rType);
+}
+
+rtl::OUString SAL_CALL Content::getImplementationName() throw( uno::RuntimeException )
+{
+ return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.GIOContent"));
+}
+
+uno::Sequence< rtl::OUString > SAL_CALL Content::getSupportedServiceNames()
+ throw( uno::RuntimeException )
+{
+ uno::Sequence< rtl::OUString > aSNS( 1 );
+ aSNS.getArray()[ 0 ] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ucb.GIOContent"));
+ return aSNS;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */