LibreOffice Module ucb (master)  1
neon/webdavcontentcaps.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * Copyright 2000, 2010 Oracle and/or its affiliates.
7  *
8  * OpenOffice.org - a multi-platform office productivity suite
9  *
10  * This file is part of OpenOffice.org.
11  *
12  * OpenOffice.org is free software: you can redistribute it and/or modify
13  * it under the terms of the GNU Lesser General Public License version 3
14  * only, as published by the Free Software Foundation.
15  *
16  * OpenOffice.org is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU Lesser General Public License version 3 for more details
20  * (a copy is included in the LICENSE file that accompanied this code).
21  *
22  * You should have received a copy of the GNU Lesser General Public License
23  * version 3 along with OpenOffice.org. If not, see
24  * <http://www.openoffice.org/license.html>
25  * for a copy of the LGPLv3 License.
26  *
27  ************************************************************************/
28 
29 /**************************************************************************
30  TODO
31  **************************************************************************
32 
33  *************************************************************************/
34 
35 #include <memory>
36 #include <set>
37 #include <com/sun/star/beans/Property.hpp>
38 #include <com/sun/star/beans/PropertyAttribute.hpp>
39 #include <com/sun/star/beans/PropertyValue.hpp>
40 #include <com/sun/star/ucb/CommandInfo.hpp>
41 #include <com/sun/star/ucb/ContentInfo.hpp>
42 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
43 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
44 #include <com/sun/star/ucb/PostCommandArgument2.hpp>
45 #include <com/sun/star/ucb/PropertyCommandArgument.hpp>
46 #include <com/sun/star/ucb/TransferInfo.hpp>
47 #include <com/sun/star/uno/Sequence.hxx>
48 #include <com/sun/star/util/DateTime.hpp>
49 #include <com/sun/star/ucb/Link.hpp>
50 #include <com/sun/star/ucb/Lock.hpp>
51 #include <com/sun/star/ucb/LockEntry.hpp>
52 #include "webdavcontent.hxx"
53 #include "webdavprovider.hxx"
54 #include "ContentProperties.hxx"
55 #include "PropfindCache.hxx"
56 
57 using namespace com::sun::star;
58 using namespace webdav_ucp;
59 
60 
61 // ContentProvider implementation.
62 
63 
64 void ContentProvider::getProperty(
65  const OUString & rPropName, beans::Property & rProp )
66 {
67  if ( !m_pProps )
68  {
69  osl::MutexGuard aGuard( m_aMutex );
70  if ( !m_pProps )
71  {
72  m_pProps.reset( new PropertyMap );
73 
74 
75  // Fill map of known properties...
76 
77 
78  // Mandatory UCB properties.
79  m_pProps->insert(
80  beans::Property(
81  "ContentType",
82  -1,
84  beans::PropertyAttribute::BOUND
85  | beans::PropertyAttribute::READONLY ) );
86 
87  m_pProps->insert(
88  beans::Property(
89  "IsDocument",
90  -1,
92  beans::PropertyAttribute::BOUND
93  | beans::PropertyAttribute::READONLY ) );
94 
95  m_pProps->insert(
96  beans::Property(
97  "IsFolder",
98  -1,
100  beans::PropertyAttribute::BOUND
101  | beans::PropertyAttribute::READONLY ) );
102 
103  m_pProps->insert(
104  beans::Property(
105  "Title",
106  -1,
108  beans::PropertyAttribute::BOUND ) );
109 
110  // Optional UCB properties.
111 
112  m_pProps->insert(
113  beans::Property(
114  "DateCreated",
115  -1,
117  beans::PropertyAttribute::BOUND
118  | beans::PropertyAttribute::READONLY ) );
119 
120  m_pProps->insert(
121  beans::Property(
122  "DateModified",
123  -1,
125  beans::PropertyAttribute::BOUND
126  | beans::PropertyAttribute::READONLY ) );
127 
128  m_pProps->insert(
129  beans::Property(
130  "MediaType",
131  -1,
133  beans::PropertyAttribute::BOUND
134  | beans::PropertyAttribute::READONLY ) );
135 
136  m_pProps->insert(
137  beans::Property(
138  "Size",
139  -1,
141  beans::PropertyAttribute::BOUND
142  | beans::PropertyAttribute::READONLY ) );
143 
144  m_pProps->insert(
145  beans::Property(
146  "BaseURI",
147  -1,
149  beans::PropertyAttribute::BOUND
150  | beans::PropertyAttribute::READONLY ) );
151 
152  m_pProps->insert(
153  beans::Property(
154  "CreatableContentsInfo",
155  -1,
157  uno::Sequence< ucb::ContentInfo >>::get(),
158  beans::PropertyAttribute::BOUND
159  | beans::PropertyAttribute::READONLY ) );
160 
161  // Standard DAV properties.
162 
163  m_pProps->insert(
164  beans::Property(
165  DAVProperties::CREATIONDATE,
166  -1,
168  beans::PropertyAttribute::BOUND
169  | beans::PropertyAttribute::READONLY ) );
170 
171  m_pProps->insert(
172  beans::Property(
173  DAVProperties::DISPLAYNAME,
174  -1,
176  beans::PropertyAttribute::BOUND ) );
177 
178  m_pProps->insert(
179  beans::Property(
180  DAVProperties::GETCONTENTLANGUAGE,
181  -1,
183  beans::PropertyAttribute::BOUND
184  | beans::PropertyAttribute::READONLY ) );
185 
186  m_pProps->insert(
187  beans::Property(
188  DAVProperties::GETCONTENTLENGTH,
189  -1,
191  beans::PropertyAttribute::BOUND
192  | beans::PropertyAttribute::READONLY ) );
193 
194  m_pProps->insert(
195  beans::Property(
196  DAVProperties::GETCONTENTTYPE ,
197  -1,
199  beans::PropertyAttribute::BOUND
200  | beans::PropertyAttribute::READONLY ) );
201 
202  m_pProps->insert(
203  beans::Property(
204  DAVProperties::GETETAG,
205  -1,
207  beans::PropertyAttribute::BOUND
208  | beans::PropertyAttribute::READONLY ) );
209 
210  m_pProps->insert(
211  beans::Property(
212  DAVProperties::GETLASTMODIFIED,
213  -1,
215  beans::PropertyAttribute::BOUND
216  | beans::PropertyAttribute::READONLY ) );
217 
218  m_pProps->insert(
219  beans::Property(
220  DAVProperties::LOCKDISCOVERY,
221  -1,
223  uno::Sequence< ucb::Lock >>::get(),
224  beans::PropertyAttribute::BOUND
225  | beans::PropertyAttribute::READONLY ) );
226 
227  m_pProps->insert(
228  beans::Property(
229  DAVProperties::RESOURCETYPE,
230  -1,
232  beans::PropertyAttribute::BOUND
233  | beans::PropertyAttribute::READONLY ) );
234 
235  m_pProps->insert(
236  beans::Property(
237  DAVProperties::SOURCE,
238  -1,
239  cppu::UnoType<uno::Sequence< ucb::Link >>::get(),
240  beans::PropertyAttribute::BOUND ) );
241 
242  m_pProps->insert(
243  beans::Property(
244  DAVProperties::SUPPORTEDLOCK,
245  -1,
246  cppu::UnoType<uno::Sequence< ucb::LockEntry >>::get(),
247  beans::PropertyAttribute::BOUND
248  | beans::PropertyAttribute::READONLY ) );
249 
250  m_pProps->insert(
251  beans::Property(
252  DAVProperties::EXECUTABLE,
253  -1,
255  beans::PropertyAttribute::BOUND ) );
256  }
257  }
258 
259 
260  // Lookup property.
261 
262 
263  beans::Property aProp;
264  aProp.Name = rPropName;
265  const PropertyMap::const_iterator it = m_pProps->find( aProp );
266  if ( it != m_pProps->end() )
267  {
268  rProp = *it;
269  }
270  else
271  {
272  // All unknown props are treated as:
273  rProp = beans::Property(
274  rPropName,
275  - 1,
277  beans::PropertyAttribute::BOUND );
278  }
279 }
280 
281 
283 
284 // static
285 void Content::removeCachedPropertyNames( const OUString & rURL )
286 {
287  aStaticPropertyNamesCache.removeCachedPropertyNames( rURL );
288 }
289 
290 // Content implementation.
291 
292 
293 // virtual
294 uno::Sequence< beans::Property > Content::getProperties(
295  const uno::Reference< ucb::XCommandEnvironment > & xEnv )
296 {
297  bool bTransient;
298  std::unique_ptr< DAVResourceAccess > xResAccess;
299  std::unique_ptr< ContentProperties > xCachedProps;
301 
302  {
303  osl::Guard< osl::Mutex > aGuard( m_aMutex );
304 
305  bTransient = m_bTransient;
306  xResAccess.reset(new DAVResourceAccess(*m_xResAccess));
307  if (m_xCachedProps)
308  xCachedProps.reset(new ContentProperties(*m_xCachedProps));
309  xProvider.set( m_pProvider );
310  }
311 
312  std::set< OUString > aPropSet;
313 
314  // No server access for just created (not yet committed) objects.
315  // Only a minimal set of properties supported at this stage.
316  if ( !bTransient )
317  {
318  // Obtain all properties supported for this resource from server.
319  DAVOptions aDAVOptions;
320  getResourceOptions( xEnv, aDAVOptions, xResAccess );
321  // only Class 1 is needed for PROPFIND
322  if ( aDAVOptions.isClass1() )
323  {
324  try
325  {
326  std::vector< DAVResourceInfo > props;
327  OUString aTheURL( xResAccess->getURL() );
328  PropertyNames aPropsNames( aTheURL );
329 
330  if( !aStaticPropertyNamesCache.getCachedPropertyNames( aTheURL, aPropsNames ) )
331  {
332 
333  xResAccess->PROPFIND( DAVZERO, props, xEnv );
334  aPropsNames.setPropertiesNames( props );
335 
336  aStaticPropertyNamesCache.addCachePropertyNames( aPropsNames );
337  }
338  else
339  {
340  props = aPropsNames.getPropertiesNames();
341  }
342 
343  // Note: vector should contain exactly one resource info, because
344  // we used a depth of DAVZERO for PROPFIND.
345  if (props.size() == 1)
346  {
347  aPropSet.insert( (*props.begin()).properties.begin(),
348  (*props.begin()).properties.end() );
349  }
350  }
351  catch ( DAVException const & )
352  {
353  }
354  }
355  }
356 
357  // Add DAV properties, map DAV properties to UCB properties.
358  bool bHasCreationDate = false; // creationdate <-> DateCreated
359  bool bHasGetLastModified = false; // getlastmodified <-> DateModified
360  bool bHasGetContentType = false; // getcontenttype <-> MediaType
361  bool bHasGetContentLength = false; // getcontentlength <-> Size
362 
363  bool bHasContentType = false;
364  bool bHasIsDocument = false;
365  bool bHasIsFolder = false;
366  bool bHasTitle = false;
367  bool bHasBaseURI = false;
368  bool bHasDateCreated = false;
369  bool bHasDateModified = false;
370  bool bHasMediaType = false;
371  bool bHasSize = false;
372  bool bHasCreatableInfos = false;
373 
374  {
375  for ( const auto& rProp : aPropSet )
376  {
377  if ( !bHasCreationDate &&
378  ( rProp == DAVProperties::CREATIONDATE ) )
379  {
380  bHasCreationDate = true;
381  }
382  else if ( !bHasGetLastModified &&
383  ( rProp == DAVProperties::GETLASTMODIFIED ) )
384  {
385  bHasGetLastModified = true;
386  }
387  else if ( !bHasGetContentType &&
388  ( rProp == DAVProperties::GETCONTENTTYPE ) )
389  {
390  bHasGetContentType = true;
391  }
392  else if ( !bHasGetContentLength &&
393  ( rProp == DAVProperties::GETCONTENTLENGTH ) )
394  {
395  bHasGetContentLength = true;
396  }
397  else if ( !bHasContentType && rProp == "ContentType" )
398  {
399  bHasContentType = true;
400  }
401  else if ( !bHasIsDocument && rProp == "IsDocument" )
402  {
403  bHasIsDocument = true;
404  }
405  else if ( !bHasIsFolder && rProp == "IsFolder" )
406  {
407  bHasIsFolder = true;
408  }
409  else if ( !bHasTitle && rProp == "Title" )
410  {
411  bHasTitle = true;
412  }
413  else if ( !bHasBaseURI && rProp == "BaseURI" )
414  {
415  bHasBaseURI = true;
416  }
417  else if ( !bHasDateCreated && rProp == "DateCreated" )
418  {
419  bHasDateCreated = true;
420  }
421  else if ( !bHasDateModified && rProp == "DateModified" )
422  {
423  bHasDateModified = true;
424  }
425  else if ( !bHasMediaType && rProp == "MediaType" )
426  {
427  bHasMediaType = true;
428  }
429  else if ( !bHasSize && rProp == "Size" )
430  {
431  bHasSize = true;
432  }
433  else if ( !bHasCreatableInfos && rProp == "CreatableContentsInfo" )
434  {
435  bHasCreatableInfos = true;
436  }
437  }
438  }
439 
440  // Add mandatory properties.
441  if ( !bHasContentType )
442  aPropSet.insert(
443  OUString( "ContentType" ) );
444 
445  if ( !bHasIsDocument )
446  aPropSet.insert(
447  OUString( "IsDocument" ) );
448 
449  if ( !bHasIsFolder )
450  aPropSet.insert(
451  OUString( "IsFolder" ) );
452 
453  if ( !bHasTitle )
454  {
455  // Always present since it can be calculated from content's URI.
456  aPropSet.insert(
457  OUString( "Title" ) );
458  }
459 
460  // Add optional properties.
461 
462  if ( !bHasBaseURI )
463  {
464  // Always present since it can be calculated from content's URI.
465  aPropSet.insert(
466  OUString( "BaseURI" ) );
467  }
468 
469  if ( !bHasDateCreated && bHasCreationDate )
470  aPropSet.insert(
471  OUString( "DateCreated" ) );
472 
473  if ( !bHasDateModified && bHasGetLastModified )
474  aPropSet.insert(
475  OUString( "DateModified" ) );
476 
477  if ( !bHasMediaType && bHasGetContentType )
478  aPropSet.insert(
479  OUString( "MediaType" ) );
480 
481  if ( !bHasSize && bHasGetContentLength )
482  aPropSet.insert(
483  OUString( "Size" ) );
484 
485  if ( !bHasCreatableInfos )
486  aPropSet.insert(
487  OUString(
488  "CreatableContentsInfo" ) );
489 
490  // Add cached properties, if present and still missing.
491  if (xCachedProps)
492  {
493  const std::unique_ptr< PropertyValueMap > & xProps
494  = xCachedProps->getProperties();
495 
496  for ( const auto& rEntry : *xProps )
497  aPropSet.insert( rEntry.first );
498  }
499 
500  // std::set -> uno::Sequence
501  sal_Int32 nCount = aPropSet.size();
502  uno::Sequence< beans::Property > aProperties( nCount );
503 
504  sal_Int32 n = 0;
505  beans::Property aProp;
506 
507  for ( const auto& rProp : aPropSet )
508  {
509  xProvider->getProperty( rProp, aProp );
510  aProperties[ n++ ] = aProp;
511  }
512 
513  return aProperties;
514 }
515 
516 
517 // virtual
518 uno::Sequence< ucb::CommandInfo > Content::getCommands(
519  const uno::Reference< ucb::XCommandEnvironment > & xEnv )
520 {
521  osl::Guard< osl::Mutex > aGuard( m_aMutex );
522 
523  uno::Sequence< ucb::CommandInfo > aCmdInfo( 10 );
524 
525 
526  // Mandatory commands
527 
528 
529  aCmdInfo[ 0 ] =
530  ucb::CommandInfo(
531  "getCommandInfo",
532  -1,
534  aCmdInfo[ 1 ] =
535  ucb::CommandInfo(
536  "getPropertySetInfo",
537  -1,
539  aCmdInfo[ 2 ] =
540  ucb::CommandInfo(
541  "getPropertyValues",
542  -1,
543  cppu::UnoType<uno::Sequence< beans::Property >>::get() );
544  aCmdInfo[ 3 ] =
545  ucb::CommandInfo(
546  "setPropertyValues",
547  -1,
548  cppu::UnoType<uno::Sequence< beans::PropertyValue >>::get() );
549 
550 
551  // Optional standard commands
552 
553 
554  aCmdInfo[ 4 ] =
555  ucb::CommandInfo(
556  "delete",
557  -1,
559  aCmdInfo[ 5 ] =
560  ucb::CommandInfo(
561  "insert",
562  -1,
564  aCmdInfo[ 6 ] =
565  ucb::CommandInfo(
566  "open",
567  -1,
569 
570 
571  // New commands
572 
573 
574  aCmdInfo[ 7 ] =
575  ucb::CommandInfo(
576  "post",
577  -1,
579  aCmdInfo[ 8 ] =
580  ucb::CommandInfo(
581  "addProperty",
582  -1,
584  aCmdInfo[ 9 ] =
585  ucb::CommandInfo(
586  "removeProperty",
587  -1,
589 
590  bool bFolder = false;
591 
592  try
593  {
594  bFolder = isFolder( xEnv );
595  }
596  catch ( uno::Exception const & )
597  {
598  return aCmdInfo;
599  }
600 
601  ResourceType eType = resourceTypeForLocks( xEnv );
602  bool bSupportsLocking = ( eType == NOT_FOUND || eType == DAV );
603 
604  sal_Int32 nPos = aCmdInfo.getLength();
605  sal_Int32 nMoreCmds = ( bFolder ? 2 : 0 ) + ( bSupportsLocking ? 2 : 0 );
606  if ( nMoreCmds )
607  aCmdInfo.realloc( nPos + nMoreCmds );
608  else
609  return aCmdInfo;
610 
611  if ( bFolder )
612  {
613 
614  // Optional standard commands
615 
616 
617  aCmdInfo[ nPos ] =
618  ucb::CommandInfo(
619  "transfer",
620  -1,
622  nPos++;
623  aCmdInfo[ nPos ] =
624  ucb::CommandInfo(
625  "createNewContent",
626  -1,
628  nPos++;
629  }
630  else
631  {
632  // no document-only commands at the moment.
633  }
634 
635  if ( bSupportsLocking )
636  {
637  aCmdInfo[ nPos ] =
638  ucb::CommandInfo(
639  "lock",
640  -1,
642  nPos++;
643  aCmdInfo[ nPos ] =
644  ucb::CommandInfo(
645  "unlock",
646  -1,
648  nPos++;
649  }
650  return aCmdInfo;
651 }
652 
653 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void addCachePropertyNames(PropertyNames &rCacheElement)
std::map< sal_Int32, STLPropertyMapEntry > PropertyMap
ResourceType
DocumentType const eType
void removeCachedPropertyNames(const OUString &URL)
static PropertyNamesCache aStaticPropertyNamesCache
bool getCachedPropertyNames(const OUString &URL, PropertyNames &rCacheElement)
sal_Int32 nPos
#define NOT_FOUND