Update ooo320-m1
[ooovba.git] / svtools / source / misc / sharecontrolfile.cxx
blob5c214b8277b26e2d56c6a6adb21268e4bb682cf8
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: sharecontrolfile.cxx,v $
10 * $Revision: 1.6.82.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svtools.hxx"
34 #include <stdio.h>
36 #include <com/sun/star/ucb/XSimpleFileAccess.hpp>
37 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
38 #include <com/sun/star/ucb/XContent.hpp>
39 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
40 #include <com/sun/star/ucb/InteractiveIOException.hpp>
41 #include <com/sun/star/io/WrongFormatException.hpp>
43 #include <osl/time.h>
44 #include <osl/security.hxx>
45 #include <osl/socket.hxx>
47 #include <rtl/string.hxx>
48 #include <rtl/ustring.hxx>
49 #include <rtl/strbuf.hxx>
50 #include <rtl/ustrbuf.hxx>
52 #include <comphelper/processfactory.hxx>
53 #include <ucbhelper/content.hxx>
55 #include <tools/urlobj.hxx>
56 #include <tools/stream.hxx>
57 #include <unotools/bootstrap.hxx>
58 #include <unotools/streamwrap.hxx>
60 #include <svtools/useroptions.hxx>
62 #include <svtools/sharecontrolfile.hxx>
64 using namespace ::com::sun::star;
66 namespace svt {
68 // ----------------------------------------------------------------------
69 ShareControlFile::ShareControlFile( const ::rtl::OUString& aOrigURL, const uno::Reference< lang::XMultiServiceFactory >& xFactory )
70 : LockFileCommon( aOrigURL, xFactory, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".~sharing." ) ) )
72 OpenStream();
74 if ( !IsValid() )
75 throw io::NotConnectedException();
78 // ----------------------------------------------------------------------
79 ShareControlFile::~ShareControlFile()
81 try
83 Close();
85 catch( uno::Exception& )
89 // ----------------------------------------------------------------------
90 void ShareControlFile::OpenStream()
92 // if it is called outside of constructor the mutex must be locked already
94 if ( !m_xStream.is() && m_aURL.getLength() )
96 uno::Reference< ucb::XCommandEnvironment > xDummyEnv;
97 ::ucbhelper::Content aContent = ::ucbhelper::Content( m_aURL, xDummyEnv );
99 uno::Reference< ucb::XContentIdentifier > xContId( aContent.get().is() ? aContent.get()->getIdentifier() : 0 );
100 if ( !xContId.is() || !xContId->getContentProviderScheme().equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "file" ) ) ) )
101 throw io::IOException(); // the implementation supports only local files for now
103 uno::Reference< io::XStream > xStream;
105 // Currently the locking of the original document is intended to be used.
106 // That means that the shared file should be accessed only when the original document is locked and only by user who has locked the document.
107 // TODO/LATER: should the own file locking be used?
111 xStream = aContent.openWriteableStreamNoLock();
113 catch ( ucb::InteractiveIOException const & e )
115 if ( e.Code == ucb::IOErrorCode_NOT_EXISTING )
117 // Create file...
118 SvMemoryStream aStream(0,0);
119 uno::Reference< io::XInputStream > xInput( new ::utl::OInputStreamWrapper( aStream ) );
120 ucb::InsertCommandArgument aInsertArg;
121 aInsertArg.Data = xInput;
122 aInsertArg.ReplaceExisting = sal_False;
123 aContent.executeCommand( rtl::OUString::createFromAscii( "insert" ), uno::makeAny( aInsertArg ) );
125 // try to let the file be hidden if possible
126 try {
127 aContent.setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsHidden" ) ), uno::makeAny( sal_True ) );
128 } catch( uno::Exception& ) {}
130 // Try to open one more time
131 xStream = aContent.openWriteableStreamNoLock();
133 else
134 throw;
137 m_xSeekable.set( xStream, uno::UNO_QUERY_THROW );
138 m_xInputStream.set( xStream->getInputStream(), uno::UNO_QUERY_THROW );
139 m_xOutputStream.set( xStream->getOutputStream(), uno::UNO_QUERY_THROW );
140 m_xTruncate.set( m_xOutputStream, uno::UNO_QUERY_THROW );
141 m_xStream = xStream;
145 // ----------------------------------------------------------------------
146 void ShareControlFile::Close()
148 // if it is called outside of destructor the mutex must be locked
150 if ( m_xStream.is() )
154 if ( m_xInputStream.is() )
155 m_xInputStream->closeInput();
156 if ( m_xOutputStream.is() )
157 m_xOutputStream->closeOutput();
159 catch( uno::Exception& )
162 m_xStream = uno::Reference< io::XStream >();
163 m_xInputStream = uno::Reference< io::XInputStream >();
164 m_xOutputStream = uno::Reference< io::XOutputStream >();
165 m_xSeekable = uno::Reference< io::XSeekable >();
166 m_xTruncate = uno::Reference< io::XTruncate >();
167 m_aUsersData.realloc( 0 );
171 // ----------------------------------------------------------------------
172 uno::Sequence< uno::Sequence< ::rtl::OUString > > ShareControlFile::GetUsersData()
174 ::osl::MutexGuard aGuard( m_aMutex );
176 if ( !IsValid() )
177 throw io::NotConnectedException();
179 if ( !m_aUsersData.getLength() )
181 sal_Int64 nLength = m_xSeekable->getLength();
182 if ( nLength > SAL_MAX_INT32 )
183 throw uno::RuntimeException();
185 uno::Sequence< sal_Int8 > aBuffer( (sal_Int32)nLength );
186 m_xSeekable->seek( 0 );
188 sal_Int32 nRead = m_xInputStream->readBytes( aBuffer, (sal_Int32)nLength );
189 nLength -= nRead;
190 while ( nLength > 0 )
192 uno::Sequence< sal_Int8 > aTmpBuf( (sal_Int32)nLength );
193 nRead = m_xInputStream->readBytes( aTmpBuf, (sal_Int32)nLength );
194 if ( nRead > nLength )
195 throw uno::RuntimeException();
197 for ( sal_Int32 nInd = 0; nInd < nRead; nInd++ )
198 aBuffer[aBuffer.getLength() - (sal_Int32)nLength + nInd] = aTmpBuf[nInd];
199 nLength -= nRead;
202 m_aUsersData = ParseList( aBuffer );
205 return m_aUsersData;
208 // ----------------------------------------------------------------------
209 void ShareControlFile::SetUsersDataAndStore( const uno::Sequence< uno::Sequence< ::rtl::OUString > >& aUsersData )
211 ::osl::MutexGuard aGuard( m_aMutex );
213 if ( !IsValid() )
214 throw io::NotConnectedException();
216 if ( !m_xTruncate.is() || !m_xOutputStream.is() || !m_xSeekable.is() )
217 throw uno::RuntimeException();
219 m_xTruncate->truncate();
220 m_xSeekable->seek( 0 );
222 ::rtl::OUStringBuffer aBuffer;
223 for ( sal_Int32 nInd = 0; nInd < aUsersData.getLength(); nInd++ )
225 if ( aUsersData[nInd].getLength() != SHARED_ENTRYSIZE )
226 throw lang::IllegalArgumentException();
228 for ( sal_Int32 nEntryInd = 0; nEntryInd < SHARED_ENTRYSIZE; nEntryInd++ )
230 aBuffer.append( EscapeCharacters( aUsersData[nInd][nEntryInd] ) );
231 if ( nEntryInd < SHARED_ENTRYSIZE - 1 )
232 aBuffer.append( (sal_Unicode)',' );
233 else
234 aBuffer.append( (sal_Unicode)';' );
238 ::rtl::OString aStringData( ::rtl::OUStringToOString( aBuffer.makeStringAndClear(), RTL_TEXTENCODING_UTF8 ) );
239 uno::Sequence< sal_Int8 > aData( (sal_Int8*)aStringData.getStr(), aStringData.getLength() );
240 m_xOutputStream->writeBytes( aData );
241 m_aUsersData = aUsersData;
244 // ----------------------------------------------------------------------
245 uno::Sequence< ::rtl::OUString > ShareControlFile::InsertOwnEntry()
247 ::osl::MutexGuard aGuard( m_aMutex );
249 if ( !IsValid() )
250 throw io::NotConnectedException();
252 GetUsersData();
253 uno::Sequence< ::uno::Sequence< ::rtl::OUString > > aNewData( m_aUsersData.getLength() + 1 );
254 uno::Sequence< ::rtl::OUString > aNewEntry = GenerateOwnEntry();
256 sal_Bool bExists = sal_False;
257 sal_Int32 nNewInd = 0;
258 for ( sal_Int32 nInd = 0; nInd < m_aUsersData.getLength(); nInd++ )
260 if ( m_aUsersData[nInd].getLength() == SHARED_ENTRYSIZE )
262 if ( m_aUsersData[nInd][SHARED_LOCALHOST_ID] == aNewEntry[SHARED_LOCALHOST_ID]
263 && m_aUsersData[nInd][SHARED_SYSUSERNAME_ID] == aNewEntry[SHARED_SYSUSERNAME_ID]
264 && m_aUsersData[nInd][SHARED_USERURL_ID] == aNewEntry[SHARED_USERURL_ID] )
266 if ( !bExists )
268 aNewData[nNewInd] = aNewEntry;
269 bExists = sal_True;
272 else
274 aNewData[nNewInd] = m_aUsersData[nInd];
277 nNewInd++;
281 if ( !bExists )
282 aNewData[nNewInd++] = aNewEntry;
284 aNewData.realloc( nNewInd );
285 SetUsersDataAndStore( aNewData );
287 return aNewEntry;
290 // ----------------------------------------------------------------------
291 bool ShareControlFile::HasOwnEntry()
293 ::osl::MutexGuard aGuard( m_aMutex );
295 if ( !IsValid() )
297 throw io::NotConnectedException();
300 GetUsersData();
301 uno::Sequence< ::rtl::OUString > aEntry = GenerateOwnEntry();
303 for ( sal_Int32 nInd = 0; nInd < m_aUsersData.getLength(); ++nInd )
305 if ( m_aUsersData[nInd].getLength() == SHARED_ENTRYSIZE &&
306 m_aUsersData[nInd][SHARED_LOCALHOST_ID] == aEntry[SHARED_LOCALHOST_ID] &&
307 m_aUsersData[nInd][SHARED_SYSUSERNAME_ID] == aEntry[SHARED_SYSUSERNAME_ID] &&
308 m_aUsersData[nInd][SHARED_USERURL_ID] == aEntry[SHARED_USERURL_ID] )
310 return true;
314 return false;
317 // ----------------------------------------------------------------------
318 void ShareControlFile::RemoveEntry( const uno::Sequence< ::rtl::OUString >& aArgEntry )
320 ::osl::MutexGuard aGuard( m_aMutex );
322 if ( !IsValid() )
323 throw io::NotConnectedException();
325 GetUsersData();
327 uno::Sequence< ::rtl::OUString > aEntry = aArgEntry;
328 if ( aEntry.getLength() != SHARED_ENTRYSIZE )
329 aEntry = GenerateOwnEntry();
331 uno::Sequence< ::uno::Sequence< ::rtl::OUString > > aNewData( m_aUsersData.getLength() + 1 );
333 sal_Int32 nNewInd = 0;
334 for ( sal_Int32 nInd = 0; nInd < m_aUsersData.getLength(); nInd++ )
336 if ( m_aUsersData[nInd].getLength() == SHARED_ENTRYSIZE )
338 if ( m_aUsersData[nInd][SHARED_LOCALHOST_ID] != aEntry[SHARED_LOCALHOST_ID]
339 || m_aUsersData[nInd][SHARED_SYSUSERNAME_ID] != aEntry[SHARED_SYSUSERNAME_ID]
340 || m_aUsersData[nInd][SHARED_USERURL_ID] != aEntry[SHARED_USERURL_ID] )
342 aNewData[nNewInd] = m_aUsersData[nInd];
343 nNewInd++;
348 aNewData.realloc( nNewInd );
349 SetUsersDataAndStore( aNewData );
351 if ( !nNewInd )
353 // try to remove the file if it is empty
354 RemoveFile();
358 // ----------------------------------------------------------------------
359 void ShareControlFile::RemoveFile()
361 ::osl::MutexGuard aGuard( m_aMutex );
363 if ( !IsValid() )
364 throw io::NotConnectedException();
366 Close();
368 uno::Reference< lang::XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory();
369 uno::Reference< ::com::sun::star::ucb::XSimpleFileAccess > xSimpleFileAccess(
370 xFactory->createInstance( ::rtl::OUString::createFromAscii("com.sun.star.ucb.SimpleFileAccess") ),
371 uno::UNO_QUERY_THROW );
372 xSimpleFileAccess->kill( m_aURL );
375 } // namespace svt