1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: localfilelayer.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_configmgr.hxx"
33 #include "localfilelayer.hxx"
34 #include "localoutputstream.hxx"
35 #include "oslstream.hxx"
36 #include <rtl/ustrbuf.hxx>
37 #include <com/sun/star/io/XActiveDataSource.hpp>
38 #include <com/sun/star/io/XActiveDataSink.hpp>
39 #include <com/sun/star/configuration/backend/BackendAccessException.hpp>
40 #include <com/sun/star/beans/PropertyAttribute.hpp>
42 namespace configmgr
{ namespace localbe
{
44 //==============================================================================
46 //------------------------------------------------------------------------------
48 BasicLocalFileLayer::BasicLocalFileLayer(
49 const uno::Reference
<lang::XMultiServiceFactory
>& xFactory
,
50 const rtl::OUString
& aComponentFile
)
52 , mFileUrl(aComponentFile
)
54 static const rtl::OUString
kXMLLayerParser(RTL_CONSTASCII_USTRINGPARAM(
55 "com.sun.star.configuration.backend.xml.LayerParser")) ;
57 mLayerReader
= uno::Reference
<backend::XLayer
>::query(
58 mFactory
->createInstance(kXMLLayerParser
)) ;
61 //------------------------------------------------------------------------------
63 SimpleLocalFileLayer::SimpleLocalFileLayer(
64 const uno::Reference
<lang::XMultiServiceFactory
>& xFactory
,
65 const rtl::OUString
& aComponentFile
)
66 : BasicLocalFileLayer(xFactory
,aComponentFile
)
69 //------------------------------------------------------------------------------
71 SimpleLocalFileLayer::SimpleLocalFileLayer(
72 const uno::Reference
<lang::XMultiServiceFactory
>& xFactory
,
73 const rtl::OUString
& aBaseDir
,
74 const rtl::OUString
& aComponent
)
75 : BasicLocalFileLayer(xFactory
,aBaseDir
+ aComponent
)
78 //------------------------------------------------------------------------------
80 FlatLocalFileLayer::FlatLocalFileLayer(
81 const uno::Reference
<lang::XMultiServiceFactory
>& xFactory
,
82 const rtl::OUString
& aBaseDir
,
83 const rtl::OUString
& aComponent
)
84 : BasicLocalFileLayer(xFactory
,aBaseDir
+ aComponent
)
85 , mLayerWriter( createLayerWriter() )
88 //------------------------------------------------------------------------------
90 BasicCompositeLocalFileLayer::BasicCompositeLocalFileLayer(
91 const uno::Reference
<lang::XMultiServiceFactory
>& xFactory
,
92 const rtl::OUString
& aComponentFile
)
93 : BasicLocalFileLayer(xFactory
,aComponentFile
)
96 //------------------------------------------------------------------------------
98 CompositeLocalFileLayer::CompositeLocalFileLayer(
99 const uno::Reference
<lang::XMultiServiceFactory
>& xFactory
,
100 const rtl::OUString
& aComponent
,
101 const std::vector
<rtl::OUString
>& aSublayerDirectories
)
102 : BasicCompositeLocalFileLayer(xFactory
,rtl::OUString())
104 fillSubLayerLists(aSublayerDirectories
, aComponent
) ;
106 //------------------------------------------------------------------------------
108 FullCompositeLocalFileLayer::FullCompositeLocalFileLayer(
109 const uno::Reference
<lang::XMultiServiceFactory
>& xFactory
,
110 const rtl::OUString
& aBaseDir
,
111 const rtl::OUString
& aComponent
,
112 const std::vector
<rtl::OUString
>& aSublayerDirectories
)
113 : BasicCompositeLocalFileLayer(xFactory
,aBaseDir
+ aComponent
)
114 , mLayerWriter( createLayerWriter() )
116 fillSubLayerLists(aSublayerDirectories
, aComponent
) ;
118 //------------------------------------------------------------------------------
120 BasicLocalFileLayer::~BasicLocalFileLayer() {}
121 //------------------------------------------------------------------------------
123 SimpleLocalFileLayer::~SimpleLocalFileLayer() {}
124 //------------------------------------------------------------------------------
126 FlatLocalFileLayer::~FlatLocalFileLayer() {}
127 //------------------------------------------------------------------------------
129 CompositeLocalFileLayer::~CompositeLocalFileLayer() {}
130 //------------------------------------------------------------------------------
132 FullCompositeLocalFileLayer::~FullCompositeLocalFileLayer() {}
133 //------------------------------------------------------------------------------
135 uno::Reference
<backend::XLayerHandler
> BasicLocalFileLayer::createLayerWriter()
137 static const rtl::OUString
kXMLLayerWriter(RTL_CONSTASCII_USTRINGPARAM(
138 "com.sun.star.configuration.backend.xml.LayerWriter")) ;
140 uno::Reference
< uno::XInterface
> xWriter
= mFactory
->createInstance(kXMLLayerWriter
);
142 return uno::Reference
<backend::XLayerHandler
>(xWriter
,uno::UNO_REF_QUERY_THROW
) ;
144 //------------------------------------------------------------------------------
146 static inline void readEmptyLayer(const uno::Reference
<backend::XLayerHandler
>& xHandler
)
148 OSL_ASSERT(xHandler
.is());
149 xHandler
->startLayer();
150 xHandler
->endLayer();
152 //------------------------------------------------------------------------------
154 void BasicLocalFileLayer::readData(
155 backend::XLayer
* pContext
,
156 const uno::Reference
<backend::XLayerHandler
>& xHandler
,
157 const rtl::OUString
& aFileUrl
)
158 throw ( backend::MalformedDataException
,
159 lang::NullPointerException
,
160 lang::WrappedTargetException
,
161 uno::RuntimeException
)
165 rtl::OUString
const sMessage(RTL_CONSTASCII_USTRINGPARAM(
166 "LocalFileLayer - Cannot readData: Handler is NULL."));
168 throw lang::NullPointerException(sMessage
,pContext
);
171 osl::File
blobFile(aFileUrl
) ;
172 osl::File::RC errorCode
= blobFile
.open(OpenFlag_Read
) ;
176 case osl::File::E_None
: // got it
178 uno::Reference
<io::XActiveDataSink
> xAS(mLayerReader
, uno::UNO_QUERY_THROW
);
180 uno::Reference
<io::XInputStream
> xStream( new OSLInputStreamWrapper(blobFile
) );
182 xAS
->setInputStream(xStream
);
184 mLayerReader
->readData(xHandler
) ;
188 case osl::File::E_NOENT
: // no layer => empty layer
189 readEmptyLayer(xHandler
);
194 rtl::OUStringBuffer sMsg
;
195 sMsg
.appendAscii("LocalFile Layer: Cannot open input file \"");
196 sMsg
.append(aFileUrl
);
197 sMsg
.appendAscii("\" : ");
198 sMsg
.append(FileHelper::createOSLErrorString(errorCode
));
200 io::IOException
ioe(sMsg
.makeStringAndClear(),pContext
);
202 sMsg
.appendAscii("LocalFileLayer - Cannot readData: ").append(ioe
.Message
);
203 throw backend::BackendAccessException(sMsg
.makeStringAndClear(),pContext
,uno::makeAny(ioe
));
207 //------------------------------------------------------------------------------
209 void SAL_CALL
SimpleLocalFileLayer::readData(
210 const uno::Reference
<backend::XLayerHandler
>& xHandler
)
211 throw ( backend::MalformedDataException
,
212 lang::NullPointerException
,
213 lang::WrappedTargetException
,
214 uno::RuntimeException
)
216 BasicLocalFileLayer::readData(this,xHandler
, getFileUrl()) ;
218 //------------------------------------------------------------------------------
220 void SAL_CALL
FlatLocalFileLayer::readData(
221 const uno::Reference
<backend::XLayerHandler
>& xHandler
)
222 throw ( backend::MalformedDataException
,
223 lang::NullPointerException
,
224 lang::WrappedTargetException
,
225 uno::RuntimeException
)
227 BasicLocalFileLayer::readData(this,xHandler
, getFileUrl() ) ;
229 //------------------------------------------------------------------------------
231 void SAL_CALL
CompositeLocalFileLayer::readData(
232 const uno::Reference
<backend::XLayerHandler
>& xHandler
)
233 throw ( backend::MalformedDataException
,
234 lang::NullPointerException
,
235 lang::WrappedTargetException
,
236 uno::RuntimeException
)
240 rtl::OUString
const sMessage(RTL_CONSTASCII_USTRINGPARAM(
241 "LocalFileLayer - Cannot readData: Handler is NULL."));
243 throw lang::NullPointerException(sMessage
,*this);
246 readEmptyLayer(xHandler
) ;
248 //------------------------------------------------------------------------------
250 void SAL_CALL
FullCompositeLocalFileLayer::readData(
251 const uno::Reference
<backend::XLayerHandler
>& xHandler
)
252 throw ( backend::MalformedDataException
,
253 lang::NullPointerException
,
254 lang::WrappedTargetException
,
255 uno::RuntimeException
)
257 BasicLocalFileLayer::readData(static_cast<backend::XCompositeLayer
*>(this),xHandler
, getFileUrl() ) ;
259 //------------------------------------------------------------------------------
261 void SAL_CALL
BasicCompositeLocalFileLayer::readSubLayerData(
262 backend::XCompositeLayer
* pContext
,
263 const uno::Reference
<backend::XLayerHandler
>& xHandler
,
264 const rtl::OUString
& aSubLayerId
)
265 throw ( backend::MalformedDataException
,
266 lang::IllegalArgumentException
,
267 lang::NullPointerException
,
268 lang::WrappedTargetException
,
269 uno::RuntimeException
)
273 rtl::OUString
const sMessage(RTL_CONSTASCII_USTRINGPARAM(
274 "CompositeLocalFileLayer - Cannot readSubLayerData: Handler is NULL."));
276 throw lang::NullPointerException(sMessage
,pContext
);
281 for (i
= 0 ; i
< mSubLayers
.getLength() ; ++ i
) {
282 if (mSubLayers
[i
].equals(aSubLayerId
)) { break ; }
284 if (i
== mSubLayers
.getLength())
286 rtl::OUStringBuffer message
;
288 message
.appendAscii("Sublayer Id '").append(aSubLayerId
) ;
289 message
.appendAscii("' is unknown") ;
290 throw lang::IllegalArgumentException(message
.makeStringAndClear(),
293 if (mSubLayerFiles
[i
].getLength() != 0)
294 BasicLocalFileLayer::readData(pContext
,xHandler
, mSubLayerFiles
[i
]) ;
296 readEmptyLayer(xHandler
);
298 //------------------------------------------------------------------------------
300 void SAL_CALL
CompositeLocalFileLayer::readSubLayerData(
301 const uno::Reference
<backend::XLayerHandler
>& xHandler
,
302 const rtl::OUString
& aSubLayerId
)
303 throw ( backend::MalformedDataException
,
304 lang::IllegalArgumentException
,
305 lang::NullPointerException
,
306 lang::WrappedTargetException
,
307 uno::RuntimeException
)
309 return BasicCompositeLocalFileLayer::readSubLayerData(this,xHandler
,aSubLayerId
);
311 //------------------------------------------------------------------------------
313 void SAL_CALL
FullCompositeLocalFileLayer::readSubLayerData(
314 const uno::Reference
<backend::XLayerHandler
>& xHandler
,
315 const rtl::OUString
& aSubLayerId
)
316 throw ( backend::MalformedDataException
,
317 lang::IllegalArgumentException
,
318 lang::NullPointerException
,
319 lang::WrappedTargetException
,
320 uno::RuntimeException
)
322 return BasicCompositeLocalFileLayer::readSubLayerData(this,xHandler
,aSubLayerId
);
324 //------------------------------------------------------------------------------
326 void SAL_CALL
FlatLocalFileLayer::replaceWith(
327 const uno::Reference
<backend::XLayer
>& aNewLayer
)
328 throw ( backend::MalformedDataException
,
329 lang::NullPointerException
,
330 lang::WrappedTargetException
,
331 uno::RuntimeException
)
335 rtl::OUString
const sMessage(RTL_CONSTASCII_USTRINGPARAM(
336 "LocalFileLayer - Cannot replaceWith: Replacement layer is NULL."));
338 throw lang::NullPointerException(sMessage
,*this);
340 OSL_ENSURE( !uno::Reference
<backend::XCompositeLayer
>::query(aNewLayer
).is(),
341 "Warning: correct updates with composite layers are not implemented");
343 uno::Reference
<io::XActiveDataSource
> xAS(mLayerWriter
, uno::UNO_QUERY_THROW
);
345 LocalOutputStream
* pStream
= new LocalOutputStream(getFileUrl());
346 uno::Reference
<io::XOutputStream
> xStream( pStream
);
348 xAS
->setOutputStream(xStream
);
350 aNewLayer
->readData(mLayerWriter
) ;
352 pStream
->finishOutput();
354 // clear the output stream
356 xAS
->setOutputStream(xStream
);
358 //------------------------------------------------------------------------------
360 void SAL_CALL
FullCompositeLocalFileLayer::replaceWith(
361 const uno::Reference
<backend::XLayer
>& aNewLayer
)
362 throw (backend::MalformedDataException
, lang::NullPointerException
,
363 lang::WrappedTargetException
, uno::RuntimeException
)
367 rtl::OUString
const sMessage(RTL_CONSTASCII_USTRINGPARAM(
368 "LocalFileLayer - Cannot replaceWith: Replacement layer is NULL."));
370 throw lang::NullPointerException(sMessage
,*this);
372 OSL_ENSURE( !uno::Reference
<backend::XCompositeLayer
>::query(aNewLayer
).is(),
373 "Warning: correct updates with composite layers are not implemented");
375 uno::Reference
<io::XActiveDataSource
> xAS(mLayerWriter
, uno::UNO_QUERY_THROW
);
377 LocalOutputStream
* pStream
= new LocalOutputStream(getFileUrl());
378 uno::Reference
<io::XOutputStream
> xStream( pStream
);
380 xAS
->setOutputStream(xStream
);
382 aNewLayer
->readData(mLayerWriter
) ;
384 pStream
->finishOutput();
386 // clear the output stream
388 xAS
->setOutputStream(xStream
);
390 //------------------------------------------------------------------------------
392 rtl::OUString
BasicLocalFileLayer::getTimestamp(const rtl::OUString
& aFileUrl
)
394 TimeValue timevalue
= {0,0};
395 sal_uInt64 aSize
= FileHelper::getModifyStatus(aFileUrl
,timevalue
) ;
396 oslDateTime fileStamp
;
397 rtl::OUString retCode
;
399 if (osl_getDateTimeFromTimeValue(&timevalue
, &fileStamp
))
401 // truncate to 32 bits
402 unsigned long aLongSize
= static_cast<sal_Int32
>(aSize
);
404 sal_Char asciiStamp
[50] ;
406 sprintf(asciiStamp
, "%04u%02u%02u%02u%02u%02uZ%010lu",
407 unsigned(fileStamp
.Year
), unsigned(fileStamp
.Month
), unsigned(fileStamp
.Day
),
408 unsigned(fileStamp
.Hours
), unsigned(fileStamp
.Minutes
), unsigned(fileStamp
.Seconds
),
410 retCode
= rtl::OUString::createFromAscii(asciiStamp
) ;
414 //------------------------------------------------------------------------------
416 rtl::OUString
SimpleLocalFileLayer::getTimestamp()
417 throw (uno::RuntimeException
)
419 rtl::OUString sStamp
= BasicLocalFileLayer::getTimestamp(getFileUrl());
423 //------------------------------------------------------------------------------
425 rtl::OUString
FlatLocalFileLayer::getTimestamp()
426 throw (uno::RuntimeException
)
428 rtl::OUString sStamp
= BasicLocalFileLayer::getTimestamp(getFileUrl());
432 //------------------------------------------------------------------------------
434 rtl::OUString
FullCompositeLocalFileLayer::getTimestamp()
435 throw (uno::RuntimeException
)
437 rtl::OUString sStamp
= BasicLocalFileLayer::getTimestamp(getFileUrl());
438 #if 0 // thus far composite layers are only manipulated via the main layer
439 for (std::vector
<rtl::OUString
>::const_iterator it
= mSubLayerFiles
.begin();
440 it
!= mSubLayerFiles
.end();
443 rtl::OUString sSublayerTime
= BasicLocalFileLayer::getTimestamp(*it
);
444 if (sStamp
< sSublayerTime
)
445 sStamp
= sSublayerTime
;
450 //------------------------------------------------------------------------------
452 void BasicCompositeLocalFileLayer::fillSubLayerLists( const std::vector
<rtl::OUString
>& aSublayerDirectories
,
453 const rtl::OUString
& aComponent
)
455 std::vector
<rtl::OUString
>::size_type
const nSublayerCount
= aSublayerDirectories
.size();
456 mSubLayers
.realloc(nSublayerCount
);
457 mSubLayerFiles
.resize(nSublayerCount
);
459 for (std::vector
<rtl::OUString
>::size_type i
= 0; i
< nSublayerCount
; ++i
)
461 mSubLayers
[i
] = FileHelper::getFileName(aSublayerDirectories
[i
]);
463 // Let's check whether the sublayer exists for the
464 // particular component.
465 rtl::OUString
subLayerFile(aSublayerDirectories
[i
] + aComponent
) ;
466 if (FileHelper::fileExists(subLayerFile
))
468 mSubLayerFiles
[i
] = subLayerFile
;
471 OSL_ASSERT(mSubLayerFiles
[i
].getLength() == 0);
474 //------------------------------------------------------------------------------
476 static bool findSubLayers(const rtl::OUString
& aResDir
,
477 std::vector
<rtl::OUString
>& aSublayerDirectories
)
479 if (aResDir
.getLength() == 0) return false;
481 // Extract the directory where the file is located
482 osl::Directory
directory(aResDir
) ;
483 if (directory
.open() != osl::Directory::E_None
) return false;
485 osl::DirectoryItem item
;
486 osl::FileStatus
status(osl_FileStatus_Mask_Type
|
487 osl_FileStatus_Mask_FileURL
) ;
489 while (directory
.getNextItem(item
) == osl::Directory::E_None
)
491 if (item
.getFileStatus(status
) == osl::Directory::E_None
)
493 if (status
.getFileType() == osl::FileStatus::Directory
)
495 aSublayerDirectories
.push_back(status
.getFileURL()) ;
499 return !aSublayerDirectories
.empty();
501 //------------------------------------------------------------------------------
503 uno::Reference
<backend::XLayer
> createReadonlyLocalFileLayer(
504 const uno::Reference
<lang::XMultiServiceFactory
>& xFactory
,
505 const rtl::OUString
& aBaseDir
,
506 const rtl::OUString
& aComponent
,
507 const rtl::OUString
& aResDir
)
509 uno::Reference
<backend::XLayer
> xResult
;
511 std::vector
<rtl::OUString
> aSublayers
;
512 if (aBaseDir
.getLength() == 0)
514 findSubLayers(aResDir
,aSublayers
);
515 xResult
.set( new CompositeLocalFileLayer(xFactory
,aComponent
,aSublayers
) );
517 else if (findSubLayers(aResDir
,aSublayers
))
519 // there is no readonly full composite layer - take the updatable one
520 backend::XCompositeLayer
* pNewLayer
=
521 new FullCompositeLocalFileLayer(xFactory
,aBaseDir
,aComponent
,aSublayers
);
522 xResult
.set( pNewLayer
);
526 xResult
.set( new SimpleLocalFileLayer(xFactory
,aBaseDir
,aComponent
) );
530 //------------------------------------------------------------------------------
532 uno::Reference
<backend::XUpdatableLayer
> createUpdatableLocalFileLayer(
533 const uno::Reference
<lang::XMultiServiceFactory
>& xFactory
,
534 const rtl::OUString
& aBaseDir
,
535 const rtl::OUString
& aComponent
,
536 const rtl::OUString
& aResDir
)
538 uno::Reference
<backend::XUpdatableLayer
> xResult
;
540 std::vector
<rtl::OUString
> aSublayers
;
541 if (findSubLayers(aResDir
,aSublayers
))
543 xResult
.set( new FullCompositeLocalFileLayer(xFactory
,aBaseDir
,aComponent
,aSublayers
) );
545 else if (aBaseDir
.getLength() != 0)
547 xResult
.set( new FlatLocalFileLayer(xFactory
,aBaseDir
,aComponent
) );
550 OSL_ENSURE(false,"WARNING: Trying to create an updatable ressource-only layer");
554 //------------------------------------------------------------------------------
555 //------------------------------------------------------------------------------
559 LAYER_PROPERTY_URL
= 1
562 #define PROPNAME( name ) rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( name ) )
563 #define PROPTYPE( type ) getCppuType( static_cast< type const *>( 0 ) )
565 // cppu::OPropertySetHelper
566 cppu::IPropertyArrayHelper
* SAL_CALL
LayerPropertyHelper::newInfoHelper()
568 com::sun::star::beans::Property properties
[] =
570 com::sun::star::beans::Property(PROPNAME("URL"), LAYER_PROPERTY_URL
, PROPTYPE(rtl::OUString
), com::sun::star::beans::PropertyAttribute::READONLY
)
573 return new cppu::OPropertyArrayHelper(properties
, sizeof(properties
)/sizeof(properties
[0]));
576 #define MESSAGE( text ) rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ERROR: Layer Properties: " text ) )
578 void SAL_CALL
LayerPropertyHelper::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle
, const uno::Any
& /*rValue*/ )
579 throw (uno::Exception
)
581 namespace beans
= com::sun::star::beans
;
585 case LAYER_PROPERTY_URL
:
586 OSL_ENSURE(false, "Error: trying to set a READONLY property");
587 throw beans::PropertyVetoException(MESSAGE("Property 'URL' is read-only"),*this);
590 OSL_ENSURE(false, "Error: trying to set an UNKNOWN property");
591 throw beans::UnknownPropertyException(MESSAGE("Trying to set an unknown property"),*this);
595 void SAL_CALL
LayerPropertyHelper::getFastPropertyValue( uno::Any
& rValue
, sal_Int32 nHandle
) const
599 case LAYER_PROPERTY_URL
:
600 rValue
= uno::makeAny( this->getLayerUrl() );
604 OSL_ENSURE(false, "Error: trying to get an UNKNOWN property");
609 //------------------------------------------------------------------------------
610 } } // configmgr.localbe