| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| #include <string.h> |
| #include <unistd.h> |
| #include <sys/types.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::createFromAscii( GIO_FOLDER_TYPE ) |
| : rtl::OUString::createFromAscii( 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::createFromAscii( "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::createFromAscii( "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::createFromAscii( "/" ); |
| |
| 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::createFromAscii( "Property value has wrong type!" ), |
| static_cast< cppu::OWeakObject * >( this ) ); |
| continue; |
| } |
| |
| if ( aNewTitle.getLength() <= 0 ) |
| { |
| aRet[ n ] <<= lang::IllegalArgumentException |
| ( rtl::OUString::createFromAscii( "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::createFromAscii( "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::createFromAscii( "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::createFromAscii( "Title" ), |
| -1, |
| getCppuType( static_cast< rtl::OUString* >( 0 ) ), |
| beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND ); |
| |
| // file |
| seq[0].Type = rtl::OUString::createFromAscii( 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::createFromAscii( 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::createFromAscii( "/" ); |
| |
| 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 = sizeof (aGenericProperties) / sizeof (aGenericProperties[0]); |
| 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 = sizeof (aCommandInfoTable) / sizeof (aCommandInfoTable[0]); |
| 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::createFromAscii("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::createFromAscii("com.sun.star.ucb.GIOContent" ); |
| return aSNS; |
| } |
| |
| } |