Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * Version: MPL 1.1 / GPLv3+ / LGPLv3+
4 : : *
5 : : * The contents of this file are subject to the Mozilla Public License Version
6 : : * 1.1 (the "License"); you may not use this file except in compliance with
7 : : * the License or as specified alternatively below. You may obtain a copy of
8 : : * the License at http://www.mozilla.org/MPL/
9 : : *
10 : : * Software distributed under the License is distributed on an "AS IS" basis,
11 : : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : : * for the specific language governing rights and limitations under the
13 : : * License.
14 : : *
15 : : * Major Contributor(s):
16 : : * [ Copyright (C) 2011 SUSE <cbosdonnat@suse.com> (initial developer) ]
17 : : *
18 : : * All Rights Reserved.
19 : : *
20 : : * For minor contributions see the git repository.
21 : : *
22 : : * Alternatively, the contents of this file may be used under the terms of
23 : : * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
24 : : * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
25 : : * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
26 : : * instead of those above.
27 : : */
28 : :
29 : : #include <cstdio>
30 : :
31 : : #include <com/sun/star/beans/PropertyAttribute.hpp>
32 : : #include <com/sun/star/beans/PropertyValue.hpp>
33 : : #include <com/sun/star/beans/XPropertySetInfo.hpp>
34 : : #include <com/sun/star/io/XActiveDataSink.hpp>
35 : : #include <com/sun/star/io/XActiveDataStreamer.hpp>
36 : : #include <com/sun/star/lang/IllegalAccessException.hpp>
37 : : #include <com/sun/star/task/InteractionClassification.hpp>
38 : : #include <com/sun/star/ucb/ContentInfo.hpp>
39 : : #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
40 : : #include <com/sun/star/ucb/InsertCommandArgument.hpp>
41 : : #include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp>
42 : : #include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
43 : : #include <com/sun/star/ucb/MissingInputStreamException.hpp>
44 : : #include <com/sun/star/ucb/NameClash.hpp>
45 : : #include <com/sun/star/ucb/NameClashException.hpp>
46 : : #include <com/sun/star/ucb/OpenMode.hpp>
47 : : #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
48 : : #include <com/sun/star/ucb/UnsupportedNameClashException.hpp>
49 : : #include <com/sun/star/ucb/UnsupportedOpenModeException.hpp>
50 : : #include <com/sun/star/ucb/XCommandInfo.hpp>
51 : : #include <com/sun/star/ucb/XDynamicResultSet.hpp>
52 : :
53 : : #include <libcmis/document.hxx>
54 : :
55 : : #include <ucbhelper/cancelcommandexecution.hxx>
56 : : #include <ucbhelper/contentidentifier.hxx>
57 : : #include <ucbhelper/std_inputstream.hxx>
58 : : #include <ucbhelper/std_outputstream.hxx>
59 : : #include <ucbhelper/propertyvalueset.hxx>
60 : :
61 : : #include "auth_provider.hxx"
62 : : #include "cmis_content.hxx"
63 : : #include "cmis_provider.hxx"
64 : : #include "cmis_resultset.hxx"
65 : :
66 : : #define OUSTR_TO_STDSTR(s) string( rtl::OUStringToOString( s, RTL_TEXTENCODING_UTF8 ).getStr() )
67 : : #define STD_TO_OUSTR( str ) rtl::OUString( str.c_str(), str.length( ), RTL_TEXTENCODING_UTF8 )
68 : :
69 : : using namespace com::sun::star;
70 : : using namespace std;
71 : :
72 : : namespace
73 : : {
74 : 0 : util::DateTime lcl_boostToUnoTime( boost::posix_time::ptime boostTime )
75 : : {
76 : 0 : util::DateTime unoTime;
77 : 0 : unoTime.Year = boostTime.date().year();
78 : 0 : unoTime.Month = boostTime.date().month();
79 : 0 : unoTime.Day = boostTime.date().day();
80 : 0 : unoTime.Hours = boostTime.time_of_day().hours();
81 : 0 : unoTime.Minutes = boostTime.time_of_day().minutes();
82 : 0 : unoTime.Seconds = boostTime.time_of_day().seconds();
83 : :
84 : 0 : long total_milli = boostTime.time_of_day().total_milliseconds( );
85 : 0 : long milli = total_milli - boostTime.time_of_day().total_seconds( );
86 : 0 : long hundredthSeconds = milli / 10;
87 : :
88 : 0 : unoTime.HundredthSeconds = hundredthSeconds;
89 : :
90 : 0 : return unoTime;
91 : : }
92 : : }
93 : :
94 : : namespace cmis
95 : : {
96 : 0 : Content::Content( const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
97 : : ContentProvider *pProvider, const uno::Reference< ucb::XContentIdentifier >& Identifier,
98 : : libcmis::ObjectPtr pObject )
99 : : throw ( ucb::ContentCreationException )
100 : : : ContentImplHelper( rxSMgr, pProvider, Identifier ),
101 : : m_pProvider( pProvider ),
102 : : m_pSession( NULL ),
103 : : m_pObject( pObject ),
104 : 0 : m_bTransient( false )
105 : : {
106 : : // Split the URL into bits
107 : 0 : m_sURL = m_xIdentifier->getContentIdentifier( );
108 : 0 : cmis::URL url( m_sURL );
109 : : SAL_INFO( "cmisucp", "Content::Content() " << m_sURL );
110 : :
111 : : // Look for a cached session, key is binding url + repo id
112 : 0 : rtl::OUString sSessionId = url.getBindingUrl( ) + url.getRepositoryId( );
113 : 0 : m_pSession = pProvider->getSession( sSessionId );
114 : 0 : if ( NULL == m_pSession )
115 : : {
116 : : // Initiate a CMIS session and register it as we found nothing
117 : 0 : m_pSession = libcmis::SessionFactory::createSession( url.getSessionParams( ) );
118 : 0 : pProvider->registerSession( sSessionId, m_pSession );
119 : : }
120 : :
121 : 0 : m_sObjectPath = url.getObjectPath( );
122 : 0 : m_sObjectId = url.getObjectId( );
123 : 0 : m_sBindingUrl = url.getBindingUrl( );
124 : 0 : }
125 : :
126 : 0 : Content::Content( const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, ContentProvider *pProvider,
127 : : const uno::Reference< ucb::XContentIdentifier >& Identifier,
128 : : sal_Bool bIsFolder )
129 : : throw ( ucb::ContentCreationException )
130 : : : ContentImplHelper( rxSMgr, pProvider, Identifier ),
131 : : m_pProvider( pProvider ),
132 : : m_pSession( NULL ),
133 : 0 : m_bTransient( true )
134 : : {
135 : : // Split the URL into bits
136 : 0 : m_sURL = m_xIdentifier->getContentIdentifier( );
137 : 0 : cmis::URL url( m_sURL );
138 : : SAL_INFO( "cmisucp", "Content::Content() " << m_sURL );
139 : :
140 : : // Look for a cached session, key is binding url + repo id
141 : 0 : rtl::OUString sSessionId = url.getBindingUrl( ) + url.getRepositoryId( );
142 : 0 : m_pSession = pProvider->getSession( sSessionId );
143 : 0 : if ( NULL == m_pSession )
144 : : {
145 : : // Initiate a CMIS session and register it as we found nothing
146 : 0 : m_pSession = libcmis::SessionFactory::createSession( url.getSessionParams( ) );
147 : 0 : pProvider->registerSession( sSessionId, m_pSession );
148 : : }
149 : :
150 : 0 : m_sObjectPath = url.getObjectPath( );
151 : 0 : m_sObjectId = url.getObjectId( );
152 : 0 : m_sBindingUrl = url.getBindingUrl( );
153 : :
154 : : // Get the object type
155 : 0 : string typeId = bIsFolder ? "cmis:folder" : "cmis:document";
156 : 0 : m_pObjectType = m_pSession->getType( typeId );
157 : 0 : }
158 : :
159 : 0 : Content::~Content()
160 : : {
161 : 0 : }
162 : :
163 : 0 : libcmis::ObjectPtr Content::getObject( ) throw ( libcmis::Exception )
164 : : {
165 : 0 : if ( !m_pObject.get() )
166 : : {
167 : 0 : if ( !m_sObjectPath.isEmpty( ) )
168 : 0 : m_pObject = m_pSession->getObjectByPath( OUSTR_TO_STDSTR( m_sObjectPath ) );
169 : 0 : else if (!m_sObjectId.isEmpty( ) )
170 : 0 : m_pObject = m_pSession->getObject( OUSTR_TO_STDSTR( m_sObjectId ) );
171 : : else
172 : : {
173 : 0 : m_pObject = m_pSession->getRootFolder( );
174 : 0 : m_sObjectPath = "/";
175 : 0 : m_sObjectId = rtl::OUString( );
176 : : }
177 : : }
178 : :
179 : 0 : return m_pObject;
180 : : }
181 : :
182 : 0 : void Content::resetAuthProvider( const uno::Reference< ucb::XCommandEnvironment >& xEnv )
183 : : {
184 : 0 : libcmis::AuthProviderPtr authProvider( new AuthProvider( xEnv, m_sURL, m_sBindingUrl ) );
185 : 0 : m_pSession->setAuthenticationProvider( authProvider );
186 : 0 : }
187 : :
188 : 0 : bool Content::isFolder(const uno::Reference< ucb::XCommandEnvironment >& xEnv )
189 : : {
190 : 0 : bool bIsFolder = false;
191 : : try
192 : : {
193 : 0 : resetAuthProvider( xEnv );
194 : 0 : bIsFolder = getObject( )->getBaseType( ) == "cmis:folder";
195 : : }
196 : 0 : catch ( const libcmis::Exception& e )
197 : : {
198 : : SAL_INFO( "cmisucp", "Unexpected libcmis exception: " << e.what( ) );
199 : : ucbhelper::cancelCommandExecution(
200 : : ucb::IOErrorCode_GENERAL,
201 : : uno::Sequence< uno::Any >( 0 ),
202 : : xEnv,
203 : 0 : rtl::OUString::createFromAscii( e.what() ) );
204 : : }
205 : 0 : return bIsFolder;
206 : : }
207 : :
208 : 0 : uno::Any Content::getBadArgExcept()
209 : : {
210 : : return uno::makeAny( lang::IllegalArgumentException(
211 : : rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Wrong argument type!")),
212 : 0 : static_cast< cppu::OWeakObject * >( this ), -1) );
213 : : }
214 : :
215 : 0 : uno::Reference< sdbc::XRow > Content::getPropertyValues(
216 : : const uno::Sequence< beans::Property >& rProperties,
217 : : const uno::Reference< ucb::XCommandEnvironment >& xEnv )
218 : : {
219 : 0 : resetAuthProvider( xEnv );
220 : :
221 : 0 : rtl::Reference< ::ucbhelper::PropertyValueSet > xRow = new ::ucbhelper::PropertyValueSet( m_xSMgr );
222 : :
223 : : sal_Int32 nProps;
224 : : const beans::Property* pProps;
225 : :
226 : 0 : nProps = rProperties.getLength();
227 : 0 : pProps = rProperties.getConstArray();
228 : :
229 : 0 : for( sal_Int32 n = 0; n < nProps; ++n )
230 : : {
231 : 0 : const beans::Property& rProp = pProps[ n ];
232 : :
233 : : try
234 : : {
235 : 0 : if ( rProp.Name == "IsDocument" )
236 : : {
237 : : try
238 : : {
239 : 0 : xRow->appendBoolean( rProp, getObject()->getBaseType( ) == "cmis:document" );
240 : : }
241 : 0 : catch ( const libcmis::Exception& )
242 : : {
243 : 0 : if ( m_pObjectType.get( ) )
244 : 0 : xRow->appendBoolean( rProp, m_pObjectType->getBaseType()->getId( ) == "cmis:document" );
245 : : else
246 : 0 : xRow->appendVoid( rProp );
247 : : }
248 : : }
249 : 0 : else if ( rProp.Name == "IsFolder" )
250 : : {
251 : : try
252 : : {
253 : 0 : xRow->appendBoolean( rProp, getObject()->getBaseType( ) == "cmis:folder" );
254 : : }
255 : 0 : catch ( const libcmis::Exception& )
256 : : {
257 : 0 : if ( m_pObjectType.get( ) )
258 : 0 : xRow->appendBoolean( rProp, m_pObjectType->getBaseType()->getId( ) == "cmis:folder" );
259 : : else
260 : 0 : xRow->appendVoid( rProp );
261 : : }
262 : : }
263 : 0 : else if ( rProp.Name == "Title" )
264 : : {
265 : 0 : rtl::OUString sTitle;
266 : : try
267 : : {
268 : 0 : sTitle = STD_TO_OUSTR( getObject()->getName() );
269 : : }
270 : 0 : catch ( const libcmis::Exception& )
271 : : {
272 : 0 : if ( !m_pObjectProps.empty() )
273 : : {
274 : 0 : map< string, libcmis::PropertyPtr >::iterator it = m_pObjectProps.find( "cmis:name" );
275 : 0 : if ( it != m_pObjectProps.end( ) )
276 : : {
277 : 0 : vector< string > values = it->second->getStrings( );
278 : 0 : if ( !values.empty() )
279 : 0 : sTitle = STD_TO_OUSTR( values.front( ) );
280 : : }
281 : : }
282 : : }
283 : :
284 : : // Nothing worked... get it from the path
285 : 0 : if ( sTitle.isEmpty( ) )
286 : : {
287 : 0 : rtl::OUString sPath = m_sObjectPath;
288 : :
289 : : // Get rid of the trailing slash problem
290 : 0 : if ( sPath[ sPath.getLength( ) - 1 ] == '/' )
291 : 0 : sPath = sPath.copy( 0, sPath.getLength() - 1 );
292 : :
293 : : // Get the last segment
294 : 0 : sal_Int32 nPos = sPath.lastIndexOf( '/' );
295 : 0 : if ( nPos >= 0 )
296 : 0 : sTitle = sPath.copy( nPos + 1 );
297 : : }
298 : :
299 : 0 : if ( !sTitle.isEmpty( ) )
300 : 0 : xRow->appendString( rProp, sTitle );
301 : : else
302 : 0 : xRow->appendVoid( rProp );
303 : : }
304 : 0 : else if ( rProp.Name == "TitleOnServer" )
305 : : {
306 : 0 : string path;
307 : : try
308 : : {
309 : 0 : vector< string > paths = getObject( )->getPaths( );
310 : 0 : if ( !paths.empty( ) )
311 : 0 : path = paths.front( );
312 : : else
313 : 0 : path = getObject()->getName( );
314 : :
315 : 0 : xRow->appendString( rProp, STD_TO_OUSTR( path ) );
316 : : }
317 : 0 : catch ( const libcmis::Exception& )
318 : : {
319 : 0 : xRow->appendVoid( rProp );
320 : 0 : }
321 : : }
322 : 0 : else if ( rProp.Name == "IsReadOnly" )
323 : : {
324 : 0 : boost::shared_ptr< libcmis::AllowableActions > allowableActions = getObject()->getAllowableActions( );
325 : 0 : sal_Bool bReadOnly = sal_False;
326 : 0 : if ( !allowableActions->isAllowed( libcmis::ObjectAction::SetContentStream ) )
327 : 0 : bReadOnly = sal_True;
328 : :
329 : 0 : xRow->appendBoolean( rProp, bReadOnly );
330 : : }
331 : 0 : else if ( rProp.Name == "DateCreated" )
332 : : {
333 : 0 : util::DateTime aTime = lcl_boostToUnoTime( getObject( )->getCreationDate( ) );
334 : 0 : xRow->appendTimestamp( rProp, aTime );
335 : : }
336 : 0 : else if ( rProp.Name == "DateModified" )
337 : : {
338 : 0 : util::DateTime aTime = lcl_boostToUnoTime( getObject( )->getLastModificationDate( ) );
339 : 0 : xRow->appendTimestamp( rProp, aTime );
340 : : }
341 : 0 : else if ( rProp.Name == "Size" )
342 : : {
343 : : try
344 : : {
345 : 0 : libcmis::Document* document = dynamic_cast< libcmis::Document* >( getObject().get( ) );
346 : 0 : if ( NULL != document )
347 : 0 : xRow->appendLong( rProp, document->getContentLength() );
348 : : else
349 : 0 : xRow->appendVoid( rProp );
350 : : }
351 : 0 : catch ( const libcmis::Exception& )
352 : : {
353 : 0 : xRow->appendVoid( rProp );
354 : : }
355 : : }
356 : 0 : else if ( rProp.Name == "CreatableContentsInfo" )
357 : : {
358 : 0 : xRow->appendObject( rProp, uno::makeAny( queryCreatableContentsInfo( xEnv ) ) );
359 : : }
360 : 0 : else if ( rProp.Name == "MediaType" )
361 : : {
362 : : try
363 : : {
364 : 0 : libcmis::Document* document = dynamic_cast< libcmis::Document* >( getObject().get( ) );
365 : 0 : if ( NULL != document )
366 : 0 : xRow->appendString( rProp, STD_TO_OUSTR( document->getContentType() ) );
367 : : else
368 : 0 : xRow->appendVoid( rProp );
369 : : }
370 : 0 : catch ( const libcmis::Exception& )
371 : : {
372 : 0 : xRow->appendVoid( rProp );
373 : : }
374 : : }
375 : : else
376 : : SAL_INFO( "cmisucp", "Looking for unsupported property " << rProp.Name );
377 : : }
378 : 0 : catch (const libcmis::Exception&)
379 : : {
380 : 0 : xRow->appendVoid( rProp );
381 : : }
382 : : }
383 : :
384 : 0 : return uno::Reference< sdbc::XRow >( xRow.get() );
385 : : }
386 : :
387 : 0 : bool Content::exists( )
388 : : {
389 : 0 : bool bExists = true;
390 : : try
391 : : {
392 : 0 : if ( !m_sObjectPath.isEmpty( ) )
393 : 0 : m_pSession->getObjectByPath( OUSTR_TO_STDSTR( m_sObjectPath ) );
394 : 0 : else if ( !m_sObjectId.isEmpty( ) )
395 : 0 : m_pSession->getObject( OUSTR_TO_STDSTR( m_sObjectId ) );
396 : : // No need to handle the root folder case... how can it not exists?
397 : : }
398 : 0 : catch ( const libcmis::Exception& )
399 : : {
400 : 0 : bExists = false;
401 : : }
402 : :
403 : 0 : return bExists;
404 : : }
405 : :
406 : 0 : uno::Any Content::open(const ucb::OpenCommandArgument2 & rOpenCommand,
407 : : const uno::Reference< ucb::XCommandEnvironment > & xEnv )
408 : : throw( uno::Exception )
409 : : {
410 : 0 : bool bIsFolder = isFolder( xEnv );
411 : :
412 : : // Handle the case of the non-existing file
413 : 0 : if ( !exists( ) )
414 : : {
415 : 0 : uno::Sequence< uno::Any > aArgs( 1 );
416 : 0 : aArgs[ 0 ] <<= m_xIdentifier->getContentIdentifier();
417 : : uno::Any aErr = uno::makeAny(
418 : : ucb::InteractiveAugmentedIOException(rtl::OUString(), static_cast< cppu::OWeakObject * >( this ),
419 : : task::InteractionClassification_ERROR,
420 : : bIsFolder ? ucb::IOErrorCode_NOT_EXISTING_PATH : ucb::IOErrorCode_NOT_EXISTING, aArgs)
421 : 0 : );
422 : :
423 : 0 : ucbhelper::cancelCommandExecution(aErr, xEnv);
424 : : }
425 : :
426 : 0 : uno::Any aRet;
427 : :
428 : : sal_Bool bOpenFolder = (
429 : : ( rOpenCommand.Mode == ucb::OpenMode::ALL ) ||
430 : : ( rOpenCommand.Mode == ucb::OpenMode::FOLDERS ) ||
431 : : ( rOpenCommand.Mode == ucb::OpenMode::DOCUMENTS )
432 : 0 : );
433 : :
434 : 0 : if ( bOpenFolder && bIsFolder )
435 : : {
436 : : uno::Reference< ucb::XDynamicResultSet > xSet
437 : 0 : = new DynamicResultSet(m_xSMgr, this, rOpenCommand, xEnv );
438 : 0 : aRet <<= xSet;
439 : : }
440 : 0 : else if ( rOpenCommand.Sink.is() )
441 : : {
442 : 0 : if (
443 : : ( rOpenCommand.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE ) ||
444 : : ( rOpenCommand.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE )
445 : : )
446 : : {
447 : : ucbhelper::cancelCommandExecution(
448 : : uno::makeAny ( ucb::UnsupportedOpenModeException
449 : : ( rtl::OUString(), static_cast< cppu::OWeakObject * >( this ),
450 : : sal_Int16( rOpenCommand.Mode ) ) ),
451 : 0 : xEnv );
452 : : }
453 : :
454 : 0 : if ( !feedSink( rOpenCommand.Sink, xEnv ) )
455 : : {
456 : : // Note: rOpenCommand.Sink may contain an XStream
457 : : // implementation. Support for this type of
458 : : // sink is optional...
459 : : SAL_INFO( "cmisucp", "Failed to copy data to sink" );
460 : :
461 : : ucbhelper::cancelCommandExecution(
462 : : uno::makeAny (ucb::UnsupportedDataSinkException
463 : : ( rtl::OUString(), static_cast< cppu::OWeakObject * >( this ),
464 : : rOpenCommand.Sink ) ),
465 : 0 : xEnv );
466 : : }
467 : : }
468 : : else
469 : : SAL_INFO( "cmisucp", "Open falling through ..." );
470 : :
471 : 0 : return aRet;
472 : : }
473 : :
474 : 0 : void Content::transfer( const ucb::TransferInfo& rTransferInfo,
475 : : const uno::Reference< ucb::XCommandEnvironment > & xEnv )
476 : : throw( uno::Exception )
477 : : {
478 : : // If the source isn't on the same CMIS repository, then simply copy
479 : 0 : INetURLObject aSourceUrl( rTransferInfo.SourceURL );
480 : 0 : if ( aSourceUrl.GetProtocol() != INET_PROT_CMIS_ATOM )
481 : : {
482 : 0 : rtl::OUString sSrcBindingUrl = URL( rTransferInfo.SourceURL ).getBindingUrl( );
483 : 0 : if ( sSrcBindingUrl != m_sBindingUrl )
484 : : {
485 : : ucbhelper::cancelCommandExecution(
486 : : uno::makeAny(
487 : : ucb::InteractiveBadTransferURLException(
488 : : rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
489 : : "Unsupported URL scheme!" )),
490 : : static_cast< cppu::OWeakObject * >( this ) ) ),
491 : 0 : xEnv );
492 : 0 : }
493 : : }
494 : :
495 : 0 : SAL_INFO( "cmisucp", "TODO - Content::transfer()" );
496 : 0 : }
497 : :
498 : 0 : void Content::insert( const uno::Reference< io::XInputStream > & xInputStream,
499 : : sal_Bool bReplaceExisting, const uno::Reference< ucb::XCommandEnvironment >& xEnv )
500 : : throw( uno::Exception )
501 : : {
502 : 0 : if ( !xInputStream.is() )
503 : : {
504 : : ucbhelper::cancelCommandExecution( uno::makeAny
505 : : ( ucb::MissingInputStreamException
506 : : ( rtl::OUString(), static_cast< cppu::OWeakObject * >( this ) ) ),
507 : 0 : xEnv );
508 : : }
509 : :
510 : : // For transient content, the URL is the one of the parent
511 : 0 : if ( m_bTransient )
512 : : {
513 : 0 : rtl::OUString sNewPath;
514 : :
515 : : // Try to get the object from the server if there is any
516 : 0 : libcmis::Folder* pFolder = NULL;
517 : : try
518 : : {
519 : 0 : pFolder = dynamic_cast< libcmis::Folder* >( getObject( ).get( ) );
520 : : }
521 : 0 : catch ( const libcmis::Exception& )
522 : : {
523 : : }
524 : :
525 : 0 : if ( pFolder != NULL )
526 : : {
527 : 0 : map< string, libcmis::PropertyPtr >::iterator it = m_pObjectProps.find( "cmis:name" );
528 : 0 : if ( it == m_pObjectProps.end( ) )
529 : : {
530 : : ucbhelper::cancelCommandExecution( uno::makeAny
531 : : ( uno::RuntimeException( "Missing name property",
532 : : static_cast< cppu::OWeakObject * >( this ) ) ),
533 : 0 : xEnv );
534 : : }
535 : 0 : string newName = it->second->getStrings( ).front( );
536 : 0 : string newPath = pFolder->getPath( );
537 : 0 : if ( newPath[ newPath.size( ) - 1 ] != '/' )
538 : 0 : newPath += "/";
539 : 0 : newPath += newName;
540 : :
541 : 0 : libcmis::ObjectPtr object;
542 : : try
543 : : {
544 : 0 : object = m_pSession->getObjectByPath( newPath );
545 : 0 : sNewPath = STD_TO_OUSTR( newPath );
546 : : }
547 : 0 : catch ( const libcmis::Exception& )
548 : : {
549 : : // Nothing matched the path
550 : : }
551 : :
552 : 0 : if ( NULL != object.get( ) )
553 : : {
554 : : // Are the base type matching?
555 : 0 : if ( object->getBaseType( ) != m_pObjectType->getBaseType( )->getId() )
556 : : {
557 : : ucbhelper::cancelCommandExecution( uno::makeAny
558 : : ( uno::RuntimeException( "Can't change a folder into a document and vice-versa.",
559 : : static_cast< cppu::OWeakObject * >( this ) ) ),
560 : 0 : xEnv );
561 : : }
562 : :
563 : : // Update the existing object if it's a document
564 : 0 : libcmis::Document* document = dynamic_cast< libcmis::Document* >( object.get( ) );
565 : 0 : if ( NULL != document )
566 : : {
567 : 0 : string sMime = document->getContentType( );
568 : 0 : boost::shared_ptr< ostream > pOut( new ostringstream ( ios_base::binary | ios_base::in | ios_base::out ) );
569 : 0 : uno::Reference < io::XOutputStream > xOutput = new ucbhelper::StdOutputStream( pOut );
570 : 0 : copyData( xInputStream, xOutput );
571 : 0 : document->setContentStream( pOut, sMime, bReplaceExisting );
572 : : }
573 : : }
574 : : else
575 : : {
576 : : // We need to create a brand new object... either folder or document
577 : 0 : bool bIsFolder = m_pObjectType->getBaseType( )->getId( ) == "cmis:folder";
578 : 0 : setCmisProperty( "cmis:objectTypeId", m_pObjectType->getId( ) );
579 : :
580 : 0 : if ( bIsFolder )
581 : : {
582 : 0 : libcmis::FolderPtr pNew = pFolder->createFolder( m_pObjectProps );
583 : 0 : sNewPath = STD_TO_OUSTR( newPath );
584 : : }
585 : : else
586 : : {
587 : 0 : boost::shared_ptr< ostream > pOut( new ostringstream ( ios_base::binary | ios_base::in | ios_base::out ) );
588 : 0 : uno::Reference < io::XOutputStream > xOutput = new ucbhelper::StdOutputStream( pOut );
589 : 0 : copyData( xInputStream, xOutput );
590 : 0 : libcmis::DocumentPtr pNew = pFolder->createDocument( m_pObjectProps, pOut, string() );
591 : 0 : sNewPath = STD_TO_OUSTR( newPath );
592 : : }
593 : : }
594 : :
595 : 0 : if ( !sNewPath.isEmpty( ) )
596 : : {
597 : : // Update the current content: it's no longer transient
598 : 0 : m_sObjectPath = sNewPath;
599 : 0 : URL aUrl( m_sURL );
600 : 0 : aUrl.setObjectPath( m_sObjectPath );
601 : 0 : m_sURL = aUrl.asString( );
602 : 0 : m_pObject.reset( );
603 : 0 : m_pObjectType.reset( );
604 : 0 : m_pObjectProps.clear( );
605 : 0 : m_bTransient = false;
606 : :
607 : 0 : inserted();
608 : 0 : }
609 : 0 : }
610 : : }
611 : 0 : }
612 : :
613 : : const int TRANSFER_BUFFER_SIZE = 65536;
614 : :
615 : 0 : void Content::copyData(
616 : : uno::Reference< io::XInputStream > xIn,
617 : : uno::Reference< io::XOutputStream > xOut )
618 : : {
619 : 0 : uno::Sequence< sal_Int8 > theData( TRANSFER_BUFFER_SIZE );
620 : :
621 : 0 : while ( xIn->readBytes( theData, TRANSFER_BUFFER_SIZE ) > 0 )
622 : 0 : xOut->writeBytes( theData );
623 : :
624 : 0 : xOut->closeOutput();
625 : 0 : }
626 : :
627 : 0 : uno::Sequence< uno::Any > Content::setPropertyValues(
628 : : const uno::Sequence< beans::PropertyValue >& rValues,
629 : : const uno::Reference< ucb::XCommandEnvironment >& xEnv )
630 : : {
631 : : try
632 : : {
633 : : // Get the already set properties if possible
634 : 0 : if ( !m_bTransient && getObject( ).get( ) )
635 : : {
636 : 0 : m_pObjectProps = getObject()->getProperties( );
637 : 0 : m_pObjectType = getObject()->getTypeDescription();
638 : : }
639 : : }
640 : 0 : catch ( const libcmis::Exception& e )
641 : : {
642 : : SAL_INFO( "cmisucp", "Unexpected libcmis exception: " << e.what( ) );
643 : : ucbhelper::cancelCommandExecution(
644 : : ucb::IOErrorCode_GENERAL,
645 : : uno::Sequence< uno::Any >( 0 ),
646 : : xEnv,
647 : 0 : rtl::OUString::createFromAscii( e.what() ) );
648 : : }
649 : :
650 : 0 : sal_Int32 nCount = rValues.getLength();
651 : 0 : uno::Sequence< uno::Any > aRet( nCount );
652 : :
653 : 0 : bool bChanged = false;
654 : 0 : const beans::PropertyValue* pValues = rValues.getConstArray();
655 : 0 : for ( sal_Int32 n = 0; n < nCount; ++n )
656 : : {
657 : 0 : const beans::PropertyValue& rValue = pValues[ n ];
658 : 0 : if ( rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) ||
659 : 0 : rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "MediaType" ) ) ||
660 : 0 : rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) ||
661 : 0 : rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) ||
662 : 0 : rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Size" ) ) ||
663 : 0 : rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "CreatableContentsInfo" ) ) )
664 : : {
665 : : lang::IllegalAccessException e ( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Property is read-only!")),
666 : 0 : static_cast< cppu::OWeakObject* >( this ) );
667 : 0 : aRet[ n ] <<= e;
668 : : }
669 : 0 : else if ( rValue.Name == "Title" )
670 : : {
671 : 0 : rtl::OUString aNewTitle;
672 : 0 : if (!( rValue.Value >>= aNewTitle ))
673 : : {
674 : 0 : aRet[ n ] <<= beans::IllegalTypeException
675 : : ( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Property value has wrong type!")),
676 : 0 : static_cast< cppu::OWeakObject * >( this ) );
677 : 0 : continue;
678 : : }
679 : :
680 : 0 : if ( aNewTitle.getLength() <= 0 )
681 : : {
682 : 0 : aRet[ n ] <<= lang::IllegalArgumentException
683 : : ( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Empty title not allowed!")),
684 : 0 : static_cast< cppu::OWeakObject * >( this ), -1 );
685 : 0 : continue;
686 : :
687 : : }
688 : :
689 : 0 : setCmisProperty( "cmis:name", OUSTR_TO_STDSTR( aNewTitle ) );
690 : 0 : bChanged = true;
691 : : }
692 : : else
693 : : {
694 : : SAL_INFO( "cmisucp", "Couln't set property: " << rValue.Name );
695 : : lang::IllegalAccessException e ( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Property is read-only!")),
696 : 0 : static_cast< cppu::OWeakObject* >( this ) );
697 : 0 : aRet[ n ] <<= e;
698 : : }
699 : : }
700 : :
701 : : try
702 : : {
703 : 0 : if ( !m_bTransient && bChanged )
704 : : {
705 : 0 : getObject()->updateProperties();
706 : : }
707 : : }
708 : 0 : catch ( const libcmis::Exception& e )
709 : : {
710 : : SAL_INFO( "cmisucp", "Unexpected libcmis exception: " << e.what( ) );
711 : : ucbhelper::cancelCommandExecution(
712 : : ucb::IOErrorCode_GENERAL,
713 : : uno::Sequence< uno::Any >( 0 ),
714 : : xEnv,
715 : 0 : rtl::OUString::createFromAscii( e.what() ) );
716 : : }
717 : :
718 : 0 : return aRet;
719 : : }
720 : :
721 : 0 : sal_Bool Content::feedSink( uno::Reference< uno::XInterface> xSink,
722 : : const uno::Reference< ucb::XCommandEnvironment >& xEnv )
723 : : {
724 : 0 : if ( !xSink.is() )
725 : 0 : return sal_False;
726 : :
727 : 0 : uno::Reference< io::XOutputStream > xOut = uno::Reference< io::XOutputStream >(xSink, uno::UNO_QUERY );
728 : 0 : uno::Reference< io::XActiveDataSink > xDataSink = uno::Reference< io::XActiveDataSink >(xSink, uno::UNO_QUERY );
729 : 0 : uno::Reference< io::XActiveDataStreamer > xDataStreamer = uno::Reference< io::XActiveDataStreamer >( xSink, uno::UNO_QUERY );
730 : :
731 : 0 : if ( !xOut.is() && !xDataSink.is() && ( !xDataStreamer.is() || !xDataStreamer->getStream().is() ) )
732 : 0 : return sal_False;
733 : :
734 : 0 : if ( xDataStreamer.is() && !xOut.is() )
735 : 0 : xOut = xDataStreamer->getStream()->getOutputStream();
736 : :
737 : : try
738 : : {
739 : 0 : libcmis::Document* document = dynamic_cast< libcmis::Document* >( getObject().get() );
740 : 0 : boost::shared_ptr< istream > aIn = document->getContentStream( );
741 : :
742 : 0 : uno::Reference< io::XInputStream > xIn = new ucbhelper::StdInputStream( aIn );
743 : 0 : if( !xIn.is( ) )
744 : 0 : return sal_False;
745 : :
746 : 0 : if ( xDataSink.is() )
747 : 0 : xDataSink->setInputStream( xIn );
748 : 0 : else if ( xOut.is() )
749 : 0 : copyData( xIn, xOut );
750 : : }
751 : 0 : catch ( const libcmis::Exception& e )
752 : : {
753 : : SAL_INFO( "cmisucp", "Unexpected libcmis exception: " << e.what( ) );
754 : : ucbhelper::cancelCommandExecution(
755 : : ucb::IOErrorCode_GENERAL,
756 : : uno::Sequence< uno::Any >( 0 ),
757 : : xEnv,
758 : 0 : rtl::OUString::createFromAscii( e.what() ) );
759 : : }
760 : :
761 : 0 : return sal_True;
762 : : }
763 : :
764 : 0 : uno::Sequence< beans::Property > Content::getProperties(
765 : : const uno::Reference< ucb::XCommandEnvironment > & xEnv )
766 : : {
767 : 0 : resetAuthProvider( xEnv );
768 : :
769 : : static const beans::Property aGenericProperties[] =
770 : : {
771 : : beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ),
772 : 0 : -1, getCppuBooleanType(),
773 : : beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
774 : : beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ),
775 : 0 : -1, getCppuBooleanType(),
776 : : beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
777 : : beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ),
778 : 0 : -1, getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
779 : : beans::PropertyAttribute::BOUND ),
780 : : beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TitleOnServer" ) ),
781 : 0 : -1, getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
782 : : beans::PropertyAttribute::BOUND ),
783 : : beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsReadOnly" ) ),
784 : 0 : -1, getCppuBooleanType(),
785 : : beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
786 : : beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DateCreated" ) ),
787 : 0 : -1, getCppuType( static_cast< const util::DateTime * >( 0 ) ),
788 : : beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
789 : : beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DateModified" ) ),
790 : 0 : -1, getCppuType( static_cast< const util::DateTime * >( 0 ) ),
791 : : beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
792 : : beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Size" ) ),
793 : 0 : -1, getCppuType( static_cast< const sal_Int64 * >( 0 ) ),
794 : : beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
795 : : beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CreatableContentsInfo" ) ),
796 : 0 : -1, getCppuType( static_cast< const uno::Sequence< ucb::ContentInfo > * >( 0 ) ),
797 : : beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
798 : : beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ),
799 : 0 : -1, getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
800 : : beans::PropertyAttribute::BOUND ),
801 : 0 : };
802 : :
803 : 0 : const int nProps = SAL_N_ELEMENTS(aGenericProperties);
804 : 0 : return uno::Sequence< beans::Property > ( aGenericProperties, nProps );
805 : : }
806 : :
807 : 0 : uno::Sequence< ucb::CommandInfo > Content::getCommands(
808 : : const uno::Reference< ucb::XCommandEnvironment > & xEnv )
809 : : {
810 : 0 : resetAuthProvider( xEnv );
811 : :
812 : : static ucb::CommandInfo aCommandInfoTable[] =
813 : : {
814 : : // Required commands
815 : : ucb::CommandInfo
816 : : ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ),
817 : 0 : -1, getCppuVoidType() ),
818 : : ucb::CommandInfo
819 : : ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ),
820 : 0 : -1, getCppuVoidType() ),
821 : : ucb::CommandInfo
822 : : ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ),
823 : 0 : -1, getCppuType( static_cast<uno::Sequence< beans::Property > * >( 0 ) ) ),
824 : : ucb::CommandInfo
825 : : ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ),
826 : 0 : -1, getCppuType( static_cast<uno::Sequence< beans::PropertyValue > * >( 0 ) ) ),
827 : :
828 : : // Optional standard commands
829 : : ucb::CommandInfo
830 : : ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "delete" ) ),
831 : 0 : -1, getCppuBooleanType() ),
832 : : ucb::CommandInfo
833 : : ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert" ) ),
834 : 0 : -1, getCppuType( static_cast<ucb::InsertCommandArgument * >( 0 ) ) ),
835 : : ucb::CommandInfo
836 : : ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ),
837 : 0 : -1, getCppuType( static_cast<ucb::OpenCommandArgument2 * >( 0 ) ) ),
838 : :
839 : : // Folder Only, omitted if not a folder
840 : : ucb::CommandInfo
841 : : ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "transfer" ) ),
842 : 0 : -1, getCppuType( static_cast<ucb::TransferInfo * >( 0 ) ) ),
843 : : ucb::CommandInfo
844 : : ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "createNewContent" ) ),
845 : 0 : -1, getCppuType( static_cast<ucb::ContentInfo * >( 0 ) ) )
846 : 0 : };
847 : :
848 : 0 : const int nProps = SAL_N_ELEMENTS(aCommandInfoTable);
849 : 0 : return uno::Sequence< ucb::CommandInfo >(aCommandInfoTable, isFolder(xEnv) ? nProps : nProps - 2);
850 : : }
851 : :
852 : 0 : ::rtl::OUString Content::getParentURL( )
853 : : {
854 : 0 : rtl::OUString sRet;
855 : :
856 : : SAL_INFO( "cmisucp", "Content::getParentURL()" );
857 : :
858 : 0 : string parentPath;
859 : : try
860 : : {
861 : 0 : libcmis::ObjectPtr pObj = getObject( );
862 : 0 : libcmis::Document* document = dynamic_cast< libcmis::Document* >( getObject( ).get( ) );
863 : 0 : if ( NULL != document )
864 : : {
865 : 0 : vector< boost::shared_ptr< libcmis::Folder > > parents = document->getParents( );
866 : 0 : if ( !parents.empty( ) )
867 : 0 : parentPath = parents.front( )->getPath( );
868 : : }
869 : : else
870 : : {
871 : 0 : libcmis::Folder* folder = dynamic_cast< libcmis::Folder* >( getObject( ).get( ) );
872 : 0 : if ( NULL != folder )
873 : 0 : parentPath = folder->getFolderParent( )->getPath( );
874 : 0 : }
875 : : }
876 : 0 : catch ( const libcmis::Exception & )
877 : : {
878 : : // We may have an exception if we don't have the rights to
879 : : // get the parents
880 : : }
881 : :
882 : 0 : if ( !parentPath.empty() )
883 : : {
884 : 0 : URL aUrl( m_sURL );
885 : 0 : aUrl.setObjectPath( STD_TO_OUSTR( parentPath ) );
886 : 0 : sRet = aUrl.asString( );
887 : : }
888 : : else
889 : : {
890 : 0 : INetURLObject aUrl( m_sURL );
891 : 0 : if ( aUrl.getSegmentCount( ) > 0 )
892 : : {
893 : 0 : URL aCmisUrl( m_sURL );
894 : 0 : aUrl.removeSegment( );
895 : 0 : aCmisUrl.setObjectPath( aUrl.GetURLPath( INetURLObject::NO_DECODE ) );
896 : 0 : sRet = aCmisUrl.asString( );
897 : 0 : }
898 : : }
899 : :
900 : 0 : return sRet;
901 : : }
902 : :
903 : 0 : XTYPEPROVIDER_COMMON_IMPL( Content );
904 : :
905 : 0 : void SAL_CALL Content::acquire() throw()
906 : : {
907 : 0 : ContentImplHelper::acquire();
908 : 0 : }
909 : :
910 : 0 : void SAL_CALL Content::release() throw()
911 : : {
912 : 0 : ContentImplHelper::release();
913 : 0 : }
914 : :
915 : 0 : uno::Any SAL_CALL Content::queryInterface( const uno::Type & rType ) throw ( uno::RuntimeException )
916 : : {
917 : 0 : uno::Any aRet = cppu::queryInterface( rType, static_cast< ucb::XContentCreator * >( this ) );
918 : 0 : return aRet.hasValue() ? aRet : ContentImplHelper::queryInterface(rType);
919 : : }
920 : :
921 : 0 : rtl::OUString SAL_CALL Content::getImplementationName() throw( uno::RuntimeException )
922 : : {
923 : 0 : return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.CmisContent"));
924 : : }
925 : :
926 : 0 : uno::Sequence< rtl::OUString > SAL_CALL Content::getSupportedServiceNames()
927 : : throw( uno::RuntimeException )
928 : : {
929 : 0 : uno::Sequence< rtl::OUString > aSNS( 1 );
930 : 0 : aSNS.getArray()[ 0 ] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ucb.CmisContent"));
931 : 0 : return aSNS;
932 : : }
933 : :
934 : 0 : rtl::OUString SAL_CALL Content::getContentType() throw( uno::RuntimeException )
935 : : {
936 : 0 : return isFolder(uno::Reference< ucb::XCommandEnvironment >())
937 : : ? rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( CMIS_FOLDER_TYPE ))
938 : 0 : : rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( CMIS_FILE_TYPE ));
939 : : }
940 : :
941 : 0 : uno::Any SAL_CALL Content::execute(
942 : : const ucb::Command& aCommand,
943 : : sal_Int32 /*CommandId*/,
944 : : const uno::Reference< ucb::XCommandEnvironment >& xEnv )
945 : : throw( uno::Exception, ucb::CommandAbortedException, uno::RuntimeException )
946 : : {
947 : : SAL_INFO( "cmisucp", "Content::execute( ) - " << aCommand.Name );
948 : 0 : resetAuthProvider( xEnv );
949 : :
950 : 0 : uno::Any aRet;
951 : :
952 : 0 : if ( aCommand.Name == "getPropertyValues" )
953 : : {
954 : 0 : uno::Sequence< beans::Property > Properties;
955 : 0 : if ( !( aCommand.Argument >>= Properties ) )
956 : 0 : ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv );
957 : 0 : aRet <<= getPropertyValues( Properties, xEnv );
958 : : }
959 : 0 : else if ( aCommand.Name == "getPropertySetInfo" )
960 : 0 : aRet <<= getPropertySetInfo( xEnv, sal_False );
961 : 0 : else if ( aCommand.Name == "getCommandInfo" )
962 : 0 : aRet <<= getCommandInfo( xEnv, sal_False );
963 : 0 : else if ( aCommand.Name == "open" )
964 : : {
965 : 0 : ucb::OpenCommandArgument2 aOpenCommand;
966 : 0 : if ( !( aCommand.Argument >>= aOpenCommand ) )
967 : 0 : ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv );
968 : 0 : aRet = open( aOpenCommand, xEnv );
969 : : }
970 : 0 : else if ( aCommand.Name == "transfer" )
971 : : {
972 : 0 : ucb::TransferInfo transferArgs;
973 : 0 : if ( !( aCommand.Argument >>= transferArgs ) )
974 : 0 : ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv );
975 : 0 : transfer( transferArgs, xEnv );
976 : : }
977 : 0 : else if ( aCommand.Name == "setPropertyValues" )
978 : : {
979 : 0 : uno::Sequence< beans::PropertyValue > aProperties;
980 : 0 : if ( !( aCommand.Argument >>= aProperties ) || !aProperties.getLength() )
981 : 0 : ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv );
982 : 0 : aRet <<= setPropertyValues( aProperties, xEnv );
983 : : }
984 : 0 : else if (aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "createNewContent" ) )
985 : 0 : && isFolder( xEnv ) )
986 : : {
987 : 0 : ucb::ContentInfo arg;
988 : 0 : if ( !( aCommand.Argument >>= arg ) )
989 : 0 : ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv );
990 : 0 : aRet <<= createNewContent( arg );
991 : : }
992 : 0 : else if ( aCommand.Name == "insert" )
993 : : {
994 : 0 : ucb::InsertCommandArgument arg;
995 : 0 : if ( !( aCommand.Argument >>= arg ) )
996 : 0 : ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv );
997 : 0 : insert( arg.Data, arg.ReplaceExisting, xEnv );
998 : : }
999 : 0 : else if ( aCommand.Name == "delete" )
1000 : : {
1001 : : try
1002 : : {
1003 : 0 : if ( !isFolder( xEnv ) )
1004 : : {
1005 : 0 : getObject( )->remove( );
1006 : : }
1007 : : else
1008 : : {
1009 : 0 : libcmis::Folder* folder = dynamic_cast< libcmis::Folder* >( getObject( ).get() );
1010 : 0 : folder->removeTree( );
1011 : : }
1012 : : }
1013 : 0 : catch ( const libcmis::Exception& e )
1014 : : {
1015 : : SAL_INFO( "cmisucp", "Unexpected libcmis exception: " << e.what( ) );
1016 : : ucbhelper::cancelCommandExecution(
1017 : : ucb::IOErrorCode_GENERAL,
1018 : : uno::Sequence< uno::Any >( 0 ),
1019 : : xEnv,
1020 : 0 : rtl::OUString::createFromAscii( e.what() ) );
1021 : : }
1022 : : }
1023 : : else
1024 : : {
1025 : : SAL_INFO( "cmisucp", "Unknown command to execute" );
1026 : :
1027 : : ucbhelper::cancelCommandExecution
1028 : : ( uno::makeAny( ucb::UnsupportedCommandException
1029 : : ( rtl::OUString(),
1030 : : static_cast< cppu::OWeakObject * >( this ) ) ),
1031 : 0 : xEnv );
1032 : : }
1033 : :
1034 : 0 : return aRet;
1035 : : }
1036 : :
1037 : 0 : void SAL_CALL Content::abort( sal_Int32 /*CommandId*/ ) throw( uno::RuntimeException )
1038 : : {
1039 : : SAL_INFO( "cmisucp", "TODO - Content::abort()" );
1040 : : // TODO Implement me
1041 : 0 : }
1042 : :
1043 : 0 : uno::Sequence< ucb::ContentInfo > SAL_CALL Content::queryCreatableContentsInfo()
1044 : : throw( uno::RuntimeException )
1045 : : {
1046 : 0 : return queryCreatableContentsInfo( uno::Reference< ucb::XCommandEnvironment >() );
1047 : : }
1048 : :
1049 : 0 : uno::Reference< ucb::XContent > SAL_CALL Content::createNewContent(
1050 : : const ucb::ContentInfo& Info ) throw( uno::RuntimeException )
1051 : : {
1052 : : bool create_document;
1053 : :
1054 : 0 : if ( Info.Type == CMIS_FILE_TYPE )
1055 : 0 : create_document = true;
1056 : 0 : else if ( Info.Type == CMIS_FOLDER_TYPE )
1057 : 0 : create_document = false;
1058 : : else
1059 : : {
1060 : : SAL_INFO( "cmisucp", "Unknown type of content to create" );
1061 : 0 : return uno::Reference< ucb::XContent >();
1062 : : }
1063 : :
1064 : 0 : rtl::OUString sParentURL = m_xIdentifier->getContentIdentifier();
1065 : 0 : URL aParentURL( sParentURL );
1066 : :
1067 : : // Set the parent URL for the transient objects
1068 : 0 : uno::Reference< ucb::XContentIdentifier > xId(new ::ucbhelper::ContentIdentifier(m_xSMgr, sParentURL));
1069 : :
1070 : : try
1071 : : {
1072 : 0 : return new ::cmis::Content( m_xSMgr, m_pProvider, xId, !create_document );
1073 : : }
1074 : 0 : catch ( ucb::ContentCreationException & )
1075 : : {
1076 : 0 : return uno::Reference< ucb::XContent >();
1077 : 0 : }
1078 : : }
1079 : :
1080 : 0 : uno::Sequence< uno::Type > SAL_CALL Content::getTypes() throw( uno::RuntimeException )
1081 : : {
1082 : 0 : if ( isFolder( uno::Reference< ucb::XCommandEnvironment >() ) )
1083 : : {
1084 : : static cppu::OTypeCollection aFolderCollection
1085 : 0 : (CPPU_TYPE_REF( lang::XTypeProvider ),
1086 : 0 : CPPU_TYPE_REF( lang::XServiceInfo ),
1087 : 0 : CPPU_TYPE_REF( lang::XComponent ),
1088 : 0 : CPPU_TYPE_REF( ucb::XContent ),
1089 : 0 : CPPU_TYPE_REF( ucb::XCommandProcessor ),
1090 : 0 : CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
1091 : 0 : CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
1092 : 0 : CPPU_TYPE_REF( beans::XPropertyContainer ),
1093 : 0 : CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
1094 : 0 : CPPU_TYPE_REF( container::XChild ),
1095 : 0 : CPPU_TYPE_REF( ucb::XContentCreator ) );
1096 : 0 : return aFolderCollection.getTypes();
1097 : : }
1098 : : else
1099 : : {
1100 : : static cppu::OTypeCollection aFileCollection
1101 : 0 : (CPPU_TYPE_REF( lang::XTypeProvider ),
1102 : 0 : CPPU_TYPE_REF( lang::XServiceInfo ),
1103 : 0 : CPPU_TYPE_REF( lang::XComponent ),
1104 : 0 : CPPU_TYPE_REF( ucb::XContent ),
1105 : 0 : CPPU_TYPE_REF( ucb::XCommandProcessor ),
1106 : 0 : CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
1107 : 0 : CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
1108 : 0 : CPPU_TYPE_REF( beans::XPropertyContainer ),
1109 : 0 : CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
1110 : 0 : CPPU_TYPE_REF( container::XChild ) );
1111 : :
1112 : 0 : return aFileCollection.getTypes();
1113 : : }
1114 : : }
1115 : :
1116 : :
1117 : 0 : uno::Sequence< ucb::ContentInfo > Content::queryCreatableContentsInfo(
1118 : : const uno::Reference< ucb::XCommandEnvironment >& xEnv)
1119 : : throw( uno::RuntimeException )
1120 : : {
1121 : 0 : resetAuthProvider( xEnv );
1122 : 0 : if ( isFolder( xEnv ) )
1123 : : {
1124 : 0 : uno::Sequence< ucb::ContentInfo > seq(2);
1125 : :
1126 : : // Minimum set of props we really need
1127 : 0 : uno::Sequence< beans::Property > props( 1 );
1128 : 0 : props[0] = beans::Property(
1129 : : rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Title")),
1130 : : -1,
1131 : 0 : getCppuType( static_cast< rtl::OUString* >( 0 ) ),
1132 : 0 : beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND );
1133 : :
1134 : : // file
1135 : 0 : seq[0].Type = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( CMIS_FILE_TYPE ));
1136 : 0 : seq[0].Attributes = ( ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM |
1137 : 0 : ucb::ContentInfoAttribute::KIND_DOCUMENT );
1138 : 0 : seq[0].Properties = props;
1139 : :
1140 : : // folder
1141 : 0 : seq[1].Type = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( CMIS_FOLDER_TYPE ));
1142 : 0 : seq[1].Attributes = ucb::ContentInfoAttribute::KIND_FOLDER;
1143 : 0 : seq[1].Properties = props;
1144 : :
1145 : 0 : return seq;
1146 : : }
1147 : : else
1148 : : {
1149 : 0 : return uno::Sequence< ucb::ContentInfo >();
1150 : : }
1151 : : }
1152 : :
1153 : 0 : list< uno::Reference< ucb::XContent > > Content::getChildren( )
1154 : : {
1155 : 0 : list< uno::Reference< ucb::XContent > > results;
1156 : : SAL_INFO( "cmisucp", "Content::getChildren() " << m_sURL );
1157 : :
1158 : 0 : libcmis::Folder* pFolder = dynamic_cast< libcmis::Folder* >( getObject( ).get( ) );
1159 : 0 : if ( NULL != pFolder )
1160 : : {
1161 : : // Get the children from pObject
1162 : : try
1163 : : {
1164 : 0 : vector< libcmis::ObjectPtr > children = pFolder->getChildren( );
1165 : :
1166 : : // Loop over the results
1167 : 0 : for ( vector< libcmis::ObjectPtr >::iterator it = children.begin();
1168 : 0 : it != children.end(); ++it )
1169 : : {
1170 : : // TODO Cache the objects
1171 : :
1172 : 0 : URL aUrl( m_sURL );
1173 : 0 : rtl::OUString sPath( m_sObjectPath );
1174 : 0 : if ( sPath[sPath.getLength( ) - 1] != '/' )
1175 : 0 : sPath += "/";
1176 : 0 : sPath += STD_TO_OUSTR( ( *it )->getName( ) );
1177 : 0 : aUrl.setObjectPath( sPath );
1178 : 0 : uno::Reference< ucb::XContentIdentifier > xId = new ucbhelper::ContentIdentifier( aUrl.asString( ) );
1179 : 0 : uno::Reference< ucb::XContent > xContent = new Content( m_xSMgr, m_pProvider, xId, *it );
1180 : :
1181 : 0 : results.push_back( xContent );
1182 : 0 : }
1183 : : }
1184 : 0 : catch ( const libcmis::Exception& e )
1185 : : {
1186 : : SAL_INFO( "cmisucp", "Exception thrown: " << e.what() );
1187 : : }
1188 : : }
1189 : :
1190 : 0 : return results;
1191 : : }
1192 : :
1193 : 0 : void Content::setCmisProperty( std::string sName, std::string sValue )
1194 : : {
1195 : 0 : if ( m_pObjectType.get( ) )
1196 : : {
1197 : 0 : map< string, libcmis::PropertyPtr >::iterator propIt = m_pObjectProps.find( sName );
1198 : 0 : vector< string > values;
1199 : 0 : values.push_back( sValue );
1200 : :
1201 : 0 : if ( propIt == m_pObjectProps.end( ) && m_pObjectType.get( ) )
1202 : : {
1203 : 0 : map< string, libcmis::PropertyTypePtr > propsTypes = m_pObjectType->getPropertiesTypes( );
1204 : 0 : map< string, libcmis::PropertyTypePtr >::iterator typeIt = propsTypes.find( sName );
1205 : :
1206 : 0 : if ( typeIt != propsTypes.end( ) )
1207 : : {
1208 : 0 : libcmis::PropertyTypePtr propType = typeIt->second;
1209 : 0 : libcmis::PropertyPtr property( new libcmis::Property( propType, values ) );
1210 : 0 : m_pObjectProps.insert( pair< string, libcmis::PropertyPtr >( sName, property ) );
1211 : 0 : }
1212 : : }
1213 : 0 : else if ( propIt != m_pObjectProps.end( ) )
1214 : : {
1215 : 0 : propIt->second->setValues( values );
1216 : 0 : }
1217 : : }
1218 : 0 : }
1219 : 0 : }
1220 : :
1221 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|