Version 4.3.0.0.beta1, tag libreoffice-4.3.0.0.beta1
[LibreOffice.git] / ucb / source / ucp / cmis / cmis_repo_content.cxx
blob3771e1a365da23332f04a4bc3f7401fbb2efd51c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
8 */
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 <config_oauth2.h>
21 #include <rtl/uri.hxx>
22 #include <ucbhelper/cancelcommandexecution.hxx>
23 #include <ucbhelper/commandenvironment.hxx>
24 #include <ucbhelper/contentidentifier.hxx>
25 #include <ucbhelper/propertyvalueset.hxx>
26 #include <ucbhelper/proxydecider.hxx>
28 #include "auth_provider.hxx"
29 #include "certvalidation_handler.hxx"
30 #include "cmis_content.hxx"
31 #include "cmis_provider.hxx"
32 #include "cmis_repo_content.hxx"
33 #include "cmis_resultset.hxx"
35 #define OUSTR_TO_STDSTR(s) string( OUStringToOString( s, RTL_TEXTENCODING_UTF8 ).getStr() )
36 #define STD_TO_OUSTR( str ) OUString( str.c_str(), str.length( ), RTL_TEXTENCODING_UTF8 )
38 using namespace com::sun::star;
39 using namespace std;
41 namespace cmis
43 RepoContent::RepoContent( const uno::Reference< uno::XComponentContext >& rxContext,
44 ContentProvider *pProvider, const uno::Reference< ucb::XContentIdentifier >& Identifier,
45 vector< libcmis::RepositoryPtr > aRepos )
46 throw ( ucb::ContentCreationException )
47 : ContentImplHelper( rxContext, pProvider, Identifier ),
48 m_pProvider( pProvider ),
49 m_aURL( Identifier->getContentIdentifier( ) ),
50 m_sRepositoryId( ),
51 m_aRepositories( aRepos )
53 // Split the URL into bits
54 OUString sURL = m_xIdentifier->getContentIdentifier( );
55 SAL_INFO( "ucb.ucp.cmis", "RepoContent::RepoContent() " << sURL );
57 m_sRepositoryId = m_aURL.getObjectPath( );
58 m_sRepositoryId.startsWith("/", &m_sRepositoryId);
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 );
78 sal_Int32 nProps;
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 ];
88 try
90 if ( rProp.Name == "IsDocument" )
92 xRow->appendBoolean( rProp, false );
94 else if ( rProp.Name == "IsFolder" )
96 xRow->appendBoolean( rProp, 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, true );
106 else
108 xRow->appendVoid( rProp );
109 SAL_INFO( "ucb.ucp.cmis", "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::number( rProxy.nPort );
131 libcmis::SessionFactory::setProxySettings( OUSTR_TO_STDSTR( sProxy ), string(), string(), string() );
133 if ( m_aRepositories.empty() )
135 // Set the SSL Validation handler
136 libcmis::CertValidationHandlerPtr certHandler(
137 new CertValidationHandler( xEnv, m_xContext, aBindingUrl.GetHost( ) ) );
138 libcmis::SessionFactory::setCertificateValidationHandler( certHandler );
140 // Get the auth credentials
141 AuthProvider authProvider( xEnv, m_xIdentifier->getContentIdentifier( ), m_aURL.getBindingUrl( ) );
143 string rUsername = OUSTR_TO_STDSTR( m_aURL.getUsername( ) );
144 string rPassword = OUSTR_TO_STDSTR( m_aURL.getPassword( ) );
145 if ( authProvider.authenticationQuery( rUsername, rPassword ) )
149 // Create a session to get repositories
150 libcmis::OAuth2DataPtr oauth2Data;
151 if ( m_aURL.getBindingUrl( ) == GDRIVE_BASE_URL )
152 oauth2Data.reset( new libcmis::OAuth2Data(
153 GDRIVE_AUTH_URL, GDRIVE_TOKEN_URL,
154 GDRIVE_SCOPE, GDRIVE_REDIRECT_URI,
155 GDRIVE_CLIENT_ID, GDRIVE_CLIENT_SECRET ) );
156 if ( m_aURL.getBindingUrl().startsWith( ALFRESCO_CLOUD_BASE_URL ) )
157 oauth2Data.reset( new libcmis::OAuth2Data(
158 ALFRESCO_CLOUD_AUTH_URL, ALFRESCO_CLOUD_TOKEN_URL,
159 ALFRESCO_CLOUD_SCOPE, ALFRESCO_CLOUD_REDIRECT_URI,
160 ALFRESCO_CLOUD_CLIENT_ID, ALFRESCO_CLOUD_CLIENT_SECRET ) );
162 libcmis::Session* session = libcmis::SessionFactory::createSession(
163 OUSTR_TO_STDSTR( m_aURL.getBindingUrl( ) ),
164 rUsername, rPassword, "", false, oauth2Data );
165 if (session == NULL )
166 ucbhelper::cancelCommandExecution(
167 ucb::IOErrorCode_INVALID_DEVICE,
168 uno::Sequence< uno::Any >( 0 ),
169 xEnv,
170 OUString( ) );
171 m_aRepositories = session->getRepositories( );
172 delete session;
174 catch (const libcmis::Exception& e)
176 SAL_INFO( "ucb.ucp.cmis", "Error getting repositories: " << e.what() );
179 else
181 // Throw user cancelled exception
182 ucbhelper::cancelCommandExecution(
183 ucb::IOErrorCode_ABORT,
184 uno::Sequence< uno::Any >( 0 ),
185 xEnv,
186 OUString( "Authentication cancelled" ) );
191 libcmis::RepositoryPtr RepoContent::getRepository( const uno::Reference< ucb::XCommandEnvironment > & xEnv )
193 // Ensure we have the repositories extracted
194 getRepositories( xEnv );
196 libcmis::RepositoryPtr repo;
198 if ( !m_sRepositoryId.isEmpty() )
200 for ( vector< libcmis::RepositoryPtr >::iterator it = m_aRepositories.begin( );
201 it != m_aRepositories.end( ) && NULL == repo.get( ); ++it )
203 if ( STD_TO_OUSTR( ( *it )->getId( ) ) == m_sRepositoryId )
204 repo = *it;
207 else
208 repo = m_aRepositories.front( );
209 return repo;
212 uno::Sequence< beans::Property > RepoContent::getProperties(
213 const uno::Reference< ucb::XCommandEnvironment > & /*xEnv*/ )
215 static const beans::Property aGenericProperties[] =
217 beans::Property( OUString( "IsDocument" ),
218 -1, getCppuBooleanType(),
219 beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
220 beans::Property( OUString( "IsFolder" ),
221 -1, getCppuBooleanType(),
222 beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
223 beans::Property( OUString( "Title" ),
224 -1, cppu::UnoType<OUString>::get(),
225 beans::PropertyAttribute::BOUND ),
226 beans::Property( OUString( "IsReadOnly" ),
227 -1, getCppuBooleanType(),
228 beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
231 const int nProps = SAL_N_ELEMENTS(aGenericProperties);
232 return uno::Sequence< beans::Property > ( aGenericProperties, nProps );
235 uno::Sequence< ucb::CommandInfo > RepoContent::getCommands(
236 const uno::Reference< ucb::XCommandEnvironment > & /*xEnv*/ )
238 static const ucb::CommandInfo aCommandInfoTable[] =
240 // Required commands
241 ucb::CommandInfo
242 ( OUString( "getCommandInfo" ),
243 -1, getCppuVoidType() ),
244 ucb::CommandInfo
245 ( OUString( "getPropertySetInfo" ),
246 -1, getCppuVoidType() ),
247 ucb::CommandInfo
248 ( OUString( "getPropertyValues" ),
249 -1, getCppuType( static_cast<uno::Sequence< beans::Property > * >( 0 ) ) ),
250 ucb::CommandInfo
251 ( OUString( "setPropertyValues" ),
252 -1, getCppuType( static_cast<uno::Sequence< beans::PropertyValue > * >( 0 ) ) ),
254 // Optional standard commands
255 ucb::CommandInfo
256 ( OUString( "open" ),
257 -1, cppu::UnoType<ucb::OpenCommandArgument2>::get() ),
260 const int nProps = SAL_N_ELEMENTS(aCommandInfoTable);
261 return uno::Sequence< ucb::CommandInfo >(aCommandInfoTable, nProps );
264 OUString RepoContent::getParentURL( )
266 OUString sRet;
268 SAL_INFO( "ucb.ucp.cmis", "RepoContent::getParentURL()" );
270 // TODO Implement me
272 return sRet;
275 XTYPEPROVIDER_COMMON_IMPL( RepoContent );
277 void SAL_CALL RepoContent::acquire() throw()
279 ContentImplHelper::acquire();
282 void SAL_CALL RepoContent::release() throw()
284 ContentImplHelper::release();
287 uno::Any SAL_CALL RepoContent::queryInterface( const uno::Type & rType ) throw ( uno::RuntimeException, std::exception )
289 return ContentImplHelper::queryInterface(rType);
292 OUString SAL_CALL RepoContent::getImplementationName() throw( uno::RuntimeException, std::exception )
294 return OUString("com.sun.star.comp.CmisRepoContent");
297 uno::Sequence< OUString > SAL_CALL RepoContent::getSupportedServiceNames()
298 throw( uno::RuntimeException, std::exception )
300 uno::Sequence< OUString > aSNS( 1 );
301 aSNS.getArray()[ 0 ] = "com.sun.star.ucb.Content";
302 return aSNS;
305 OUString SAL_CALL RepoContent::getContentType() throw( uno::RuntimeException, std::exception )
307 return OUString( CMIS_REPO_TYPE );
310 uno::Any SAL_CALL RepoContent::execute(
311 const ucb::Command& aCommand,
312 sal_Int32 /*CommandId*/,
313 const uno::Reference< ucb::XCommandEnvironment >& xEnv )
314 throw( uno::Exception, ucb::CommandAbortedException, uno::RuntimeException, std::exception )
316 SAL_INFO( "ucb.ucp.cmis", "RepoContent::execute( ) - " << aCommand.Name );
318 uno::Any aRet;
320 if ( aCommand.Name == "getPropertyValues" )
322 uno::Sequence< beans::Property > Properties;
323 if ( !( aCommand.Argument >>= Properties ) )
324 ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv );
325 aRet <<= getPropertyValues( Properties, xEnv );
327 else if ( aCommand.Name == "getPropertySetInfo" )
328 aRet <<= getPropertySetInfo( xEnv, false );
329 else if ( aCommand.Name == "getCommandInfo" )
330 aRet <<= getCommandInfo( xEnv, false );
331 else if ( aCommand.Name == "open" )
333 ucb::OpenCommandArgument2 aOpenCommand;
334 if ( !( aCommand.Argument >>= aOpenCommand ) )
335 ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv );
336 const ucb::OpenCommandArgument2& rOpenCommand = aOpenCommand;
338 getRepositories( xEnv );
339 uno::Reference< ucb::XDynamicResultSet > xSet
340 = new DynamicResultSet(m_xContext, this, rOpenCommand, xEnv );
341 aRet <<= xSet;
343 else
345 SAL_INFO( "ucb.ucp.cmis", "Command not allowed" );
348 return aRet;
351 void SAL_CALL RepoContent::abort( sal_Int32 /*CommandId*/ ) throw( uno::RuntimeException, std::exception )
353 SAL_INFO( "ucb.ucp.cmis", "TODO - RepoContent::abort()" );
354 // TODO Implement me
357 uno::Sequence< uno::Type > SAL_CALL RepoContent::getTypes() throw( uno::RuntimeException, std::exception )
359 static cppu::OTypeCollection aFolderCollection
360 (CPPU_TYPE_REF( lang::XTypeProvider ),
361 CPPU_TYPE_REF( lang::XServiceInfo ),
362 CPPU_TYPE_REF( lang::XComponent ),
363 CPPU_TYPE_REF( ucb::XContent ),
364 CPPU_TYPE_REF( ucb::XCommandProcessor ),
365 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
366 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
367 CPPU_TYPE_REF( beans::XPropertyContainer ),
368 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
369 CPPU_TYPE_REF( container::XChild ) );
370 return aFolderCollection.getTypes();
373 list< uno::Reference< ucb::XContent > > RepoContent::getChildren( )
375 list< uno::Reference< ucb::XContent > > result;
377 // TODO Cache the results somehow
378 SAL_INFO( "ucb.ucp.cmis", "RepoContent::getChildren" );
380 if ( m_sRepositoryId.isEmpty( ) )
382 for ( vector< libcmis::RepositoryPtr >::iterator it = m_aRepositories.begin( );
383 it != m_aRepositories.end(); ++it )
385 URL aUrl( m_aURL );
386 aUrl.setObjectPath( STD_TO_OUSTR( ( *it )->getId( ) ) );
388 uno::Reference< ucb::XContentIdentifier > xId = new ucbhelper::ContentIdentifier( aUrl.asString( ) );
389 uno::Reference< ucb::XContent > xContent = new RepoContent( m_xContext, m_pProvider, xId, m_aRepositories );
391 result.push_back( xContent );
394 else
396 // Return the repository root as child
397 OUString sUrl;
398 OUString sEncodedBinding = rtl::Uri::encode(
399 m_aURL.getBindingUrl( ) + "#" + m_sRepositoryId,
400 rtl_UriCharClassRelSegment,
401 rtl_UriEncodeKeepEscapes,
402 RTL_TEXTENCODING_UTF8 );
403 sUrl = "vnd.libreoffice.cmis://" + sEncodedBinding;
405 uno::Reference< ucb::XContentIdentifier > xId = new ucbhelper::ContentIdentifier( sUrl );
406 uno::Reference< ucb::XContent > xContent = new Content( m_xContext, m_pProvider, xId );
408 result.push_back( xContent );
410 return result;
414 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */