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