| /************************************************************** |
| * |
| * 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. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_ucb.hxx" |
| |
| /************************************************************************** |
| TODO |
| ************************************************************************** |
| |
| *************************************************************************/ |
| #include <osl/diagnose.h> |
| #include "odma_contentprops.hxx" |
| #include <com/sun/star/ucb/XDynamicResultSet.hpp> |
| #include <com/sun/star/beans/PropertyAttribute.hpp> |
| #include <com/sun/star/beans/XPropertyAccess.hpp> |
| #include <com/sun/star/lang/IllegalAccessException.hpp> |
| #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp> |
| #include <com/sun/star/sdbc/XRow.hpp> |
| #include <com/sun/star/io/XOutputStream.hpp> |
| #include <com/sun/star/io/XActiveDataSink.hpp> |
| #include <com/sun/star/ucb/OpenCommandArgument2.hpp> |
| #include <com/sun/star/ucb/OpenMode.hpp> |
| #include <com/sun/star/ucb/XCommandInfo.hpp> |
| #include <com/sun/star/ucb/XPersistentPropertySet.hpp> |
| #include <ucbhelper/contentidentifier.hxx> |
| #include <ucbhelper/propertyvalueset.hxx> |
| #include <ucbhelper/cancelcommandexecution.hxx> |
| #include <com/sun/star/ucb/UnsupportedOpenModeException.hpp> |
| #include <com/sun/star/ucb/MissingInputStreamException.hpp> |
| #include <com/sun/star/ucb/InsertCommandArgument.hpp> |
| #include <com/sun/star/ucb/MissingPropertiesException.hpp> |
| #include <com/sun/star/io/XActiveDataStreamer.hpp> |
| #include <com/sun/star/ucb/TransferInfo.hpp> |
| #include <com/sun/star/ucb/NameClash.hpp> |
| #include "odma_content.hxx" |
| #include "odma_provider.hxx" |
| #include "odma_resultset.hxx" |
| #include "odma_inputstream.hxx" |
| #include <ucbhelper/content.hxx> |
| #include <com/sun/star/uno/Exception.hpp> |
| #include <rtl/ref.hxx> |
| #include <osl/file.hxx> |
| |
| using namespace com::sun::star; |
| using namespace odma; |
| |
| //========================================================================= |
| //========================================================================= |
| // |
| // Content Implementation. |
| // |
| //========================================================================= |
| //========================================================================= |
| |
| Content::Content( const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, |
| ContentProvider* pProvider, |
| const uno::Reference< ucb::XContentIdentifier >& Identifier, |
| const ::rtl::Reference<ContentProperties>& _rProps) |
| : ContentImplHelper( rxSMgr, pProvider, Identifier ) |
| ,m_aProps(_rProps) |
| ,m_pProvider(pProvider) |
| ,m_pContent(NULL) |
| { |
| OSL_ENSURE(m_aProps.is(),"No valid ContentPropeties!"); |
| } |
| |
| //========================================================================= |
| // virtual |
| Content::~Content() |
| { |
| delete m_pContent; |
| } |
| |
| //========================================================================= |
| // |
| // XInterface methods. |
| // |
| //========================================================================= |
| |
| // virtual |
| void SAL_CALL Content::acquire() throw() |
| { |
| ContentImplHelper::acquire(); |
| } |
| |
| //========================================================================= |
| // virtual |
| void SAL_CALL Content::release() throw() |
| { |
| ContentImplHelper::release(); |
| } |
| |
| //========================================================================= |
| // virtual |
| uno::Any SAL_CALL Content::queryInterface( const uno::Type & rType ) |
| throw ( uno::RuntimeException ) |
| { |
| uno::Any aRet; |
| |
| // @@@ Add support for additional interfaces. |
| #if 0 |
| aRet = cppu::queryInterface( rType, |
| static_cast< yyy::Xxxxxxxxx * >( this ) ); |
| #endif |
| |
| return aRet.hasValue() ? aRet : ContentImplHelper::queryInterface( rType ); |
| } |
| |
| //========================================================================= |
| // |
| // XTypeProvider methods. |
| // |
| //========================================================================= |
| |
| XTYPEPROVIDER_COMMON_IMPL( Content ); |
| |
| //========================================================================= |
| // virtual |
| uno::Sequence< uno::Type > SAL_CALL Content::getTypes() |
| throw( uno::RuntimeException ) |
| { |
| // @@@ Add own interfaces. |
| |
| static cppu::OTypeCollection* pCollection = 0; |
| |
| if ( !pCollection ) |
| { |
| osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); |
| if ( !pCollection ) |
| { |
| static cppu::OTypeCollection aCollection( |
| 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 ) ); |
| pCollection = &aCollection; |
| } |
| } |
| |
| return (*pCollection).getTypes(); |
| } |
| |
| //========================================================================= |
| // |
| // XServiceInfo methods. |
| // |
| //========================================================================= |
| |
| // virtual |
| rtl::OUString SAL_CALL Content::getImplementationName() |
| throw( uno::RuntimeException ) |
| { |
| // @@@ Adjust implementation name. Keep the prefix "com.sun.star.comp."! |
| return rtl::OUString::createFromAscii( "com.sun.star.comp.odma.Content" ); |
| } |
| |
| //========================================================================= |
| // virtual |
| uno::Sequence< rtl::OUString > SAL_CALL Content::getSupportedServiceNames() |
| throw( uno::RuntimeException ) |
| { |
| // @@@ Adjust macro name. |
| uno::Sequence< rtl::OUString > aSNS( 1 ); |
| aSNS.getArray()[ 0 ] |
| = rtl::OUString::createFromAscii( ODMA_CONTENT_SERVICE_NAME ); |
| return aSNS; |
| } |
| |
| //========================================================================= |
| // |
| // XContent methods. |
| // |
| //========================================================================= |
| |
| // virtual |
| rtl::OUString SAL_CALL Content::getContentType() |
| throw( uno::RuntimeException ) |
| { |
| // @@@ Adjust macro name ( def in odma_provider.hxx ). |
| return rtl::OUString::createFromAscii( ODMA_CONTENT_TYPE ); |
| } |
| |
| //========================================================================= |
| // |
| // XCommandProcessor methods. |
| // |
| //========================================================================= |
| |
| // virtual |
| uno::Any SAL_CALL Content::execute( |
| const ucb::Command& aCommand, |
| sal_Int32 /*CommandId*/, |
| const uno::Reference< ucb::XCommandEnvironment >& Environment ) |
| throw( uno::Exception, |
| ucb::CommandAbortedException, |
| uno::RuntimeException ) |
| { |
| uno::Any aRet; |
| |
| if ( aCommand.Name.equalsAsciiL( |
| RTL_CONSTASCII_STRINGPARAM( "getPropertyValues" ) ) ) |
| { |
| ////////////////////////////////////////////////////////////////// |
| // getPropertyValues |
| ////////////////////////////////////////////////////////////////// |
| |
| uno::Sequence< beans::Property > Properties; |
| if ( !( aCommand.Argument >>= Properties ) ) |
| { |
| OSL_ENSURE( sal_False, "Wrong argument type!" ); |
| ucbhelper::cancelCommandExecution( |
| uno::makeAny( lang::IllegalArgumentException( |
| rtl::OUString(), |
| static_cast< cppu::OWeakObject * >( this ), |
| -1 ) ), |
| Environment ); |
| // Unreachable |
| } |
| |
| aRet <<= getPropertyValues( Properties, Environment ); |
| } |
| else if ( aCommand.Name.equalsAsciiL( |
| RTL_CONSTASCII_STRINGPARAM( "setPropertyValues" ) ) ) |
| { |
| ////////////////////////////////////////////////////////////////// |
| // setPropertyValues |
| ////////////////////////////////////////////////////////////////// |
| |
| uno::Sequence< beans::PropertyValue > aProperties; |
| if ( !( aCommand.Argument >>= aProperties ) ) |
| { |
| OSL_ENSURE( sal_False, "Wrong argument type!" ); |
| ucbhelper::cancelCommandExecution( |
| uno::makeAny( lang::IllegalArgumentException( |
| rtl::OUString(), |
| static_cast< cppu::OWeakObject * >( this ), |
| -1 ) ), |
| Environment ); |
| // Unreachable |
| } |
| |
| if ( !aProperties.getLength() ) |
| { |
| OSL_ENSURE( sal_False, "No properties!" ); |
| ucbhelper::cancelCommandExecution( |
| uno::makeAny( lang::IllegalArgumentException( |
| rtl::OUString(), |
| static_cast< cppu::OWeakObject * >( this ), |
| -1 ) ), |
| Environment ); |
| // Unreachable |
| } |
| |
| aRet <<= setPropertyValues( aProperties, Environment ); |
| } |
| else if ( aCommand.Name.equalsAsciiL( |
| RTL_CONSTASCII_STRINGPARAM( "getPropertySetInfo" ) ) ) |
| { |
| ////////////////////////////////////////////////////////////////// |
| // getPropertySetInfo |
| ////////////////////////////////////////////////////////////////// |
| |
| // Note: Implemented by base class. |
| aRet <<= getPropertySetInfo( Environment ); |
| } |
| else if ( aCommand.Name.equalsAsciiL( |
| RTL_CONSTASCII_STRINGPARAM( "getCommandInfo" ) ) ) |
| { |
| ////////////////////////////////////////////////////////////////// |
| // getCommandInfo |
| ////////////////////////////////////////////////////////////////// |
| |
| // Note: Implemented by base class. |
| aRet <<= getCommandInfo( Environment ); |
| } |
| else if ( aCommand.Name.equalsAsciiL( |
| RTL_CONSTASCII_STRINGPARAM( "open" ) ) ) |
| { |
| ucb::OpenCommandArgument2 aOpenCommand; |
| if ( !( aCommand.Argument >>= aOpenCommand ) ) |
| { |
| OSL_ENSURE( sal_False, "Wrong argument type!" ); |
| ucbhelper::cancelCommandExecution( |
| uno::makeAny( lang::IllegalArgumentException( |
| rtl::OUString(), |
| static_cast< cppu::OWeakObject * >( this ), |
| -1 ) ), |
| Environment ); |
| // Unreachable |
| } |
| |
| sal_Bool bOpenFolder = |
| ( ( aOpenCommand.Mode == ucb::OpenMode::ALL ) || |
| ( aOpenCommand.Mode == ucb::OpenMode::FOLDERS ) || |
| ( aOpenCommand.Mode == ucb::OpenMode::DOCUMENTS ) ); |
| |
| if ( bOpenFolder) |
| { |
| // open as folder - return result set |
| |
| uno::Reference< ucb::XDynamicResultSet > xSet |
| = new DynamicResultSet( m_xSMgr, |
| this, |
| aOpenCommand, |
| Environment ); |
| aRet <<= xSet; |
| } |
| |
| if ( aOpenCommand.Sink.is() ) |
| { |
| // Open document - supply document data stream. |
| |
| // Check open mode |
| if ( ( aOpenCommand.Mode |
| == ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE ) || |
| ( aOpenCommand.Mode |
| == ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE ) ) |
| { |
| // Unsupported. |
| ucbhelper::cancelCommandExecution( |
| uno::makeAny( ucb::UnsupportedOpenModeException( |
| rtl::OUString(), |
| static_cast< cppu::OWeakObject * >( this ), |
| sal_Int16( aOpenCommand.Mode ) ) ), |
| Environment ); |
| // Unreachable |
| } |
| |
| |
| rtl::OUString aURL = m_xIdentifier->getContentIdentifier(); |
| rtl::OUString sFileURL = openDoc(); |
| delete m_pContent; |
| m_pContent = new ::ucbhelper::Content(sFileURL,NULL); |
| if(!m_pContent->isDocument()) |
| { |
| rtl::OUString sErrorMsg(RTL_CONSTASCII_USTRINGPARAM("File: ")); |
| sErrorMsg += sFileURL; |
| sErrorMsg += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" could not be found.")); |
| ucbhelper::cancelCommandExecution( |
| uno::makeAny( io::IOException( |
| sErrorMsg, |
| static_cast< cppu::OWeakObject * >( this )) ), |
| Environment ); |
| } |
| |
| uno::Reference< io::XOutputStream > xOut |
| = uno::Reference< io::XOutputStream >( |
| aOpenCommand.Sink, uno::UNO_QUERY ); |
| if ( xOut.is() ) |
| { |
| // @@@ PUSH: write data into xOut |
| m_pContent->openStream(xOut); |
| } |
| else |
| { |
| uno::Reference< io::XActiveDataSink > xDataSink |
| = uno::Reference< io::XActiveDataSink >( |
| aOpenCommand.Sink, uno::UNO_QUERY ); |
| if ( xDataSink.is() ) |
| { |
| // @@@ PULL: wait for client read |
| uno::Reference< io::XInputStream > xIn; |
| try |
| { |
| xIn = m_pContent->openStream(); |
| } |
| catch(uno::Exception&) |
| { |
| OSL_ENSURE(0,"Exception occured while creating the file content!"); |
| } |
| xDataSink->setInputStream( xIn ); |
| } |
| else |
| { |
| uno::Reference< io::XActiveDataStreamer > activeDataStreamer( aOpenCommand.Sink,uno::UNO_QUERY ); |
| if(activeDataStreamer.is()) |
| { |
| activeDataStreamer->setStream(new OOdmaStream(m_pContent,getContentProvider(),m_aProps)); |
| m_pContent = NULL; // don't delete here because the stream is now the owner |
| } |
| else |
| { |
| // Note: aOpenCommand.Sink may contain an XStream |
| // implementation. Support for this type of |
| // sink is optional... |
| ucbhelper::cancelCommandExecution( |
| uno::makeAny( ucb::UnsupportedDataSinkException( |
| rtl::OUString(), |
| static_cast< cppu::OWeakObject * >( this ), |
| aOpenCommand.Sink ) ), |
| Environment ); |
| // Unreachable |
| } |
| } |
| } |
| } |
| } |
| else if ( aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "close" ) ) ) |
| { |
| getContentProvider()->closeDocument(m_aProps->m_sDocumentId); |
| } |
| else if ( aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "delete" ) ) ) |
| { |
| ////////////////////////////////////////////////////////////////// |
| // delete |
| ////////////////////////////////////////////////////////////////// |
| |
| // Remove own and all children's Additional Core Properties. |
| removeAdditionalPropertySet( sal_True ); |
| // Remove own and all childrens(!) persistent data. |
| if(!getContentProvider()->deleteDocument(m_aProps)) |
| ucbhelper::cancelCommandExecution( |
| uno::makeAny( lang::IllegalArgumentException( |
| rtl::OUString(), |
| static_cast< cppu::OWeakObject * >( this ), |
| -1 ) ), |
| Environment ); |
| } |
| else if ( aCommand.Name.equalsAsciiL( |
| RTL_CONSTASCII_STRINGPARAM( "insert" ) ) ) |
| { |
| ////////////////////////////////////////////////////////////////// |
| // insert |
| ////////////////////////////////////////////////////////////////// |
| |
| ucb::InsertCommandArgument arg; |
| if ( !( aCommand.Argument >>= arg ) ) |
| { |
| OSL_ENSURE( sal_False, "Wrong argument type!" ); |
| ucbhelper::cancelCommandExecution( |
| uno::makeAny( lang::IllegalArgumentException( |
| rtl::OUString(), |
| static_cast< cppu::OWeakObject * >( this ), |
| -1 ) ), |
| Environment ); |
| // Unreachable |
| } |
| |
| insert( arg.Data, arg.ReplaceExisting, Environment ); |
| } |
| else if( ! aCommand.Name.compareToAscii( "transfer" ) ) |
| { |
| ucb::TransferInfo aTransferInfo; |
| if( ! ( aCommand.Argument >>= aTransferInfo ) ) |
| { |
| OSL_ENSURE( sal_False, "Wrong argument type!" ); |
| ucbhelper::cancelCommandExecution( |
| uno::makeAny( lang::IllegalArgumentException( |
| rtl::OUString(), |
| static_cast< cppu::OWeakObject * >( this ), |
| -1 ) ), |
| Environment ); |
| // Unreachable |
| } |
| ::rtl::Reference<ContentProperties> aProp = m_aProps; |
| if(aProp->m_bIsFolder) |
| { |
| aProp = getContentProvider()->getContentPropertyWithTitle(aTransferInfo.NewTitle); |
| if(!aProp.is()) |
| aProp = getContentProvider()->getContentPropertyWithSavedAsName(aTransferInfo.NewTitle); |
| sal_Bool bError = !aProp.is(); |
| if(bError) |
| { |
| sal_Char* pExtension = NULL; |
| ::rtl::OString sExt; |
| sal_Int32 nPos = aTransferInfo.NewTitle.lastIndexOf('.'); |
| if(nPos != -1) |
| { |
| sExt = ::rtl::OUStringToOString(aTransferInfo.NewTitle.copy(nPos+1),RTL_TEXTENCODING_ASCII_US); |
| if(sExt.equalsIgnoreAsciiCase("txt")) |
| pExtension = ODM_FORMAT_TEXT; |
| else if(sExt.equalsIgnoreAsciiCase("rtf")) |
| pExtension = ODM_FORMAT_RTF; |
| else if(sExt.equalsIgnoreAsciiCase("ps")) |
| pExtension = ODM_FORMAT_PS; |
| else |
| pExtension = const_cast<sal_Char*>(sExt.getStr()); |
| } |
| else |
| pExtension = ODM_FORMAT_TEXT; |
| |
| sal_Char* lpszNewDocId = new sal_Char[ODM_DOCID_MAX]; |
| void *pData = NULL; |
| DWORD dwFlags = ODM_SILENT; |
| ODMSTATUS odm = NODMSaveAsEx(ContentProvider::getHandle(), |
| NULL, // means it is saved the first time |
| lpszNewDocId, |
| pExtension, |
| NULL, // no callback function here |
| pData, |
| &dwFlags); |
| |
| // check if we have to call the DMS dialog |
| if(odm == ODM_E_USERINT) |
| { |
| dwFlags = 0; |
| odm = NODMSaveAsEx(ContentProvider::getHandle(), |
| NULL, // means it is saved the first time |
| lpszNewDocId, |
| pExtension, |
| NULL, // no callback function here |
| pData, |
| &dwFlags); |
| } |
| bError = odm != ODM_SUCCESS; |
| if(!bError) |
| { |
| aProp = new ContentProperties(); |
| aProp->m_sDocumentId = ::rtl::OString(lpszNewDocId); |
| aProp->m_sContentType = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ODMA_CONTENT_TYPE)); |
| aProp->m_sSavedAsName = aTransferInfo.NewTitle; |
| getContentProvider()->append(aProp); |
| |
| // now set the title |
| WORD nDocInfo = ODM_NAME; |
| ::rtl::OUString sFileName = aTransferInfo.NewTitle; |
| sal_Int32 nIndex = aTransferInfo.NewTitle.lastIndexOf( sal_Unicode('.') ); |
| if(nIndex != -1) |
| sFileName = aTransferInfo.NewTitle.copy(0,nIndex); |
| |
| ::rtl::OString sDocInfoValue = ::rtl::OUStringToOString(sFileName,RTL_TEXTENCODING_ASCII_US); |
| odm = NODMSetDocInfo( ContentProvider::getHandle(), |
| lpszNewDocId, |
| nDocInfo, |
| const_cast<sal_Char*>(sDocInfoValue.getStr()) |
| ); |
| |
| } |
| else if ( odm == ODM_E_CANCEL) |
| NODMActivate(ContentProvider::getHandle(), |
| ODM_DELETE, |
| lpszNewDocId); |
| |
| delete [] lpszNewDocId; |
| } |
| if(bError) |
| ucbhelper::cancelCommandExecution( |
| uno::makeAny( lang::IllegalArgumentException( |
| rtl::OUString(), |
| static_cast< cppu::OWeakObject * >( this ), |
| -1 ) ), |
| Environment ); |
| } |
| rtl::OUString sFileURL = ContentProvider::openDoc(aProp); |
| |
| sal_Int32 nLastIndex = sFileURL.lastIndexOf( sal_Unicode('/') ); |
| ::ucbhelper::Content aContent(sFileURL.copy(0,nLastIndex),NULL); |
| // aTransferInfo.NameClash = ucb::NameClash::OVERWRITE; |
| aTransferInfo.NewTitle = sFileURL.copy( 1 + nLastIndex ); |
| aContent.executeCommand(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("transfer")),uno::makeAny(aTransferInfo)); |
| getContentProvider()->saveDocument(aProp->m_sDocumentId); |
| } |
| else |
| { |
| ////////////////////////////////////////////////////////////////// |
| // Unsupported command |
| ////////////////////////////////////////////////////////////////// |
| |
| OSL_ENSURE( sal_False, "Content::execute - unsupported command!" ); |
| |
| ucbhelper::cancelCommandExecution( |
| uno::makeAny( ucb::UnsupportedCommandException( |
| rtl::OUString(), |
| static_cast< cppu::OWeakObject * >( this ) ) ), |
| Environment ); |
| // Unreachable |
| } |
| |
| return aRet; |
| } |
| |
| //========================================================================= |
| // virtual |
| void SAL_CALL Content::abort( sal_Int32 /*CommandId*/ ) |
| throw( uno::RuntimeException ) |
| { |
| // @@@ Implement logic to abort running commands, if this makes |
| // sense for your content. |
| } |
| |
| //========================================================================= |
| // |
| // Non-interface methods. |
| // |
| //========================================================================= |
| |
| // virtual |
| ::rtl::OUString Content::getParentURL() |
| { |
| ::rtl::OUString sURL = m_xIdentifier->getContentIdentifier(); |
| |
| // @@@ Extract URL of parent from aURL and return it... |
| static ::rtl::OUString sScheme1(RTL_CONSTASCII_USTRINGPARAM(ODMA_URL_SCHEME ODMA_URL_SHORT "/")); |
| static ::rtl::OUString sScheme2(RTL_CONSTASCII_USTRINGPARAM(ODMA_URL_SCHEME ODMA_URL_SHORT)); |
| if(sURL == sScheme1 || sURL == sScheme2) |
| sURL = ::rtl::OUString(); |
| else |
| sURL = sScheme1; |
| |
| return sURL; |
| } |
| |
| //========================================================================= |
| // static |
| uno::Reference< sdbc::XRow > Content::getPropertyValues( |
| const uno::Reference< lang::XMultiServiceFactory >& rSMgr, |
| const uno::Sequence< beans::Property >& rProperties, |
| const rtl::Reference<ContentProperties>& rData, |
| const rtl::Reference< ::ucbhelper::ContentProviderImplHelper >& rProvider, |
| const rtl::OUString& rContentId ) |
| { |
| // Note: Empty sequence means "get values of all supported properties". |
| |
| rtl::Reference< ::ucbhelper::PropertyValueSet > xRow |
| = new ::ucbhelper::PropertyValueSet( rSMgr ); |
| |
| sal_Int32 nCount = rProperties.getLength(); |
| if ( nCount ) |
| { |
| uno::Reference< beans::XPropertySet > xAdditionalPropSet; |
| sal_Bool bTriedToGetAdditonalPropSet = sal_False; |
| |
| const beans::Property* pProps = rProperties.getConstArray(); |
| for ( sal_Int32 n = 0; n < nCount; ++n ) |
| { |
| const beans::Property& rProp = pProps[ n ]; |
| |
| // Process Core properties. |
| |
| if ( rProp.Name.equalsAsciiL( |
| RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) ) |
| { |
| xRow->appendString ( rProp, rData->m_sContentType ); |
| } |
| else if ( rProp.Name.equalsAsciiL( |
| RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) |
| { |
| xRow->appendString ( rProp, rData->m_sTitle ); |
| } |
| else if ( rProp.Name.equalsAsciiL( |
| RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) ) |
| { |
| xRow->appendBoolean( rProp, rData->m_bIsDocument ); |
| } |
| else if ( rProp.Name.equalsAsciiL( |
| RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) ) |
| { |
| xRow->appendBoolean( rProp, rData->m_bIsFolder ); |
| } |
| else if ( rProp.Name.equalsAsciiL( |
| RTL_CONSTASCII_STRINGPARAM( "DateCreated" ) ) ) |
| { |
| xRow->appendTimestamp( rProp, rData->m_aDateCreated ); |
| } |
| else if ( rProp.Name.equalsAsciiL( |
| RTL_CONSTASCII_STRINGPARAM( "DateModified" ) ) ) |
| { |
| xRow->appendTimestamp( rProp, rData->m_aDateModified ); |
| } |
| else if ( rProp.Name.equalsAsciiL( |
| RTL_CONSTASCII_STRINGPARAM( "IsReadOnly" ) ) ) |
| { |
| xRow->appendBoolean( rProp, rData->m_bIsReadOnly ); |
| } |
| else if ( rProp.Name.equalsAsciiL( |
| RTL_CONSTASCII_STRINGPARAM( "Author" ) ) ) |
| { |
| xRow->appendString ( rProp, rData->m_sAuthor ); |
| } |
| else if ( rProp.Name.equalsAsciiL( |
| RTL_CONSTASCII_STRINGPARAM( "Subject" ) ) ) |
| { |
| xRow->appendString ( rProp, rData->m_sSubject ); |
| } |
| else if ( rProp.Name.equalsAsciiL( |
| RTL_CONSTASCII_STRINGPARAM( "Keywords" ) ) ) |
| { |
| xRow->appendString ( rProp, rData->m_sKeywords ); |
| } |
| else |
| { |
| // @@@ Note: If your data source supports adding/removing |
| // properties, you should implement the interface |
| // XPropertyContainer by yourself and supply your own |
| // logic here. The base class uses the service |
| // "com.sun.star.ucb.Store" to maintain Additional Core |
| // properties. But using server functionality is preferred! |
| |
| // Not a Core Property! Maybe it's an Additional Core Property?! |
| |
| if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() ) |
| { |
| xAdditionalPropSet |
| = uno::Reference< beans::XPropertySet >( |
| rProvider->getAdditionalPropertySet( rContentId, |
| sal_False ), |
| uno::UNO_QUERY ); |
| bTriedToGetAdditonalPropSet = sal_True; |
| } |
| |
| if ( xAdditionalPropSet.is() ) |
| { |
| if ( !xRow->appendPropertySetValue( |
| xAdditionalPropSet, |
| rProp ) ) |
| { |
| // Append empty entry. |
| xRow->appendVoid( rProp ); |
| } |
| } |
| else |
| { |
| // Append empty entry. |
| xRow->appendVoid( rProp ); |
| } |
| } |
| } |
| } |
| else |
| { |
| // Append all Core Properties. |
| xRow->appendString ( |
| beans::Property( rtl::OUString::createFromAscii( "ContentType" ), |
| -1, |
| getCppuType( static_cast< const rtl::OUString * >( 0 ) ), |
| beans::PropertyAttribute::BOUND |
| | beans::PropertyAttribute::READONLY ), |
| rData->m_sContentType ); |
| xRow->appendString ( |
| beans::Property( rtl::OUString::createFromAscii( "Title" ), |
| -1, |
| getCppuType( static_cast< const rtl::OUString * >( 0 ) ), |
| beans::PropertyAttribute::BOUND ), |
| rData->m_sTitle ); |
| xRow->appendBoolean( |
| beans::Property( rtl::OUString::createFromAscii( "IsDocument" ), |
| -1, |
| getCppuBooleanType(), |
| beans::PropertyAttribute::BOUND |
| | beans::PropertyAttribute::READONLY ), |
| rData->m_bIsDocument ); |
| xRow->appendBoolean( |
| beans::Property( rtl::OUString::createFromAscii( "IsFolder" ), |
| -1, |
| getCppuBooleanType(), |
| beans::PropertyAttribute::BOUND |
| | beans::PropertyAttribute::READONLY ), |
| rData->m_bIsFolder ); |
| |
| // @@@ Append other properties supported directly. |
| xRow->appendTimestamp( |
| beans::Property( rtl::OUString::createFromAscii( "DateCreated" ), |
| -1, |
| getCppuType(static_cast< const util::DateTime * >( 0 ) ), |
| beans::PropertyAttribute::BOUND |
| | beans::PropertyAttribute::READONLY ), |
| rData->m_aDateCreated ); |
| xRow->appendTimestamp( |
| beans::Property( rtl::OUString::createFromAscii( "DateModified" ), |
| -1, |
| getCppuType(static_cast< const util::DateTime * >( 0 ) ), |
| beans::PropertyAttribute::BOUND |
| | beans::PropertyAttribute::READONLY ), |
| rData->m_aDateModified ); |
| xRow->appendBoolean( |
| beans::Property( rtl::OUString::createFromAscii( "IsReadOnly" ), |
| -1, |
| getCppuBooleanType(), |
| beans::PropertyAttribute::BOUND |
| | beans::PropertyAttribute::READONLY ), |
| rData->m_bIsReadOnly ); |
| xRow->appendString ( |
| beans::Property( rtl::OUString::createFromAscii( "Author" ), |
| -1, |
| getCppuType( static_cast< const rtl::OUString * >( 0 ) ), |
| beans::PropertyAttribute::BOUND ), |
| rData->m_sAuthor ); |
| xRow->appendString ( |
| beans::Property( rtl::OUString::createFromAscii( "Subject" ), |
| -1, |
| getCppuType( static_cast< const rtl::OUString * >( 0 ) ), |
| beans::PropertyAttribute::BOUND ), |
| rData->m_sSubject ); |
| xRow->appendString ( |
| beans::Property( rtl::OUString::createFromAscii( "Keywords" ), |
| -1, |
| getCppuType( static_cast< const rtl::OUString * >( 0 ) ), |
| beans::PropertyAttribute::BOUND ), |
| rData->m_sKeywords ); |
| |
| // @@@ Note: If your data source supports adding/removing |
| // properties, you should implement the interface |
| // XPropertyContainer by yourself and supply your own |
| // logic here. The base class uses the service |
| // "com.sun.star.ucb.Store" to maintain Additional Core |
| // properties. But using server functionality is preferred! |
| |
| // Append all Additional Core Properties. |
| |
| uno::Reference< beans::XPropertySet > xSet( |
| rProvider->getAdditionalPropertySet( rContentId, sal_False ), |
| uno::UNO_QUERY ); |
| xRow->appendPropertySet( xSet ); |
| } |
| |
| 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*/ ) |
| { |
| osl::Guard< osl::Mutex > aGuard( m_aMutex ); |
| return getPropertyValues( m_xSMgr, |
| rProperties, |
| m_aProps, |
| rtl::Reference< |
| ::ucbhelper::ContentProviderImplHelper >( |
| m_xProvider.get() ), |
| m_xIdentifier->getContentIdentifier() ); |
| } |
| |
| //========================================================================= |
| uno::Sequence< uno::Any > Content::setPropertyValues( |
| const uno::Sequence< beans::PropertyValue >& rValues, |
| const uno::Reference< ucb::XCommandEnvironment >& /*xEnv*/ ) |
| { |
| osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); |
| |
| uno::Sequence< uno::Any > aRet( rValues.getLength() ); |
| uno::Sequence< beans::PropertyChangeEvent > aChanges( rValues.getLength() ); |
| sal_Int32 nChanged = 0; |
| |
| beans::PropertyChangeEvent aEvent; |
| aEvent.Source = static_cast< cppu::OWeakObject * >( this ); |
| aEvent.Further = sal_False; |
| // aEvent.PropertyName = |
| aEvent.PropertyHandle = -1; |
| // aEvent.OldValue = |
| // aEvent.NewValue = |
| |
| const beans::PropertyValue* pValues = rValues.getConstArray(); |
| sal_Int32 nCount = rValues.getLength(); |
| |
| uno::Reference< ucb::XPersistentPropertySet > xAdditionalPropSet; |
| sal_Bool bTriedToGetAdditonalPropSet = sal_False; |
| |
| for ( sal_Int32 n = 0; n < nCount; ++n ) |
| { |
| const beans::PropertyValue& rValue = pValues[ n ]; |
| |
| if ( rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) |
| { |
| changePropertyValue(rValue,n,m_aProps->m_sTitle,nChanged,aRet,aChanges); |
| } |
| else if ( rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "Author") ) ) |
| { |
| changePropertyValue(rValue,n,m_aProps->m_sAuthor,nChanged,aRet,aChanges); |
| } |
| else if ( rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "Keywords") ) ) |
| { |
| changePropertyValue(rValue,n,m_aProps->m_sKeywords,nChanged,aRet,aChanges); |
| } |
| else if ( rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "Subject") ) ) |
| { |
| changePropertyValue(rValue,n,m_aProps->m_sSubject,nChanged,aRet,aChanges); |
| } |
| else if ( rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) || |
| rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) || |
| rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) || |
| rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "DateCreated" ) ) || |
| rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "DateModified" ) ) || |
| rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "IsReadOnly" ) ) ) |
| { |
| // Read-only property! |
| aRet[ n ] <<= lang::IllegalAccessException( |
| rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( |
| "Property is read-only!") ), |
| static_cast< cppu::OWeakObject * >( this ) ); |
| } |
| else |
| { |
| // @@@ Note: If your data source supports adding/removing |
| // properties, you should implement the interface |
| // XPropertyContainer by yourself and supply your own |
| // logic here. The base class uses the service |
| // "com.sun.star.ucb.Store" to maintain Additional Core |
| // properties. But using server functionality is preferred! |
| |
| // Not a Core Property! Maybe it's an Additional Core Property?! |
| |
| if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() ) |
| { |
| xAdditionalPropSet = getAdditionalPropertySet( sal_False ); |
| bTriedToGetAdditonalPropSet = sal_True; |
| } |
| |
| if ( xAdditionalPropSet.is() ) |
| { |
| try |
| { |
| uno::Any aOldValue |
| = xAdditionalPropSet->getPropertyValue( rValue.Name ); |
| if ( aOldValue != rValue.Value ) |
| { |
| xAdditionalPropSet->setPropertyValue( |
| rValue.Name, rValue.Value ); |
| |
| aEvent.PropertyName = rValue.Name; |
| aEvent.OldValue = aOldValue; |
| aEvent.NewValue = rValue.Value; |
| |
| aChanges.getArray()[ nChanged ] = aEvent; |
| nChanged++; |
| } |
| else |
| { |
| // Old value equals new value. No error! |
| } |
| } |
| catch ( beans::UnknownPropertyException const & e ) |
| { |
| aRet[ n ] <<= e; |
| } |
| catch ( lang::WrappedTargetException const & e ) |
| { |
| aRet[ n ] <<= e; |
| } |
| catch ( beans::PropertyVetoException const & e ) |
| { |
| aRet[ n ] <<= e; |
| } |
| catch ( lang::IllegalArgumentException const & e ) |
| { |
| aRet[ n ] <<= e; |
| } |
| } |
| else |
| { |
| aRet[ n ] <<= uno::Exception( |
| rtl::OUString::createFromAscii( |
| "No property set for storing the value!" ), |
| static_cast< cppu::OWeakObject * >( this ) ); |
| } |
| } |
| } |
| |
| if ( nChanged > 0 ) |
| { |
| // @@@ Save changes. |
| // storeData(); |
| |
| aGuard.clear(); |
| aChanges.realloc( nChanged ); |
| notifyPropertiesChange( aChanges ); |
| } |
| |
| return aRet; |
| } |
| |
| #if 0 |
| //========================================================================= |
| void Content::queryChildren( ContentRefList& rChildren ) |
| { |
| // @@@ Adapt method to your URL scheme... |
| |
| // 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 ); |
| |
| OUString aURL = m_xIdentifier->getContentIdentifier(); |
| sal_Int32 nPos = aURL.lastIndexOf( '/' ); |
| |
| if ( nPos != ( aURL.getLength() - 1 ) ) |
| { |
| // No trailing slash found. Append. |
| aURL += 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); |
| 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( |
| ContentRef( |
| static_cast< Content * >( xChild.get() ) ) ); |
| } |
| } |
| ++it; |
| } |
| } |
| #endif |
| //========================================================================= |
| void Content::insert( |
| const uno::Reference< io::XInputStream > & xInputStream, |
| sal_Bool bReplaceExisting, |
| const uno::Reference< ucb::XCommandEnvironment >& Environment ) |
| throw( uno::Exception ) |
| { |
| osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); |
| |
| // Check, if all required properties were set. |
| if ( !m_aProps->m_sTitle.getLength()) |
| { |
| OSL_ENSURE( sal_False, "Content::insert - property value missing!" ); |
| |
| uno::Sequence< rtl::OUString > aProps( 1 ); |
| aProps[ 0 ] = rtl::OUString::createFromAscii( "zzzz" ); |
| ucbhelper::cancelCommandExecution( |
| uno::makeAny( ucb::MissingPropertiesException( |
| rtl::OUString(), |
| static_cast< cppu::OWeakObject * >( this ), |
| aProps ) ), |
| Environment ); |
| // Unreachable |
| } |
| |
| if ( !xInputStream.is() ) |
| { |
| OSL_ENSURE( sal_False, "Content::insert - No data stream!" ); |
| |
| ucbhelper::cancelCommandExecution( |
| uno::makeAny( ucb::MissingInputStreamException( |
| rtl::OUString(), |
| static_cast< cppu::OWeakObject * >( this ) ) ), |
| Environment ); |
| // Unreachable |
| } |
| |
| // Assemble new content identifier... |
| |
| // uno::Reference< ucb::XContentIdentifier > xId = ...; |
| |
| // Fail, if a resource with given id already exists. |
| if ( !bReplaceExisting ) // && hasData( m_xIdentifier ) ) |
| { |
| ucbhelper::cancelCommandExecution( |
| uno::makeAny( ucb::UnsupportedCommandException( |
| rtl::OUString(), |
| static_cast< cppu::OWeakObject * >( this ) ) ), |
| Environment ); |
| // ucbhelper::cancelCommandExecution( |
| // ucb::IOErrorCode_ALREADY_EXISTING, |
| // Environment, |
| // uno::makeAny(static_cast< cppu::OWeakObject * >( this )) |
| // ); |
| // Unreachable |
| } |
| |
| // m_xIdentifier = xId; |
| |
| // @@@ |
| // storeData(); |
| |
| aGuard.clear(); |
| inserted(); |
| } |
| #if 0 |
| //========================================================================= |
| void Content::destroy( sal_Bool bDeletePhysical ) |
| throw( uno::Exception ) |
| { |
| // @@@ take care about bDeletePhysical -> trashcan support |
| |
| uno::Reference< ucb::XContent > xThis = this; |
| |
| deleted(); |
| |
| osl::Guard< osl::Mutex > aGuard( m_aMutex ); |
| |
| // Process instanciated children... |
| |
| ContentRefList aChildren; |
| queryChildren( aChildren ); |
| |
| ContentRefList::const_iterator it = aChildren.begin(); |
| ContentRefList::const_iterator end = aChildren.end(); |
| |
| while ( it != end ) |
| { |
| (*it)->destroy( bDeletePhysical ); |
| ++it; |
| } |
| } |
| #endif |
| |
| // ----------------------------------------------------------------------------- |
| ::rtl::OUString Content::openDoc() |
| { |
| OSL_ENSURE(m_aProps.is(),"No valid content properties!"); |
| return ContentProvider::openDoc(m_aProps); |
| } |
| // ----------------------------------------------------------------------------- |
| void Content::changePropertyValue(const beans::PropertyValue& _rValue, |
| sal_Int32 _rnCurrentPos, |
| ::rtl::OUString& _rsMemberValue, |
| sal_Int32& _rnChanged, |
| uno::Sequence< uno::Any >& _rRet, |
| uno::Sequence< beans::PropertyChangeEvent >& _rChanges) throw (beans::IllegalTypeException) |
| { |
| rtl::OUString sNewValue; |
| sal_Bool bError = sal_False; |
| if ( _rValue.Value >>= sNewValue ) |
| { |
| if ( sNewValue != _rsMemberValue ) |
| { |
| osl::Guard< osl::Mutex > aGuard( m_aMutex ); |
| // first we have to check if we could change the property inside the DMS |
| ::rtl::OString sDocInfoValue = ::rtl::OUStringToOString(sNewValue,RTL_TEXTENCODING_ASCII_US); |
| WORD nDocInfo = 0; |
| if(&_rsMemberValue == &m_aProps->m_sTitle) |
| nDocInfo = ODM_TITLETEXT; |
| else if(&_rsMemberValue == &m_aProps->m_sAuthor) |
| nDocInfo = ODM_AUTHOR; |
| else if(&_rsMemberValue == &m_aProps->m_sSubject) |
| nDocInfo = ODM_SUBJECT; |
| else if(&_rsMemberValue == &m_aProps->m_sKeywords) |
| nDocInfo = ODM_KEYWORDS; |
| else |
| bError = sal_True; |
| |
| if(!bError) |
| { |
| ODMSTATUS odm = NODMSetDocInfo( ContentProvider::getHandle(), |
| const_cast<sal_Char*>(m_aProps->m_sDocumentId.getStr()), |
| nDocInfo, |
| const_cast<sal_Char*>(sDocInfoValue.getStr()) |
| ); |
| if(odm == ODM_SUCCESS) |
| { |
| beans::PropertyChangeEvent aEvent; |
| aEvent.Source = static_cast< cppu::OWeakObject * >( this ); |
| aEvent.Further = sal_False; |
| aEvent.PropertyHandle = -1; |
| aEvent.PropertyName = _rValue.Name; |
| aEvent.OldValue = uno::makeAny( _rsMemberValue ); |
| aEvent.NewValue = uno::makeAny( sNewValue ); |
| |
| _rChanges.getArray()[ _rnChanged ] = aEvent; |
| |
| _rsMemberValue = sNewValue; |
| ++_rnChanged; |
| } |
| } |
| } |
| else |
| { |
| // Old value equals new value. No error! |
| } |
| } |
| else |
| bError = sal_True; |
| |
| if(bError) |
| { |
| _rRet[ _rnCurrentPos ] <<= beans::IllegalTypeException( |
| rtl::OUString::createFromAscii( |
| "Property value has wrong type!" ), |
| static_cast< cppu::OWeakObject * >( this ) ); |
| } |
| } |
| // ----------------------------------------------------------------------------- |
| |