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