lok: vcl: fix multiple floatwin removal case more robustly.
[LibreOffice.git] / svl / source / misc / documentlockfile.cxx
blob1bdf7ce5f3867b7f7170dfc178c2bfb4ad2d2a64
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/XSimpleFileAccess.hpp>
22 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
23 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
24 #include <com/sun/star/ucb/NameClashException.hpp>
25 #include <com/sun/star/io/WrongFormatException.hpp>
26 #include <com/sun/star/io/TempFile.hpp>
27 #include <com/sun/star/io/XStream.hpp>
28 #include <com/sun/star/io/XInputStream.hpp>
29 #include <com/sun/star/io/XOutputStream.hpp>
30 #include <com/sun/star/io/XSeekable.hpp>
31 #include <com/sun/star/io/XTruncate.hpp>
33 #include <osl/time.h>
34 #include <osl/security.hxx>
35 #include <osl/socket.hxx>
36 #include <o3tl/enumrange.hxx>
38 #include <rtl/string.hxx>
39 #include <rtl/ustring.hxx>
40 #include <rtl/strbuf.hxx>
41 #include <rtl/ustrbuf.hxx>
43 #include <comphelper/processfactory.hxx>
45 #include <unotools/bootstrap.hxx>
47 #include <ucbhelper/content.hxx>
49 #include <unotools/useroptions.hxx>
51 #include <svl/documentlockfile.hxx>
53 using namespace ::com::sun::star;
55 namespace svt {
57 GenDocumentLockFile::GenDocumentLockFile( const OUString& aURL )
58 : LockFileCommon( aURL )
63 GenDocumentLockFile::GenDocumentLockFile( const OUString& aOrigURL, const OUString& aPrefix )
64 : LockFileCommon( aOrigURL, aPrefix )
69 GenDocumentLockFile::~GenDocumentLockFile()
73 uno::Reference< io::XInputStream > GenDocumentLockFile::OpenStream()
75 ::osl::MutexGuard aGuard( m_aMutex );
77 uno::Reference < css::ucb::XCommandEnvironment > xEnv;
78 ::ucbhelper::Content aSourceContent( GetURL(), xEnv, comphelper::getProcessComponentContext() );
80 // the file can be opened readonly, no locking will be done
81 return aSourceContent.openStream();
84 bool GenDocumentLockFile::CreateOwnLockFile()
86 ::osl::MutexGuard aGuard( m_aMutex );
88 try
90 uno::Reference< io::XStream > xTempFile(
91 io::TempFile::create( comphelper::getProcessComponentContext() ),
92 uno::UNO_QUERY_THROW );
93 uno::Reference< io::XSeekable > xSeekable( xTempFile, uno::UNO_QUERY_THROW );
95 uno::Reference< io::XInputStream > xInput = xTempFile->getInputStream();
96 uno::Reference< io::XOutputStream > xOutput = xTempFile->getOutputStream();
98 if ( !xInput.is() || !xOutput.is() )
99 throw uno::RuntimeException();
101 LockFileEntry aNewEntry = GenerateOwnEntry();
102 WriteEntryToStream( aNewEntry, xOutput );
103 xOutput->closeOutput();
105 xSeekable->seek( 0 );
107 uno::Reference < css::ucb::XCommandEnvironment > xEnv;
108 ::ucbhelper::Content aTargetContent( GetURL(), xEnv, comphelper::getProcessComponentContext() );
110 ucb::InsertCommandArgument aInsertArg;
111 aInsertArg.Data = xInput;
112 aInsertArg.ReplaceExisting = false;
113 uno::Any aCmdArg;
114 aCmdArg <<= aInsertArg;
115 aTargetContent.executeCommand( "insert", aCmdArg );
117 // try to let the file be hidden if possible
118 try {
119 aTargetContent.setPropertyValue("IsHidden", uno::makeAny( true ) );
120 } catch( uno::Exception& ) {}
122 catch( ucb::NameClashException& )
124 return false;
127 return true;
130 bool GenDocumentLockFile::OverwriteOwnLockFile()
132 // allows to overwrite the lock file with the current data
135 uno::Reference < css::ucb::XCommandEnvironment > xEnv;
136 ::ucbhelper::Content aTargetContent( GetURL(), xEnv, comphelper::getProcessComponentContext() );
138 LockFileEntry aNewEntry = GenerateOwnEntry();
140 uno::Reference< io::XStream > xStream = aTargetContent.openWriteableStreamNoLock();
141 uno::Reference< io::XOutputStream > xOutput = xStream->getOutputStream();
142 uno::Reference< io::XTruncate > xTruncate( xOutput, uno::UNO_QUERY_THROW );
144 xTruncate->truncate();
145 WriteEntryToStream( aNewEntry, xOutput );
146 xOutput->closeOutput();
148 catch( uno::Exception& )
150 return false;
153 return true;
156 void GenDocumentLockFile::RemoveFile()
158 ::osl::MutexGuard aGuard( m_aMutex );
160 // TODO/LATER: the removing is not atomic, is it possible in general to make it atomic?
161 LockFileEntry aNewEntry = GenerateOwnEntry();
162 LockFileEntry aFileData = GetLockData();
164 if ( aFileData[LockFileComponent::SYSUSERNAME] != aNewEntry[LockFileComponent::SYSUSERNAME]
165 || aFileData[LockFileComponent::LOCALHOST] != aNewEntry[LockFileComponent::LOCALHOST]
166 || aFileData[LockFileComponent::USERURL] != aNewEntry[LockFileComponent::USERURL] )
167 throw io::IOException(); // not the owner, access denied
169 RemoveFileDirectly();
172 void GenDocumentLockFile::RemoveFileDirectly()
174 uno::Reference < css::ucb::XCommandEnvironment > xEnv;
175 ::ucbhelper::Content aCnt(GetURL(), xEnv, comphelper::getProcessComponentContext());
176 aCnt.executeCommand("delete",
177 uno::makeAny(true));
181 DocumentLockFile::DocumentLockFile( const OUString& aOrigURL )
182 : GenDocumentLockFile( aOrigURL, ".~lock." )
187 DocumentLockFile::~DocumentLockFile()
192 void DocumentLockFile::WriteEntryToStream( const LockFileEntry& aEntry, const uno::Reference< io::XOutputStream >& xOutput )
194 ::osl::MutexGuard aGuard( m_aMutex );
196 OUStringBuffer aBuffer;
198 for ( LockFileComponent lft : o3tl::enumrange<LockFileComponent>() )
200 aBuffer.append( EscapeCharacters( aEntry[lft] ) );
201 if ( lft < LockFileComponent::LAST )
202 aBuffer.append( ',' );
203 else
204 aBuffer.append( ';' );
207 OString aStringData( OUStringToOString( aBuffer.makeStringAndClear(), RTL_TEXTENCODING_UTF8 ) );
208 uno::Sequence< sal_Int8 > aData( reinterpret_cast<sal_Int8 const *>(aStringData.getStr()), aStringData.getLength() );
209 xOutput->writeBytes( aData );
212 LockFileEntry DocumentLockFile::GetLockData()
214 ::osl::MutexGuard aGuard( m_aMutex );
216 uno::Reference< io::XInputStream > xInput = OpenStream();
217 if ( !xInput.is() )
218 throw uno::RuntimeException();
220 const sal_Int32 nBufLen = 32000;
221 uno::Sequence< sal_Int8 > aBuffer( nBufLen );
223 sal_Int32 nRead = 0;
225 nRead = xInput->readBytes( aBuffer, nBufLen );
226 xInput->closeInput();
228 if ( nRead == nBufLen )
229 throw io::WrongFormatException();
231 sal_Int32 nCurPos = 0;
232 return ParseEntry( aBuffer, nCurPos );
238 } // namespace svt
240 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */