1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include <com/sun/star/beans/PropertyAttribute.hpp>
11 #include <com/sun/star/beans/PropertyValue.hpp>
12 #include <com/sun/star/beans/XPropertySetInfo.hpp>
13 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
14 #include <com/sun/star/task/XInteractionHandler.hpp>
15 #include <com/sun/star/ucb/XCommandInfo.hpp>
16 #include <com/sun/star/ucb/XDynamicResultSet.hpp>
17 #include <com/sun/star/ucb/XProgressHandler.hpp>
19 #include <comphelper/processfactory.hxx>
20 #include <rtl/uri.hxx>
21 #include <ucbhelper/cancelcommandexecution.hxx>
22 #include <ucbhelper/commandenvironment.hxx>
23 #include <ucbhelper/contentidentifier.hxx>
24 #include <ucbhelper/propertyvalueset.hxx>
25 #include <ucbhelper/proxydecider.hxx>
27 #include "auth_provider.hxx"
28 #include "cmis_content.hxx"
29 #include "cmis_provider.hxx"
30 #include "cmis_repo_content.hxx"
31 #include "cmis_resultset.hxx"
33 #define OUSTR_TO_STDSTR(s) string( OUStringToOString( s, RTL_TEXTENCODING_UTF8 ).getStr() )
34 #define STD_TO_OUSTR( str ) OUString( str.c_str(), str.length( ), RTL_TEXTENCODING_UTF8 )
36 using namespace com::sun::star
;
41 RepoContent::RepoContent( const uno::Reference
< uno::XComponentContext
>& rxContext
,
42 ContentProvider
*pProvider
, const uno::Reference
< ucb::XContentIdentifier
>& Identifier
,
43 list
< libcmis::RepositoryPtr
> aRepos
)
44 throw ( ucb::ContentCreationException
)
45 : ContentImplHelper( rxContext
, pProvider
, Identifier
),
46 m_pProvider( pProvider
),
47 m_aURL( Identifier
->getContentIdentifier( ) ),
49 m_aRepositories( aRepos
)
51 // Split the URL into bits
52 OUString sURL
= m_xIdentifier
->getContentIdentifier( );
53 SAL_INFO( "cmisucp", "RepoContent::RepoContent() " << sURL
);
55 m_sRepositoryId
= m_aURL
.getObjectPath( );
56 if ( m_sRepositoryId
[0] == '/' )
57 m_sRepositoryId
= m_sRepositoryId
.copy( 1 );
61 RepoContent::~RepoContent()
65 uno::Any
RepoContent::getBadArgExcept()
67 return uno::makeAny( lang::IllegalArgumentException(
68 OUString("Wrong argument type!"),
69 static_cast< cppu::OWeakObject
* >( this ), -1) );
72 uno::Reference
< sdbc::XRow
> RepoContent::getPropertyValues(
73 const uno::Sequence
< beans::Property
>& rProperties
,
74 const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
76 rtl::Reference
< ::ucbhelper::PropertyValueSet
> xRow
= new ::ucbhelper::PropertyValueSet( m_xContext
);
79 const beans::Property
* pProps
;
81 nProps
= rProperties
.getLength();
82 pProps
= rProperties
.getConstArray();
84 for( sal_Int32 n
= 0; n
< nProps
; ++n
)
86 const beans::Property
& rProp
= pProps
[ n
];
90 if ( rProp
.Name
== "IsDocument" )
92 xRow
->appendBoolean( rProp
, sal_False
);
94 else if ( rProp
.Name
== "IsFolder" )
96 xRow
->appendBoolean( rProp
, sal_True
);
98 else if ( rProp
.Name
== "Title" )
100 xRow
->appendString( rProp
, STD_TO_OUSTR( getRepository( xEnv
)->getName( ) ) );
102 else if ( rProp
.Name
== "IsReadOnly" )
104 xRow
->appendBoolean( rProp
, sal_True
);
108 xRow
->appendVoid( rProp
);
109 SAL_INFO( "cmisucp", "Looking for unsupported property " << rProp
.Name
);
112 catch (const libcmis::Exception
&)
114 xRow
->appendVoid( rProp
);
118 return uno::Reference
< sdbc::XRow
>( xRow
.get() );
121 void RepoContent::getRepositories( const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
123 // Set the proxy if needed. We are doing that all times as the proxy data shouldn't be cached.
124 ucbhelper::InternetProxyDecider
aProxyDecider( m_xContext
);
125 INetURLObject
aBindingUrl( m_aURL
.getBindingUrl( ) );
126 const ucbhelper::InternetProxyServer
& rProxy
= aProxyDecider
.getProxy(
127 INetURLObject::GetScheme( aBindingUrl
.GetProtocol( ) ), aBindingUrl
.GetHost(), aBindingUrl
.GetPort() );
128 OUString sProxy
= rProxy
.aName
;
129 if ( rProxy
.nPort
> 0 )
130 sProxy
+= ":" + OUString::valueOf( rProxy
.nPort
);
131 libcmis::SessionFactory::setProxySettings( OUSTR_TO_STDSTR( sProxy
), string(), string(), string() );
133 if ( m_aRepositories
.empty() )
135 // Get the auth credentials
136 AuthProvider
authProvider( xEnv
, m_xIdentifier
->getContentIdentifier( ), m_aURL
.getBindingUrl( ) );
138 string rUsername
= OUSTR_TO_STDSTR( m_aURL
.getUsername( ) );
139 string rPassword
= OUSTR_TO_STDSTR( m_aURL
.getPassword( ) );
140 if ( authProvider
.authenticationQuery( rUsername
, rPassword
) )
144 m_aRepositories
= libcmis::SessionFactory::getRepositories(
145 OUSTR_TO_STDSTR( m_aURL
.getBindingUrl( ) ), rUsername
, rPassword
);
147 catch (const libcmis::Exception
&)
153 // Throw user cancelled exception
154 ucbhelper::cancelCommandExecution(
155 ucb::IOErrorCode_ABORT
,
156 uno::Sequence
< uno::Any
>( 0 ),
158 OUString::createFromAscii( "Authentication cancelled" ) );
163 libcmis::RepositoryPtr
RepoContent::getRepository( const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
165 // Ensure we have the repositories extracted
166 getRepositories( xEnv
);
168 libcmis::RepositoryPtr repo
;
170 if ( !m_sRepositoryId
.isEmpty() )
172 for ( list
< libcmis::RepositoryPtr
>::iterator it
= m_aRepositories
.begin( );
173 it
!= m_aRepositories
.end( ) && NULL
== repo
.get( ); ++it
)
175 if ( STD_TO_OUSTR( ( *it
)->getId( ) ) == m_sRepositoryId
)
182 uno::Sequence
< beans::Property
> RepoContent::getProperties(
183 const uno::Reference
< ucb::XCommandEnvironment
> & /*xEnv*/ )
185 static const beans::Property aGenericProperties
[] =
187 beans::Property( OUString( "IsDocument" ),
188 -1, getCppuBooleanType(),
189 beans::PropertyAttribute::BOUND
| beans::PropertyAttribute::READONLY
),
190 beans::Property( OUString( "IsFolder" ),
191 -1, getCppuBooleanType(),
192 beans::PropertyAttribute::BOUND
| beans::PropertyAttribute::READONLY
),
193 beans::Property( OUString( "Title" ),
194 -1, getCppuType( static_cast< const OUString
* >( 0 ) ),
195 beans::PropertyAttribute::BOUND
),
196 beans::Property( OUString( "IsReadOnly" ),
197 -1, getCppuBooleanType(),
198 beans::PropertyAttribute::BOUND
| beans::PropertyAttribute::READONLY
),
201 const int nProps
= SAL_N_ELEMENTS(aGenericProperties
);
202 return uno::Sequence
< beans::Property
> ( aGenericProperties
, nProps
);
205 uno::Sequence
< ucb::CommandInfo
> RepoContent::getCommands(
206 const uno::Reference
< ucb::XCommandEnvironment
> & /*xEnv*/ )
208 static ucb::CommandInfo aCommandInfoTable
[] =
212 ( OUString( "getCommandInfo" ),
213 -1, getCppuVoidType() ),
215 ( OUString( "getPropertySetInfo" ),
216 -1, getCppuVoidType() ),
218 ( OUString( "getPropertyValues" ),
219 -1, getCppuType( static_cast<uno::Sequence
< beans::Property
> * >( 0 ) ) ),
221 ( OUString( "setPropertyValues" ),
222 -1, getCppuType( static_cast<uno::Sequence
< beans::PropertyValue
> * >( 0 ) ) ),
224 // Optional standard commands
226 ( OUString( "open" ),
227 -1, getCppuType( static_cast<ucb::OpenCommandArgument2
* >( 0 ) ) ),
230 const int nProps
= SAL_N_ELEMENTS(aCommandInfoTable
);
231 return uno::Sequence
< ucb::CommandInfo
>(aCommandInfoTable
, nProps
);
234 OUString
RepoContent::getParentURL( )
238 SAL_INFO( "cmisucp", "RepoContent::getParentURL()" );
245 XTYPEPROVIDER_COMMON_IMPL( RepoContent
);
247 void SAL_CALL
RepoContent::acquire() throw()
249 ContentImplHelper::acquire();
252 void SAL_CALL
RepoContent::release() throw()
254 ContentImplHelper::release();
257 uno::Any SAL_CALL
RepoContent::queryInterface( const uno::Type
& rType
) throw ( uno::RuntimeException
)
259 return ContentImplHelper::queryInterface(rType
);
262 OUString SAL_CALL
RepoContent::getImplementationName() throw( uno::RuntimeException
)
264 return OUString("com.sun.star.comp.CmisRepoContent");
267 uno::Sequence
< OUString
> SAL_CALL
RepoContent::getSupportedServiceNames()
268 throw( uno::RuntimeException
)
270 uno::Sequence
< OUString
> aSNS( 1 );
271 aSNS
.getArray()[ 0 ] = "com.sun.star.ucb.Content";
275 OUString SAL_CALL
RepoContent::getContentType() throw( uno::RuntimeException
)
277 return OUString( CMIS_REPO_TYPE
);
280 uno::Any SAL_CALL
RepoContent::execute(
281 const ucb::Command
& aCommand
,
282 sal_Int32
/*CommandId*/,
283 const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
284 throw( uno::Exception
, ucb::CommandAbortedException
, uno::RuntimeException
)
286 SAL_INFO( "cmisucp", "RepoContent::execute( ) - " << aCommand
.Name
);
290 if ( aCommand
.Name
== "getPropertyValues" )
292 uno::Sequence
< beans::Property
> Properties
;
293 if ( !( aCommand
.Argument
>>= Properties
) )
294 ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv
);
295 aRet
<<= getPropertyValues( Properties
, xEnv
);
297 else if ( aCommand
.Name
== "getPropertySetInfo" )
298 aRet
<<= getPropertySetInfo( xEnv
, sal_False
);
299 else if ( aCommand
.Name
== "getCommandInfo" )
300 aRet
<<= getCommandInfo( xEnv
, sal_False
);
301 else if ( aCommand
.Name
== "open" )
303 ucb::OpenCommandArgument2 aOpenCommand
;
304 if ( !( aCommand
.Argument
>>= aOpenCommand
) )
305 ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv
);
306 const ucb::OpenCommandArgument2
& rOpenCommand
= aOpenCommand
;
308 getRepositories( xEnv
);
309 uno::Reference
< ucb::XDynamicResultSet
> xSet
310 = new DynamicResultSet(m_xContext
, this, rOpenCommand
, xEnv
);
315 SAL_INFO( "cmisucp", "Command not allowed" );
321 void SAL_CALL
RepoContent::abort( sal_Int32
/*CommandId*/ ) throw( uno::RuntimeException
)
323 SAL_INFO( "cmisucp", "TODO - RepoContent::abort()" );
327 uno::Sequence
< uno::Type
> SAL_CALL
RepoContent::getTypes() throw( uno::RuntimeException
)
329 static cppu::OTypeCollection aFolderCollection
330 (CPPU_TYPE_REF( lang::XTypeProvider
),
331 CPPU_TYPE_REF( lang::XServiceInfo
),
332 CPPU_TYPE_REF( lang::XComponent
),
333 CPPU_TYPE_REF( ucb::XContent
),
334 CPPU_TYPE_REF( ucb::XCommandProcessor
),
335 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier
),
336 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier
),
337 CPPU_TYPE_REF( beans::XPropertyContainer
),
338 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier
),
339 CPPU_TYPE_REF( container::XChild
) );
340 return aFolderCollection
.getTypes();
343 list
< uno::Reference
< ucb::XContent
> > RepoContent::getChildren( )
345 list
< uno::Reference
< ucb::XContent
> > result
;
347 // TODO Cache the results somehow
348 SAL_INFO( "cmisucp", "RepoContent::getChildren" );
350 if ( m_sRepositoryId
.isEmpty( ) )
352 for ( list
< libcmis::RepositoryPtr
>::iterator it
= m_aRepositories
.begin( );
353 it
!= m_aRepositories
.end(); ++it
)
356 aUrl
.setObjectPath( STD_TO_OUSTR( ( *it
)->getId( ) ) );
358 uno::Reference
< ucb::XContentIdentifier
> xId
= new ucbhelper::ContentIdentifier( aUrl
.asString( ) );
359 uno::Reference
< ucb::XContent
> xContent
= new RepoContent( m_xContext
, m_pProvider
, xId
, m_aRepositories
);
361 result
.push_back( xContent
);
366 // Return the repository root as child
368 OUString sEncodedBinding
= rtl::Uri::encode(
369 m_aURL
.getBindingUrl( ) + "#" + m_sRepositoryId
,
370 rtl_UriCharClassRelSegment
,
371 rtl_UriEncodeKeepEscapes
,
372 RTL_TEXTENCODING_UTF8
);
373 sUrl
= "vnd.libreoffice.cmis://" + sEncodedBinding
;
375 uno::Reference
< ucb::XContentIdentifier
> xId
= new ucbhelper::ContentIdentifier( sUrl
);
376 uno::Reference
< ucb::XContent
> xContent
= new Content( m_xContext
, m_pProvider
, xId
);
378 result
.push_back( xContent
);
384 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */