Update git submodules
[LibreOffice.git] / svl / source / misc / documentlockfile.cxx
blob5ee13a68bbf05aa1c5b7e6eef0618489f4a18ec2
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(std::unique_lock<std::mutex>& /*rGuard*/)
60 uno::Reference < css::ucb::XCommandEnvironment > xEnv;
61 ::ucbhelper::Content aSourceContent( GetURL(), xEnv, comphelper::getProcessComponentContext() );
63 // the file can be opened readonly, no locking will be done
64 return aSourceContent.openStream();
67 bool GenDocumentLockFile::CreateOwnLockFile()
69 std::unique_lock aGuard( m_aMutex );
71 try
73 uno::Reference< io::XStream > xTempFile(
74 io::TempFile::create( comphelper::getProcessComponentContext() ),
75 uno::UNO_QUERY_THROW );
76 uno::Reference< io::XSeekable > xSeekable( xTempFile, uno::UNO_QUERY_THROW );
78 uno::Reference< io::XInputStream > xInput = xTempFile->getInputStream();
79 uno::Reference< io::XOutputStream > xOutput = xTempFile->getOutputStream();
81 if ( !xInput.is() || !xOutput.is() )
82 throw uno::RuntimeException();
84 LockFileEntry aNewEntry = GenerateOwnEntry();
85 WriteEntryToStream( aGuard, aNewEntry, xOutput );
86 xOutput->closeOutput();
88 xSeekable->seek( 0 );
90 uno::Reference < css::ucb::XCommandEnvironment > xEnv;
91 ::ucbhelper::Content aTargetContent( GetURL(), xEnv, comphelper::getProcessComponentContext() );
93 ucb::InsertCommandArgument aInsertArg;
94 aInsertArg.Data = std::move(xInput);
95 aInsertArg.ReplaceExisting = false;
96 uno::Any aCmdArg;
97 aCmdArg <<= aInsertArg;
98 aTargetContent.executeCommand( u"insert"_ustr, aCmdArg );
100 // try to let the file be hidden if possible
101 try {
102 aTargetContent.setPropertyValue(u"IsHidden"_ustr, uno::Any( true ) );
103 } catch( uno::Exception& ) {}
105 catch( ucb::NameClashException& )
107 return false;
110 return true;
113 bool GenDocumentLockFile::OverwriteOwnLockFile()
115 std::unique_lock aGuard(m_aMutex);
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( aGuard, aNewEntry, xOutput );
131 xOutput->closeOutput();
133 catch( uno::Exception& )
135 return false;
138 return true;
141 void GenDocumentLockFile::RemoveFile()
143 std::unique_lock 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 = GetLockDataImpl(aGuard);
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(u"delete"_ustr,
162 uno::Any(true));
165 LockFileEntry GenDocumentLockFile::GetLockData()
167 std::unique_lock aGuard(m_aMutex);
168 return GetLockDataImpl(aGuard);
171 DocumentLockFile::DocumentLockFile( std::u16string_view aOrigURL )
172 : GenDocumentLockFile(GenerateOwnLockFileURL(aOrigURL, u".~lock."))
177 DocumentLockFile::~DocumentLockFile()
182 void DocumentLockFile::WriteEntryToStream(
183 std::unique_lock<std::mutex>& /*rGuard*/,
184 const LockFileEntry& aEntry, const uno::Reference< io::XOutputStream >& xOutput )
186 OUStringBuffer aBuffer(256);
188 for ( LockFileComponent lft : o3tl::enumrange<LockFileComponent>() )
190 aBuffer.append( EscapeCharacters( aEntry[lft] ) );
191 if ( lft < LockFileComponent::LAST )
192 aBuffer.append( ',' );
193 else
194 aBuffer.append( ';' );
197 OString aStringData( OUStringToOString( aBuffer, RTL_TEXTENCODING_UTF8 ) );
198 uno::Sequence< sal_Int8 > aData( reinterpret_cast<sal_Int8 const *>(aStringData.getStr()), aStringData.getLength() );
199 xOutput->writeBytes( aData );
202 LockFileEntry DocumentLockFile::GetLockDataImpl(std::unique_lock<std::mutex>& rGuard)
204 uno::Reference< io::XInputStream > xInput = OpenStream(rGuard);
205 if ( !xInput.is() )
206 throw uno::RuntimeException();
208 const sal_Int32 nBufLen = 32000;
209 uno::Sequence< sal_Int8 > aBuffer( nBufLen );
211 sal_Int32 nRead = xInput->readBytes( aBuffer, nBufLen );
212 xInput->closeInput();
214 if ( nRead == nBufLen )
215 throw io::WrongFormatException();
217 sal_Int32 nCurPos = 0;
218 return ParseEntry( aBuffer, nCurPos );
224 } // namespace svt
226 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */