LibreOffice Module svl (master) 1
documentlockfile.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20
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>
31
32#include <o3tl/enumrange.hxx>
33
34#include <rtl/string.hxx>
35#include <rtl/ustring.hxx>
36#include <rtl/ustrbuf.hxx>
37
39
40#include <ucbhelper/content.hxx>
41
43
44using namespace ::com::sun::star;
45
46namespace svt {
47
48GenDocumentLockFile::GenDocumentLockFile(const OUString& aLockFileURL)
49 : LockFileCommon(aLockFileURL)
50{
51}
52
53
55{
56}
57
58uno::Reference< io::XInputStream > GenDocumentLockFile::OpenStream(std::unique_lock<std::mutex>& /*rGuard*/)
59{
60 uno::Reference < css::ucb::XCommandEnvironment > xEnv;
62
63 // the file can be opened readonly, no locking will be done
64 return aSourceContent.openStream();
65}
66
68{
69 std::unique_lock aGuard( m_aMutex );
70
71 try
72 {
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 );
77
78 uno::Reference< io::XInputStream > xInput = xTempFile->getInputStream();
79 uno::Reference< io::XOutputStream > xOutput = xTempFile->getOutputStream();
80
81 if ( !xInput.is() || !xOutput.is() )
82 throw uno::RuntimeException();
83
84 LockFileEntry aNewEntry = GenerateOwnEntry();
85 WriteEntryToStream( aGuard, aNewEntry, xOutput );
86 xOutput->closeOutput();
87
88 xSeekable->seek( 0 );
89
90 uno::Reference < css::ucb::XCommandEnvironment > xEnv;
92
93 ucb::InsertCommandArgument aInsertArg;
94 aInsertArg.Data = xInput;
95 aInsertArg.ReplaceExisting = false;
96 uno::Any aCmdArg;
97 aCmdArg <<= aInsertArg;
98 aTargetContent.executeCommand( "insert", aCmdArg );
99
100 // try to let the file be hidden if possible
101 try {
102 aTargetContent.setPropertyValue("IsHidden", uno::Any( true ) );
103 } catch( uno::Exception& ) {}
104 }
105 catch( ucb::NameClashException& )
106 {
107 return false;
108 }
109
110 return true;
111}
112
114{
115 std::unique_lock aGuard(m_aMutex);
116
117 // allows to overwrite the lock file with the current data
118 try
119 {
120 uno::Reference < css::ucb::XCommandEnvironment > xEnv;
122
123 LockFileEntry aNewEntry = GenerateOwnEntry();
124
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 );
128
129 xTruncate->truncate();
130 WriteEntryToStream( aGuard, aNewEntry, xOutput );
131 xOutput->closeOutput();
132 }
133 catch( uno::Exception& )
134 {
135 return false;
136 }
137
138 return true;
139}
140
142{
143 std::unique_lock aGuard( m_aMutex );
144
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);
148
151 || aFileData[LockFileComponent::USERURL] != aNewEntry[LockFileComponent::USERURL] )
152 throw io::IOException(); // not the owner, access denied
153
155}
156
158{
159 uno::Reference < css::ucb::XCommandEnvironment > xEnv;
161 aCnt.executeCommand("delete",
162 uno::Any(true));
163}
164
166{
167 std::unique_lock aGuard(m_aMutex);
168 return GetLockDataImpl(aGuard);
169}
170
171DocumentLockFile::DocumentLockFile( std::u16string_view aOrigURL )
172 : GenDocumentLockFile(GenerateOwnLockFileURL(aOrigURL, u".~lock."))
173{
174}
175
176
178{
179}
180
181
183 std::unique_lock<std::mutex>& /*rGuard*/,
184 const LockFileEntry& aEntry, const uno::Reference< io::XOutputStream >& xOutput )
185{
186 OUStringBuffer aBuffer(256);
187
189 {
190 aBuffer.append( EscapeCharacters( aEntry[lft] ) );
191 if ( lft < LockFileComponent::LAST )
192 aBuffer.append( ',' );
193 else
194 aBuffer.append( ';' );
195 }
196
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 );
200}
201
202LockFileEntry DocumentLockFile::GetLockDataImpl(std::unique_lock<std::mutex>& rGuard)
203{
204 uno::Reference< io::XInputStream > xInput = OpenStream(rGuard);
205 if ( !xInput.is() )
206 throw uno::RuntimeException();
207
208 const sal_Int32 nBufLen = 32000;
209 uno::Sequence< sal_Int8 > aBuffer( nBufLen );
210
211 sal_Int32 nRead = xInput->readBytes( aBuffer, nBufLen );
212 xInput->closeInput();
213
214 if ( nRead == nBufLen )
215 throw io::WrongFormatException();
216
217 sal_Int32 nCurPos = 0;
218 return ParseEntry( aBuffer, nCurPos );
219}
220
221
222
223
224} // namespace svt
225
226/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Reference< XInputStream > xStream
virtual void WriteEntryToStream(std::unique_lock< std::mutex > &rGuard, const LockFileEntry &aEntry, const css::uno::Reference< css::io::XOutputStream > &xStream) override
virtual LockFileEntry GetLockDataImpl(std::unique_lock< std::mutex > &rGuard) override
DocumentLockFile(std::u16string_view aOrigURL)
virtual ~DocumentLockFile() override
Generalized class for LO and MSO lockfile handling.
virtual css::uno::Reference< css::io::XInputStream > OpenStream(std::unique_lock< std::mutex > &rGuard)
virtual ~GenDocumentLockFile() override
virtual LockFileEntry GetLockDataImpl(std::unique_lock< std::mutex > &rGuard)=0
void RemoveFileDirectly()
Only delete lockfile, disregarding ownership.
GenDocumentLockFile(const OUString &aLockFileURL)
virtual void RemoveFile()
Delete the Lockfile, if current user is the owner.
virtual void WriteEntryToStream(std::unique_lock< std::mutex > &rGuard, const LockFileEntry &aEntry, const css::uno::Reference< css::io::XOutputStream > &xStream)=0
This is a general implementation that is used in document lock file implementation and in sharing con...
static LockFileEntry GenerateOwnEntry()
static OUString EscapeCharacters(const OUString &aSource)
const OUString & GetURL() const
static LockFileEntry ParseEntry(const css::uno::Sequence< sal_Int8 > &aBuffer, sal_Int32 &o_nCurPos)
css::uno::Any setPropertyValue(const OUString &rPropertyName, const css::uno::Any &rValue)
css::uno::Any executeCommand(const OUString &rCommandName, const css::uno::Any &rCommandArgument)
css::uno::Reference< css::io::XStream > openWriteableStreamNoLock()
css::uno::Reference< css::io::XInputStream > openStream()
float u
LockFileComponent
constexpr OUStringLiteral aData
Reference< XComponentContext > getProcessComponentContext()
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
signed char sal_Int8
std::unique_ptr< char[]> aBuffer