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_ucb.hxx"
26 #include "odma_inputstream.hxx"
27 #include "com/sun/star/io/IOException.hpp"
28 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
29 #include <com/sun/star/ucb/OpenMode.hpp>
30 #include <ucbhelper/content.hxx>
31 #include <com/sun/star/io/XActiveDataStreamer.hpp>
32 #include <cppuhelper/implbase1.hxx>
33 #include "odma_contentprops.hxx"
34 #include "odma_provider.hxx"
35 
36 using namespace odma;
37 using namespace com::sun::star;
38 
39 class OActiveDataStreamer : public ::cppu::WeakImplHelper1< io::XActiveDataStreamer>
40 {
41 	uno::Reference< io::XStream > m_xStream;
42 public:
OActiveDataStreamer()43 	OActiveDataStreamer(){}
setStream(const uno::Reference<io::XStream> & _rStream)44 	virtual void SAL_CALL setStream( const uno::Reference< io::XStream >& _rStream ) throw (uno::RuntimeException)
45 	{
46 		m_xStream = _rStream;
47 	}
getStream()48     virtual uno::Reference< io::XStream > SAL_CALL getStream(  ) throw (uno::RuntimeException)
49 	{
50 		return m_xStream;
51 	}
52 };
53 // -----------------------------------------------------------------------------
OOdmaStream(::ucbhelper::Content * _pContent,ContentProvider * _pProvider,const::rtl::Reference<ContentProperties> & _rProp)54 OOdmaStream::OOdmaStream(::ucbhelper::Content* _pContent,
55 						 ContentProvider* _pProvider,
56 						 const ::rtl::Reference<ContentProperties>& _rProp)
57  :m_pContent(_pContent)
58  ,m_bInputStreamCalled(sal_False)
59  ,m_bOutputStreamCalled(sal_False)
60  ,m_bModified(sal_False)
61  ,m_pProvider(_pProvider)
62  ,m_aProp(_rProp)
63 {
64 }
65 // -----------------------------------------------------------------------------
~OOdmaStream()66 OOdmaStream::~OOdmaStream()
67 {
68     try
69     {
70         closeStream();
71 		delete m_pContent;
72     }
73     catch (io::IOException const &)
74     {
75         OSL_ENSURE(false, "unexpected situation");
76     }
77     catch (uno::RuntimeException const &)
78     {
79         OSL_ENSURE(false, "unexpected situation");
80     }
81 }
82 // -----------------------------------------------------------------------------
getInputStream()83 uno::Reference< io::XInputStream > SAL_CALL OOdmaStream::getInputStream(  ) throw( uno::RuntimeException)
84 {
85 	{
86 		osl::MutexGuard aGuard( m_aMutex );
87 		m_bInputStreamCalled = sal_True;
88 	}
89 	return uno::Reference< io::XInputStream >( this );
90 }
91 // -----------------------------------------------------------------------------
getOutputStream()92 uno::Reference< io::XOutputStream > SAL_CALL OOdmaStream::getOutputStream(  ) throw( uno::RuntimeException )
93 {
94 	{
95 		osl::MutexGuard aGuard( m_aMutex );
96 		m_bOutputStreamCalled = sal_True;
97 	}
98 	return uno::Reference< io::XOutputStream >( this );
99 }
100 // -----------------------------------------------------------------------------
readBytes(uno::Sequence<sal_Int8> & aData,sal_Int32 nBytesToRead)101 sal_Int32 SAL_CALL OOdmaStream::readBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead )
102 	throw( io::NotConnectedException,
103 		   io::BufferSizeExceededException,
104 		   io::IOException,
105 		   uno::RuntimeException)
106 {
107 	ensureInputStream();
108 
109 	return m_xInput->readBytes(aData,nBytesToRead);
110 }
111 // -----------------------------------------------------------------------------
readSomeBytes(uno::Sequence<sal_Int8> & aData,sal_Int32 nMaxBytesToRead)112 sal_Int32 SAL_CALL OOdmaStream::readSomeBytes( uno::Sequence< sal_Int8 >& aData,sal_Int32 nMaxBytesToRead )
113 	throw( io::NotConnectedException,
114 		   io::BufferSizeExceededException,
115 		   io::IOException,
116 		   uno::RuntimeException)
117 {
118 	return readBytes( aData,nMaxBytesToRead );
119 }
120 // -----------------------------------------------------------------------------
skipBytes(sal_Int32 nBytesToSkip)121 void SAL_CALL OOdmaStream::skipBytes( sal_Int32 nBytesToSkip )
122 	throw( io::NotConnectedException,
123 		   io::BufferSizeExceededException,
124 		   io::IOException,
125 		   uno::RuntimeException )
126 {
127 	ensureInputStream();
128 	m_xInput->skipBytes(nBytesToSkip );
129 }
130 // -----------------------------------------------------------------------------
available()131 sal_Int32 SAL_CALL OOdmaStream::available()
132 	throw( io::NotConnectedException,
133 		   io::IOException,
134 		   uno::RuntimeException)
135 {
136 	ensureInputStream();
137 	return m_xInput->available();
138 }
139 // -----------------------------------------------------------------------------
writeBytes(const uno::Sequence<sal_Int8> & aData)140 void SAL_CALL OOdmaStream::writeBytes( const uno::Sequence< sal_Int8 >& aData )
141 	throw( io::NotConnectedException,
142 		   io::BufferSizeExceededException,
143 		   io::IOException,
144 		   uno::RuntimeException)
145 {
146 	ensureOutputStream();
147 	m_xOutput->writeBytes(aData);
148 	m_bModified = sal_True;
149 }
150 // -----------------------------------------------------------------------------
closeStream()151 void SAL_CALL OOdmaStream::closeStream() throw( io::NotConnectedException,io::IOException,uno::RuntimeException )
152 {
153 	if( m_xInput.is() )
154 	{
155 		m_xInput->closeInput();
156 		m_xInput		= NULL;
157 		m_xInputSeek	= NULL;
158 	}
159 	if(m_xOutput.is())
160 	{
161 		m_xOutput->closeOutput();
162 		m_xOutput		= NULL;
163 		m_xTruncate		= NULL;
164 		if(m_bModified)
165 			m_pProvider->saveDocument(m_aProp->m_sDocumentId);
166 	}
167 }
168 // -----------------------------------------------------------------------------
closeInput()169 void SAL_CALL OOdmaStream::closeInput()
170 	throw( io::NotConnectedException,
171 		   io::IOException,
172 		   uno::RuntimeException )
173 {
174 	osl::MutexGuard aGuard( m_aMutex );
175 	m_bInputStreamCalled = sal_False;
176 
177 	if( ! m_bOutputStreamCalled )
178 		closeStream();
179 }
180 // -----------------------------------------------------------------------------
closeOutput()181 void SAL_CALL OOdmaStream::closeOutput()
182 	throw( io::NotConnectedException,
183 		   io::IOException,
184 		   uno::RuntimeException )
185 {
186 	osl::MutexGuard aGuard( m_aMutex );
187 	m_bOutputStreamCalled = sal_False;
188 
189 	if( ! m_bInputStreamCalled )
190 		closeStream();
191 }
192 // -----------------------------------------------------------------------------
flush()193 void SAL_CALL OOdmaStream::flush()
194 	throw( io::NotConnectedException,
195 		   io::BufferSizeExceededException,
196 		   io::IOException,
197 		   uno::RuntimeException )
198 {
199 	ensureOutputStream();
200 	m_xOutput->flush();
201 }
202 // -----------------------------------------------------------------------------
ensureInputStream()203 void OOdmaStream::ensureInputStream() throw( io::IOException )
204 {
205 	try
206 	{
207 		if(!m_xInput.is())
208 		{
209 			m_xInput = m_pContent->openStream();
210 			m_xInputSeek = uno::Reference< io::XSeekable>(m_xInput,uno::UNO_QUERY);
211 		}
212 	}
213 	catch(const uno::Exception&)
214 	{
215 	}
216 	if(!m_xInput.is())
217 		throw io::IOException();
218 }
219 // -----------------------------------------------------------------------------
ensureOutputStream()220 void OOdmaStream::ensureOutputStream() throw( io::IOException )
221 {
222 	try
223 	{
224 		if(!m_xOutput.is())
225 		{
226 			ucb::OpenCommandArgument2 aCommand;
227 			aCommand.Mode = ucb::OpenMode::DOCUMENT;
228 			uno::Reference< io::XActiveDataStreamer > xActiveStreamer = new OActiveDataStreamer();
229 			aCommand.Sink = xActiveStreamer;
230 			m_pContent->executeCommand(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("open")),uno::makeAny(aCommand));
231 			if(xActiveStreamer.is())
232 			{
233 				uno::Reference< io::XStream> xStream = xActiveStreamer->getStream();
234 				if(xStream.is())
235 					m_xOutput = xStream->getOutputStream();
236 			}
237 		}
238 	}
239 	catch(const uno::Exception&)
240 	{
241 	}
242 	if(!m_xOutput.is())
243 		throw io::IOException();
244 	m_xTruncate = uno::Reference< io::XTruncate>(m_xOutput,uno::UNO_QUERY);
245 }
246 // -----------------------------------------------------------------------------
247 // XTruncate
truncate(void)248 void SAL_CALL OOdmaStream::truncate( void )
249 	throw( io::IOException,
250 		   uno::RuntimeException )
251 {
252 	if(m_xTruncate.is())
253 		m_xTruncate->truncate();
254 }
255 // -----------------------------------------------------------------------------
256 // XSeekable
seek(sal_Int64 location)257 void SAL_CALL OOdmaStream::seek(sal_Int64 location )
258 	throw( lang::IllegalArgumentException,
259 		   io::IOException,
260 		   uno::RuntimeException )
261 {
262 	ensureInputStream();
263 	if(m_xInputSeek.is())
264 		m_xInputSeek->seek(location);
265 }
266 // -----------------------------------------------------------------------------
getPosition()267 sal_Int64 SAL_CALL OOdmaStream::getPosition()
268 	throw( io::IOException,
269 		   uno::RuntimeException )
270 {
271 	ensureInputStream();
272 	return m_xInputSeek.is() ? m_xInputSeek->getPosition() : sal_Int64(0);
273 }
274 // -----------------------------------------------------------------------------
getLength()275 sal_Int64 SAL_CALL OOdmaStream::getLength()
276 	throw( io::IOException,
277 		   uno::RuntimeException )
278 {
279 	ensureInputStream();
280 	return m_xInputSeek.is() ? m_xInputSeek->getLength() : sal_Int64(0);
281 }
282 // -----------------------------------------------------------------------------
283