/************************************************************************* * * $RCSfile: localfilelayer.cxx,v $ * * $Revision: 1.11 $ * * last change: $Author: rt $ $Date: 2004-08-20 12:55:36 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses * * - GNU Lesser General Public License Version 2.1 * - Sun Industry Standards Source License Version 1.1 * * Sun Microsystems Inc., October, 2000 * * GNU Lesser General Public License Version 2.1 * ============================================= * Copyright 2000 by Sun Microsystems, Inc. * 901 San Antonio Road, Palo Alto, CA 94303, USA * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * * * Sun Industry Standards Source License Version 1.1 * ================================================= * The contents of this file are subject to the Sun Industry Standards * Source License Version 1.1 (the "License"); You may not use this file * except in compliance with the License. You may obtain a copy of the * License at http://www.openoffice.org/license.html. * * Software provided under this License is provided on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. * See the License for the specific provisions governing your rights and * obligations concerning the Software. * * The Initial Developer of the Original Code is: Sun Microsystems, Inc. * * Copyright: 2000 by Sun Microsystems, Inc. * * All Rights Reserved. * * Contributor(s): _______________________________________ * * ************************************************************************/ #ifndef CONFIGMGR_LOCALBE_LOCALFILELAYER_HXX_ #include "localfilelayer.hxx" #endif // CONFIGMGR_LOCALBE_LOCALFILELAYER_HXX_ #ifndef CONFIGMGR_LOCALBE_LOCALOUTPUTSTREAM_HXX_ #include "localoutputstream.hxx" #endif // CONFIGMGR_LOCALBE_LOCALOUTPUTSTREAM_HXX_ #ifndef _CONFIGMGR_OSLSTREAM_HXX_ #include "oslstream.hxx" #endif // _CONFIGMGR_OSLSTREAM_HXX_ #ifndef _RTL_USTRBUF_HXX_ #include #endif // _RTL_USTRBUF_HXX_ #ifndef _COM_SUN_STAR_IO_XACTIVEDATASOURCE_HPP_ #include #endif #ifndef _COM_SUN_STAR_IO_XACTIVEDATASINK_HPP_ #include #endif #ifndef _COM_SUN_STAR_CONFIGURATION_BACKEND_BACKENDACCESSEXCEPTION_HPP_ #include #endif #ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_ #include #endif namespace configmgr { namespace localbe { //============================================================================== //------------------------------------------------------------------------------ BasicLocalFileLayer::BasicLocalFileLayer( const uno::Reference& xFactory, const rtl::OUString& aComponentFile) : mFactory(xFactory) , mFileUrl(aComponentFile) { static const rtl::OUString kXMLLayerParser(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.backend.xml.LayerParser")) ; mLayerReader = uno::Reference::query( mFactory->createInstance(kXMLLayerParser)) ; } //------------------------------------------------------------------------------ SimpleLocalFileLayer::SimpleLocalFileLayer( const uno::Reference& xFactory, const rtl::OUString& aComponentFile) : BasicLocalFileLayer(xFactory,aComponentFile) { } //------------------------------------------------------------------------------ SimpleLocalFileLayer::SimpleLocalFileLayer( const uno::Reference& xFactory, const rtl::OUString& aBaseDir, const rtl::OUString& aComponent) : BasicLocalFileLayer(xFactory,aBaseDir + aComponent) { } //------------------------------------------------------------------------------ FlatLocalFileLayer::FlatLocalFileLayer( const uno::Reference& xFactory, const rtl::OUString& aBaseDir, const rtl::OUString& aComponent) : BasicLocalFileLayer(xFactory,aBaseDir + aComponent) , mLayerWriter( createLayerWriter() ) { } //------------------------------------------------------------------------------ BasicCompositeLocalFileLayer::BasicCompositeLocalFileLayer( const uno::Reference& xFactory, const rtl::OUString& aComponentFile) : BasicLocalFileLayer(xFactory,aComponentFile) { } //------------------------------------------------------------------------------ CompositeLocalFileLayer::CompositeLocalFileLayer( const uno::Reference& xFactory, const rtl::OUString& aComponent, const SubLayerFiles& aSublayerDirectories) : BasicCompositeLocalFileLayer(xFactory,rtl::OUString()) { fillSubLayerLists(aSublayerDirectories, aComponent) ; } //------------------------------------------------------------------------------ FullCompositeLocalFileLayer::FullCompositeLocalFileLayer( const uno::Reference& xFactory, const rtl::OUString& aBaseDir, const rtl::OUString& aComponent, const SubLayerFiles& aSublayerDirectories) : BasicCompositeLocalFileLayer(xFactory,aBaseDir + aComponent) , mLayerWriter( createLayerWriter() ) { fillSubLayerLists(aSublayerDirectories, aComponent) ; } //------------------------------------------------------------------------------ BasicLocalFileLayer::~BasicLocalFileLayer() {} //------------------------------------------------------------------------------ SimpleLocalFileLayer::~SimpleLocalFileLayer() {} //------------------------------------------------------------------------------ FlatLocalFileLayer::~FlatLocalFileLayer() {} //------------------------------------------------------------------------------ CompositeLocalFileLayer::~CompositeLocalFileLayer() {} //------------------------------------------------------------------------------ FullCompositeLocalFileLayer::~FullCompositeLocalFileLayer() {} //------------------------------------------------------------------------------ uno::Reference BasicLocalFileLayer::createLayerWriter() { static const rtl::OUString kXMLLayerWriter(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.backend.xml.LayerWriter")) ; uno::Reference< uno::XInterface > xWriter = mFactory->createInstance(kXMLLayerWriter); return uno::Reference(xWriter,uno::UNO_REF_QUERY_THROW) ; } //------------------------------------------------------------------------------ static inline void readEmptyLayer(const uno::Reference& xHandler) { OSL_ASSERT(xHandler.is()); xHandler->startLayer(); xHandler->endLayer(); } //------------------------------------------------------------------------------ void BasicLocalFileLayer::readData( backend::XLayer * pContext, const uno::Reference& xHandler, const rtl::OUString& aFileUrl) throw ( backend::MalformedDataException, lang::NullPointerException, lang::WrappedTargetException, uno::RuntimeException) { if (!xHandler.is()) { rtl::OUString const sMessage(RTL_CONSTASCII_USTRINGPARAM( "LocalFileLayer - Cannot readData: Handler is NULL.")); throw lang::NullPointerException(sMessage,pContext); } osl::File blobFile(aFileUrl) ; osl::File::RC errorCode = blobFile.open(OpenFlag_Read) ; switch (errorCode) { case osl::File::E_None: // got it { uno::Reference xAS(mLayerReader, uno::UNO_QUERY_THROW); uno::Reference xStream( new OSLInputStreamWrapper(blobFile) ); xAS->setInputStream(xStream); mLayerReader->readData(xHandler) ; } break; case osl::File::E_NOENT: // no layer => empty layer readEmptyLayer(xHandler); break; default: { rtl::OUStringBuffer sMsg; sMsg.appendAscii("LocalFile Layer: Cannot open input file \""); sMsg.append(aFileUrl); sMsg.appendAscii("\" : "); sMsg.append(FileHelper::createOSLErrorString(errorCode)); io::IOException ioe(sMsg.makeStringAndClear(),pContext); sMsg.appendAscii("LocalFileLayer - Cannot readData: ").append(ioe.Message); throw backend::BackendAccessException(sMsg.makeStringAndClear(),pContext,uno::makeAny(ioe)); } break; } } //------------------------------------------------------------------------------ void SAL_CALL SimpleLocalFileLayer::readData( const uno::Reference& xHandler) throw ( backend::MalformedDataException, lang::NullPointerException, lang::WrappedTargetException, uno::RuntimeException) { BasicLocalFileLayer::readData(this,xHandler, getFileUrl()) ; } //------------------------------------------------------------------------------ void SAL_CALL FlatLocalFileLayer::readData( const uno::Reference& xHandler) throw ( backend::MalformedDataException, lang::NullPointerException, lang::WrappedTargetException, uno::RuntimeException) { BasicLocalFileLayer::readData(this,xHandler, getFileUrl() ) ; } //------------------------------------------------------------------------------ void SAL_CALL CompositeLocalFileLayer::readData( const uno::Reference& xHandler) throw ( backend::MalformedDataException, lang::NullPointerException, lang::WrappedTargetException, uno::RuntimeException) { if (!xHandler.is()) { rtl::OUString const sMessage(RTL_CONSTASCII_USTRINGPARAM( "LocalFileLayer - Cannot readData: Handler is NULL.")); throw lang::NullPointerException(sMessage,*this); } readEmptyLayer(xHandler) ; } //------------------------------------------------------------------------------ void SAL_CALL FullCompositeLocalFileLayer::readData( const uno::Reference& xHandler) throw ( backend::MalformedDataException, lang::NullPointerException, lang::WrappedTargetException, uno::RuntimeException) { BasicLocalFileLayer::readData(static_cast(this),xHandler, getFileUrl() ) ; } //------------------------------------------------------------------------------ void SAL_CALL BasicCompositeLocalFileLayer::readSubLayerData( backend::XCompositeLayer * pContext, const uno::Reference& xHandler, const rtl::OUString& aSubLayerId) throw ( backend::MalformedDataException, lang::IllegalArgumentException, lang::NullPointerException, lang::WrappedTargetException, uno::RuntimeException) { if (!xHandler.is()) { rtl::OUString const sMessage(RTL_CONSTASCII_USTRINGPARAM( "CompositeLocalFileLayer - Cannot readSubLayerData: Handler is NULL.")); throw lang::NullPointerException(sMessage,pContext); } sal_Int32 i ; for (i = 0 ; i < mSubLayers.getLength() ; ++ i) { if (mSubLayers [i].equals(aSubLayerId)) { break ; } } if (i == mSubLayers.getLength()) { rtl::OUStringBuffer message ; message.appendAscii("Sublayer Id '").append(aSubLayerId) ; message.appendAscii("' is unknown") ; throw lang::IllegalArgumentException(message.makeStringAndClear(), pContext, 2) ; } if (mSubLayerFiles[i].getLength() != 0) BasicLocalFileLayer::readData(pContext,xHandler, mSubLayerFiles [i]) ; else readEmptyLayer(xHandler); } //------------------------------------------------------------------------------ void SAL_CALL CompositeLocalFileLayer::readSubLayerData( const uno::Reference& xHandler, const rtl::OUString& aSubLayerId) throw ( backend::MalformedDataException, lang::IllegalArgumentException, lang::NullPointerException, lang::WrappedTargetException, uno::RuntimeException) { return BasicCompositeLocalFileLayer::readSubLayerData(this,xHandler,aSubLayerId); } //------------------------------------------------------------------------------ void SAL_CALL FullCompositeLocalFileLayer::readSubLayerData( const uno::Reference& xHandler, const rtl::OUString& aSubLayerId) throw ( backend::MalformedDataException, lang::IllegalArgumentException, lang::NullPointerException, lang::WrappedTargetException, uno::RuntimeException) { return BasicCompositeLocalFileLayer::readSubLayerData(this,xHandler,aSubLayerId); } //------------------------------------------------------------------------------ void SAL_CALL FlatLocalFileLayer::replaceWith( const uno::Reference& aNewLayer) throw ( backend::MalformedDataException, lang::NullPointerException, lang::WrappedTargetException, uno::RuntimeException) { if (!aNewLayer.is()) { rtl::OUString const sMessage(RTL_CONSTASCII_USTRINGPARAM( "LocalFileLayer - Cannot replaceWith: Replacement layer is NULL.")); throw lang::NullPointerException(sMessage,*this); } OSL_ENSURE( !uno::Reference::query(aNewLayer).is(), "Warning: correct updates with composite layers are not implemented"); uno::Reference xAS(mLayerWriter, uno::UNO_QUERY_THROW); LocalOutputStream * pStream = new LocalOutputStream(getFileUrl()); uno::Reference xStream( pStream ); xAS->setOutputStream(xStream); aNewLayer->readData(mLayerWriter) ; pStream->finishOutput(); // clear the output stream xStream.clear(); xAS->setOutputStream(xStream); } //------------------------------------------------------------------------------ void SAL_CALL FullCompositeLocalFileLayer::replaceWith( const uno::Reference& aNewLayer) throw (backend::MalformedDataException, lang::NullPointerException, lang::WrappedTargetException, uno::RuntimeException) { if (!aNewLayer.is()) { rtl::OUString const sMessage(RTL_CONSTASCII_USTRINGPARAM( "LocalFileLayer - Cannot replaceWith: Replacement layer is NULL.")); throw lang::NullPointerException(sMessage,*this); } OSL_ENSURE( !uno::Reference::query(aNewLayer).is(), "Warning: correct updates with composite layers are not implemented"); uno::Reference xAS(mLayerWriter, uno::UNO_QUERY_THROW); LocalOutputStream * pStream = new LocalOutputStream(getFileUrl()); uno::Reference xStream( pStream ); xAS->setOutputStream(xStream); aNewLayer->readData(mLayerWriter) ; pStream->finishOutput(); // clear the output stream xStream.clear(); xAS->setOutputStream(xStream); } //------------------------------------------------------------------------------ rtl::OUString BasicLocalFileLayer::getTimestamp(const rtl::OUString& aFileUrl) { TimeValue timevalue = {0,0}; sal_uInt64 aSize = FileHelper::getModifyStatus(aFileUrl,timevalue) ; oslDateTime fileStamp ; rtl::OUString retCode ; if (osl_getDateTimeFromTimeValue(&timevalue, &fileStamp)) { // truncate to 32 bits unsigned long aLongSize = static_cast(aSize); sal_Char asciiStamp [50] ; sprintf(asciiStamp, "%04u%02u%02u%02u%02u%02uZ%010lu", unsigned(fileStamp.Year), unsigned(fileStamp.Month), unsigned(fileStamp.Day), unsigned(fileStamp.Hours), unsigned(fileStamp.Minutes), unsigned(fileStamp.Seconds), aLongSize) ; retCode = rtl::OUString::createFromAscii(asciiStamp) ; } return retCode ; } //------------------------------------------------------------------------------ rtl::OUString SimpleLocalFileLayer::getTimestamp() throw (uno::RuntimeException) { rtl::OUString sStamp = BasicLocalFileLayer::getTimestamp(getFileUrl()); return sStamp; } //------------------------------------------------------------------------------ rtl::OUString FlatLocalFileLayer::getTimestamp() throw (uno::RuntimeException) { rtl::OUString sStamp = BasicLocalFileLayer::getTimestamp(getFileUrl()); return sStamp; } //------------------------------------------------------------------------------ rtl::OUString FullCompositeLocalFileLayer::getTimestamp() throw (uno::RuntimeException) { rtl::OUString sStamp = BasicLocalFileLayer::getTimestamp(getFileUrl()); #if 0 // thus far composite layers are only manipulated via the main layer for (SubLayerFiles::const_iterator it = mSubLayerFiles.begin(); it != mSubLayerFiles.end(); ++it) { rtl::OUString sSublayerTime = BasicLocalFileLayer::getTimestamp(*it); if (sStamp < sSublayerTime) sStamp = sSublayerTime; } #endif return sStamp; } //------------------------------------------------------------------------------ void BasicCompositeLocalFileLayer::fillSubLayerLists( const SubLayerFiles& aSublayerDirectories, const rtl::OUString& aComponent) { SubLayerFiles::size_type const nSublayerCount = aSublayerDirectories.size(); mSubLayers.realloc(nSublayerCount); mSubLayerFiles.resize(nSublayerCount); for (SubLayerFiles::size_type i = 0; i < nSublayerCount; ++i) { mSubLayers[i] = FileHelper::getFileName(aSublayerDirectories[i]); // Let's check whether the sublayer exists for the // particular component. rtl::OUString subLayerFile(aSublayerDirectories[i] + aComponent) ; if (FileHelper::fileExists(subLayerFile)) { mSubLayerFiles[i] = subLayerFile; } else OSL_ASSERT(mSubLayerFiles[i].getLength() == 0); } } //------------------------------------------------------------------------------ static bool findSubLayers(const rtl::OUString& aResDir, CompositeLocalFileLayer::SubLayerFiles& aSublayerDirectories) { if (aResDir.getLength() == 0) return false; // Extract the directory where the file is located osl::Directory directory(aResDir) ; if (directory.open() != osl::Directory::E_None) return false; osl::DirectoryItem item ; osl::FileStatus status(osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileURL) ; while (directory.getNextItem(item) == osl::Directory::E_None) { if (item.getFileStatus(status) == osl::Directory::E_None) { if (status.getFileType() == osl::FileStatus::Directory) { aSublayerDirectories.push_back(status.getFileURL()) ; } } } return !aSublayerDirectories.empty(); } //------------------------------------------------------------------------------ uno::Reference createReadonlyLocalFileLayer( const uno::Reference& xFactory, const rtl::OUString& aBaseDir, const rtl::OUString& aComponent, const rtl::OUString& aResDir) { uno::Reference xResult; CompositeLocalFileLayer::SubLayerFiles aSublayers; if (aBaseDir.getLength() == 0) { findSubLayers(aResDir,aSublayers); xResult.set( new CompositeLocalFileLayer(xFactory,aComponent,aSublayers) ); } else if (findSubLayers(aResDir,aSublayers)) { // there is no readonly full composite layer - take the updatable one backend::XCompositeLayer * pNewLayer = new FullCompositeLocalFileLayer(xFactory,aBaseDir,aComponent,aSublayers); xResult.set( pNewLayer ); } else { xResult.set( new SimpleLocalFileLayer(xFactory,aBaseDir,aComponent) ); } return xResult; } //------------------------------------------------------------------------------ uno::Reference createUpdatableLocalFileLayer( const uno::Reference& xFactory, const rtl::OUString& aBaseDir, const rtl::OUString& aComponent, const rtl::OUString& aResDir) { uno::Reference xResult; CompositeLocalFileLayer::SubLayerFiles aSublayers; if (findSubLayers(aResDir,aSublayers)) { xResult.set( new FullCompositeLocalFileLayer(xFactory,aBaseDir,aComponent,aSublayers) ); } else if (aBaseDir.getLength() != 0) { xResult.set( new FlatLocalFileLayer(xFactory,aBaseDir,aComponent) ); } else OSL_ENSURE(false,"WARNING: Trying to create an updatable ressource-only layer"); return xResult; } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ enum { LAYER_PROPERTY_URL = 1 }; #define PROPNAME( name ) rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( name ) ) #define PROPTYPE( type ) getCppuType( static_cast< type const *>( 0 ) ) // cppu::OPropertySetHelper cppu::IPropertyArrayHelper * SAL_CALL LayerPropertyHelper::newInfoHelper() { using com::sun::star::beans::Property; using namespace com::sun::star::beans::PropertyAttribute; Property properties[] = { Property(PROPNAME("URL"), LAYER_PROPERTY_URL, PROPTYPE(rtl::OUString), READONLY) }; return new cppu::OPropertyArrayHelper(properties, sizeof(properties)/sizeof(properties[0])); } #define MESSAGE( text ) rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ERROR: Layer Properties: " text ) ) void SAL_CALL LayerPropertyHelper::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const uno::Any& /*rValue*/ ) throw (uno::Exception) { namespace beans = com::sun::star::beans; switch (nHandle) { case LAYER_PROPERTY_URL: OSL_ENSURE(false, "Error: trying to set a READONLY property"); throw beans::PropertyVetoException(MESSAGE("Property 'URL' is read-only"),*this); default: OSL_ENSURE(false, "Error: trying to set an UNKNOWN property"); throw beans::UnknownPropertyException(MESSAGE("Trying to set an unknown property"),*this); } } void SAL_CALL LayerPropertyHelper::getFastPropertyValue( uno::Any& rValue, sal_Int32 nHandle ) const { switch (nHandle) { case LAYER_PROPERTY_URL: rValue = uno::makeAny( this->getLayerUrl() ); break; default: OSL_ENSURE(false, "Error: trying to get an UNKNOWN property"); break; } } //------------------------------------------------------------------------------ } } // configmgr.localbe