OInterfaceContainerHelper3 needs to be thread-safe
[LibreOffice.git] / svl / source / misc / documentlockfile.cxx
blob935a568310fc2a75496bbded283143451c57f6ba
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
22 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
23 #include <com/sun/star/ucb/NameClashException.hpp>
24 #include <com/sun/star/io/WrongFormatException.hpp>
25 #include <com/sun/star/io/TempFile.hpp>
26 #include <com/sun/star/io/XStream.hpp>
27 #include <com/sun/star/io/XInputStream.hpp>
28 #include <com/sun/star/io/XOutputStream.hpp>
29 #include <com/sun/star/io/XSeekable.hpp>
30 #include <com/sun/star/io/XTruncate.hpp>
32 #include <o3tl/enumrange.hxx>
34 #include <rtl/string.hxx>
35 #include <rtl/ustring.hxx>
36 #include <rtl/ustrbuf.hxx>
38 #include <comphelper/processfactory.hxx>
40 #include <ucbhelper/content.hxx>
42 #include <svl/documentlockfile.hxx>
44 using namespace ::com::sun::star;
46 namespace svt {
48 GenDocumentLockFile::GenDocumentLockFile(const OUString& aLockFileURL)
49 : LockFileCommon(aLockFileURL)
54 GenDocumentLockFile::~GenDocumentLockFile()
58 uno::Reference< io::XInputStream > GenDocumentLockFile::OpenStream()
60 ::osl::MutexGuard aGuard( m_aMutex );
62 uno::Reference < css::ucb::XCommandEnvironment > xEnv;
63 ::ucbhelper::Content aSourceContent( GetURL(), xEnv, comphelper::getProcessComponentContext() );
65 // the file can be opened readonly, no locking will be done
66 return aSourceContent.openStream();
69 bool GenDocumentLockFile::CreateOwnLockFile()
71 ::osl::MutexGuard aGuard( m_aMutex );
73 try
75 uno::Reference< io::XStream > xTempFile(
76 io::TempFile::create( comphelper::getProcessComponentContext() ),
77 uno::UNO_QUERY_THROW );
78 uno::Reference< io::XSeekable > xSeekable( xTempFile, uno::UNO_QUERY_THROW );
80 uno::Reference< io::XInputStream > xInput = xTempFile->getInputStream();
81 uno::Reference< io::XOutputStream > xOutput = xTempFile->getOutputStream();
83 if ( !xInput.is() || !xOutput.is() )
84 throw uno::RuntimeException();
86 LockFileEntry aNewEntry = GenerateOwnEntry();
87 WriteEntryToStream( aNewEntry, xOutput );
88 xOutput->closeOutput();
90 xSeekable->seek( 0 );
92 uno::Reference < css::ucb::XCommandEnvironment > xEnv;
93 ::ucbhelper::Content aTargetContent( GetURL(), xEnv, comphelper::getProcessComponentContext() );
95 ucb::InsertCommandArgument aInsertArg;
96 aInsertArg.Data = xInput;
97 aInsertArg.ReplaceExisting = false;
98 uno::Any aCmdArg;
99 aCmdArg <<= aInsertArg;
100 aTargetContent.executeCommand( "insert", aCmdArg );
102 // try to let the file be hidden if possible
103 try {
104 aTargetContent.setPropertyValue("IsHidden", uno::makeAny( true ) );
105 } catch( uno::Exception& ) {}
107 catch( ucb::NameClashException& )
109 return false;
112 return true;
115 bool GenDocumentLockFile::OverwriteOwnLockFile()
117 // allows to overwrite the lock file with the current data
120 uno::Reference < css::ucb::XCommandEnvironment > xEnv;
121 ::ucbhelper::Content aTargetContent( GetURL(), xEnv, comphelper::getProcessComponentContext() );
123 LockFileEntry aNewEntry = GenerateOwnEntry();
125 uno::Reference< io::XStream > xStream = aTargetContent.openWriteableStreamNoLock();
126 uno::Reference< io::XOutputStream > xOutput = xStream->getOutputStream();
127 uno::Reference< io::XTruncate > xTruncate( xOutput, uno::UNO_QUERY_THROW );
129 xTruncate->truncate();
130 WriteEntryToStream( aNewEntry, xOutput );
131 xOutput->closeOutput();
133 catch( uno::Exception& )
135 return false;
138 return true;
141 void GenDocumentLockFile::RemoveFile()
143 ::osl::MutexGuard aGuard( m_aMutex );
145 // TODO/LATER: the removing is not atomic, is it possible in general to make it atomic?
146 LockFileEntry aNewEntry = GenerateOwnEntry();
147 LockFileEntry aFileData = GetLockData();
149 if ( aFileData[LockFileComponent::SYSUSERNAME] != aNewEntry[LockFileComponent::SYSUSERNAME]
150 || aFileData[LockFileComponent::LOCALHOST] != aNewEntry[LockFileComponent::LOCALHOST]
151 || aFileData[LockFileComponent::USERURL] != aNewEntry[LockFileComponent::USERURL] )
152 throw io::IOException(); // not the owner, access denied
154 RemoveFileDirectly();
157 void GenDocumentLockFile::RemoveFileDirectly()
159 uno::Reference < css::ucb::XCommandEnvironment > xEnv;
160 ::ucbhelper::Content aCnt(GetURL(), xEnv, comphelper::getProcessComponentContext());
161 aCnt.executeCommand("delete",
162 uno::makeAny(true));
166 DocumentLockFile::DocumentLockFile( const OUString& aOrigURL )
167 : GenDocumentLockFile(GenerateOwnLockFileURL(aOrigURL, ".~lock."))
172 DocumentLockFile::~DocumentLockFile()
177 void DocumentLockFile::WriteEntryToStream( const LockFileEntry& aEntry, const uno::Reference< io::XOutputStream >& xOutput )
179 ::osl::MutexGuard aGuard( m_aMutex );
181 OUStringBuffer aBuffer(256);
183 for ( LockFileComponent lft : o3tl::enumrange<LockFileComponent>() )
185 aBuffer.append( EscapeCharacters( aEntry[lft] ) );
186 if ( lft < LockFileComponent::LAST )
187 aBuffer.append( ',' );
188 else
189 aBuffer.append( ';' );
192 OString aStringData( OUStringToOString( aBuffer.makeStringAndClear(), RTL_TEXTENCODING_UTF8 ) );
193 uno::Sequence< sal_Int8 > aData( reinterpret_cast<sal_Int8 const *>(aStringData.getStr()), aStringData.getLength() );
194 xOutput->writeBytes( aData );
197 LockFileEntry DocumentLockFile::GetLockData()
199 ::osl::MutexGuard aGuard( m_aMutex );
201 uno::Reference< io::XInputStream > xInput = OpenStream();
202 if ( !xInput.is() )
203 throw uno::RuntimeException();
205 const sal_Int32 nBufLen = 32000;
206 uno::Sequence< sal_Int8 > aBuffer( nBufLen );
208 sal_Int32 nRead = xInput->readBytes( aBuffer, nBufLen );
209 xInput->closeInput();
211 if ( nRead == nBufLen )
212 throw io::WrongFormatException();
214 sal_Int32 nCurPos = 0;
215 return ParseEntry( aBuffer, nCurPos );
221 } // namespace svt
223 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */