1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_unotools.hxx"
30 
31 #include <unotools/ucblockbytes.hxx>
32 #include <unotools/ucbstreamhelper.hxx>
33 #include <comphelper/processfactory.hxx>
34 #include <com/sun/star/ucb/CommandAbortedException.hpp>
35 
36 #ifndef _COM_SUN_STAR_UCB_XCOMMANDENVIRONMENT_HDL_
37 #include <com/sun/star/ucb/XCommandEnvironment.hdl>
38 #endif
39 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
40 #include <com/sun/star/io/XActiveDataStreamer.hpp>
41 
42 #include <ucbhelper/contentbroker.hxx>
43 #include <ucbhelper/content.hxx>
44 #include <tools/debug.hxx>
45 #include <unotools/streamwrap.hxx>
46 
47 using namespace ::com::sun::star::uno;
48 using namespace ::com::sun::star::io;
49 using namespace ::com::sun::star::uno;
50 using namespace ::com::sun::star::ucb;
51 using namespace ::com::sun::star::task;
52 using namespace ::com::sun::star::lang;
53 using namespace ::com::sun::star::beans;
54 
55 namespace utl
56 {
57 
58 static SvStream* lcl_CreateStream( const String& rFileName, StreamMode eOpenMode,
59 		Reference < XInteractionHandler > xInteractionHandler,
60         UcbLockBytesHandler* pHandler, sal_Bool /*bForceSynchron*/, sal_Bool bEnsureFileExists )
61 {
62     SvStream* pStream = NULL;
63     ::ucbhelper::ContentBroker* pBroker = ::ucbhelper::ContentBroker::get();
64     if ( pBroker )
65     {
66         UcbLockBytesRef xLockBytes;
67         if ( eOpenMode & STREAM_WRITE )
68         {
69             sal_Bool bTruncate = ( eOpenMode & STREAM_TRUNC ) != 0;
70             if ( bTruncate )
71             {
72                 try
73                 {
74                     // truncate is implemented with deleting the original file
75                     ::ucbhelper::Content aCnt( rFileName, Reference < XCommandEnvironment >() );
76                     aCnt.executeCommand( ::rtl::OUString::createFromAscii( "delete" ), makeAny( sal_Bool( sal_True ) ) );
77                 }
78 
79                 catch ( CommandAbortedException& )
80                 {
81                     // couldn't truncate/delete
82                 }
83                 catch ( ContentCreationException& )
84                 {
85                 }
86                 catch ( Exception& )
87                 {
88                 }
89             }
90 
91             if ( bEnsureFileExists || bTruncate )
92             {
93                 try
94                 {
95                     // make sure that the desired file exists before trying to open
96                     SvMemoryStream aStream(0,0);
97                     ::utl::OInputStreamWrapper* pInput = new ::utl::OInputStreamWrapper( aStream );
98                     Reference< XInputStream > xInput( pInput );
99 
100                     ::ucbhelper::Content aContent( rFileName, Reference < XCommandEnvironment >() );
101                     InsertCommandArgument aInsertArg;
102                     aInsertArg.Data = xInput;
103 
104                     aInsertArg.ReplaceExisting = sal_False;
105                     Any aCmdArg;
106                     aCmdArg <<= aInsertArg;
107                     aContent.executeCommand( ::rtl::OUString::createFromAscii( "insert" ), aCmdArg );
108                 }
109 
110                 // it is NOT an error when the stream already exists and no truncation was desired
111                 catch ( CommandAbortedException& )
112                 {
113                     // currently never an error is detected !
114                 }
115                 catch ( ContentCreationException& )
116                 {
117                 }
118                 catch ( Exception& )
119                 {
120                 }
121             }
122         }
123 
124         try
125         {
126             // create LockBytes using UCB
127             ::ucbhelper::Content aContent( rFileName, Reference < XCommandEnvironment >() );
128             xLockBytes = UcbLockBytes::CreateLockBytes( aContent.get(), Sequence < PropertyValue >(),
129 												eOpenMode, xInteractionHandler, pHandler );
130             if ( xLockBytes.Is() )
131             {
132                 pStream = new SvStream( xLockBytes );
133                 pStream->SetBufferSize( 4096 );
134                 pStream->SetError( xLockBytes->GetError() );
135             }
136         }
137         catch ( CommandAbortedException& )
138         {
139         }
140         catch ( ContentCreationException& )
141         {
142         }
143         catch ( Exception& )
144         {
145         }
146     }
147     else
148         // if no UCB is present at least conventional file io is supported
149         pStream = new SvFileStream( rFileName, eOpenMode );
150 
151     return pStream;
152 }
153 
154 //============================================================================
155 
156 SvStream* UcbStreamHelper::CreateStream( const String& rFileName, StreamMode eOpenMode,
157         UcbLockBytesHandler* pHandler, sal_Bool bForceSynchron )
158 {
159     return lcl_CreateStream( rFileName, eOpenMode, Reference < XInteractionHandler >(), pHandler, bForceSynchron, sal_True /* bEnsureFileExists */ );
160 }
161 
162 SvStream* UcbStreamHelper::CreateStream( const String& rFileName, StreamMode eOpenMode,
163         Reference < XInteractionHandler > xInteractionHandler,
164         UcbLockBytesHandler* pHandler, sal_Bool bForceSynchron )
165 {
166     return lcl_CreateStream( rFileName, eOpenMode, xInteractionHandler, pHandler, bForceSynchron, sal_True /* bEnsureFileExists */ );
167 }
168 
169 SvStream* UcbStreamHelper::CreateStream( const String& rFileName, StreamMode eOpenMode,
170         sal_Bool bFileExists,
171         UcbLockBytesHandler* pHandler, sal_Bool bForceSynchron )
172 {
173     return lcl_CreateStream( rFileName, eOpenMode, Reference < XInteractionHandler >(), pHandler, bForceSynchron, !bFileExists );
174 }
175 
176 SvStream* UcbStreamHelper::CreateStream( Reference < XInputStream > xStream )
177 {
178     SvStream* pStream = NULL;
179     UcbLockBytesRef xLockBytes = UcbLockBytes::CreateInputLockBytes( xStream );
180     if ( xLockBytes.Is() )
181     {
182         pStream = new SvStream( xLockBytes );
183         pStream->SetBufferSize( 4096 );
184         pStream->SetError( xLockBytes->GetError() );
185     }
186 
187     return pStream;
188 }
189 
190 SvStream* UcbStreamHelper::CreateStream( Reference < XStream > xStream )
191 {
192     SvStream* pStream = NULL;
193 	if ( xStream->getOutputStream().is() )
194 	{
195     	UcbLockBytesRef xLockBytes = UcbLockBytes::CreateLockBytes( xStream );
196     	if ( xLockBytes.Is() )
197     	{
198         	pStream = new SvStream( xLockBytes );
199         	pStream->SetBufferSize( 4096 );
200         	pStream->SetError( xLockBytes->GetError() );
201     	}
202 	}
203 	else
204 		return CreateStream( xStream->getInputStream() );
205 
206     return pStream;
207 }
208 
209 SvStream* UcbStreamHelper::CreateStream( Reference < XInputStream > xStream, sal_Bool bCloseStream )
210 {
211     SvStream* pStream = NULL;
212     UcbLockBytesRef xLockBytes = UcbLockBytes::CreateInputLockBytes( xStream );
213     if ( xLockBytes.Is() )
214     {
215 		if ( !bCloseStream )
216 			xLockBytes->setDontClose_Impl();
217 
218         pStream = new SvStream( xLockBytes );
219         pStream->SetBufferSize( 4096 );
220         pStream->SetError( xLockBytes->GetError() );
221     }
222 
223     return pStream;
224 };
225 
226 SvStream* UcbStreamHelper::CreateStream( Reference < XStream > xStream, sal_Bool bCloseStream )
227 {
228     SvStream* pStream = NULL;
229 	if ( xStream->getOutputStream().is() )
230 	{
231     	UcbLockBytesRef xLockBytes = UcbLockBytes::CreateLockBytes( xStream );
232     	if ( xLockBytes.Is() )
233     	{
234 			if ( !bCloseStream )
235 				xLockBytes->setDontClose_Impl();
236 
237         	pStream = new SvStream( xLockBytes );
238         	pStream->SetBufferSize( 4096 );
239         	pStream->SetError( xLockBytes->GetError() );
240     	}
241 	}
242 	else
243 		return CreateStream( xStream->getInputStream(), bCloseStream );
244 
245     return pStream;
246 };
247 
248 }
249