xref: /aoo41x/main/package/source/xstor/xfactory.cxx (revision cdf0e10c)
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_package.hxx"
30 #include <com/sun/star/ucb/XSimpleFileAccess.hpp>
31 #include <com/sun/star/embed/ElementModes.hpp>
32 #include <com/sun/star/embed/StorageFormats.hpp>
33 #include <com/sun/star/beans/PropertyValue.hpp>
34 #include <com/sun/star/io/XSeekable.hpp>
35 
36 #include <comphelper/storagehelper.hxx>
37 
38 #include "xfactory.hxx"
39 #include "xstorage.hxx"
40 
41 
42 using namespace ::com::sun::star;
43 
44 //-------------------------------------------------------------------------
45 sal_Bool CheckPackageSignature_Impl( const uno::Reference< io::XInputStream >& xInputStream,
46 									 const uno::Reference< io::XSeekable >& xSeekable )
47 {
48 	if ( !xInputStream.is() || !xSeekable.is() )
49 		throw uno::RuntimeException();
50 
51 	if ( xSeekable->getLength() )
52 	{
53 		uno::Sequence< sal_Int8 > aData( 4 );
54 		xSeekable->seek( 0 );
55 		sal_Int32 nRead = xInputStream->readBytes( aData, 4 );
56 		xSeekable->seek( 0 );
57 
58 		// TODO/LATER: should the disk spanned files be supported?
59     	// 0x50, 0x4b, 0x07, 0x08
60 		return ( nRead == 4 && aData[0] == 0x50 && aData[1] == 0x4b && aData[2] == 0x03 && aData[3] == 0x04 );
61 	}
62 	else
63 		return sal_True; // allow to create a storage based on empty stream
64 }
65 
66 //-------------------------------------------------------------------------
67 uno::Sequence< ::rtl::OUString > SAL_CALL OStorageFactory::impl_staticGetSupportedServiceNames()
68 {
69     uno::Sequence< ::rtl::OUString > aRet(2);
70     aRet[0] = ::rtl::OUString::createFromAscii("com.sun.star.embed.StorageFactory");
71     aRet[1] = ::rtl::OUString::createFromAscii("com.sun.star.comp.embed.StorageFactory");
72     return aRet;
73 }
74 
75 //-------------------------------------------------------------------------
76 ::rtl::OUString SAL_CALL OStorageFactory::impl_staticGetImplementationName()
77 {
78     return ::rtl::OUString::createFromAscii("com.sun.star.comp.embed.StorageFactory");
79 }
80 
81 //-------------------------------------------------------------------------
82 uno::Reference< uno::XInterface > SAL_CALL OStorageFactory::impl_staticCreateSelfInstance(
83 			const uno::Reference< lang::XMultiServiceFactory >& xServiceManager )
84 {
85 	return uno::Reference< uno::XInterface >( *new OStorageFactory( xServiceManager ) );
86 }
87 
88 //-------------------------------------------------------------------------
89 uno::Reference< uno::XInterface > SAL_CALL OStorageFactory::createInstance()
90 	throw ( uno::Exception,
91 			uno::RuntimeException )
92 {
93 	// TODO: reimplement TempStream service to support XStream interface
94 	uno::Reference < io::XStream > xTempStream(
95 						m_xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ),
96 						uno::UNO_QUERY );
97 
98 	if ( !xTempStream.is() )
99 		throw uno::RuntimeException(); // TODO:
100 
101 	return uno::Reference< uno::XInterface >(
102 				static_cast< OWeakObject* >( new OStorage(	xTempStream,
103 															embed::ElementModes::READWRITE,
104 															uno::Sequence< beans::PropertyValue >(),
105 															m_xFactory,
106 															embed::StorageFormats::PACKAGE ) ),
107 				uno::UNO_QUERY );
108 }
109 
110 //-------------------------------------------------------------------------
111 uno::Reference< uno::XInterface > SAL_CALL OStorageFactory::createInstanceWithArguments(
112 			const uno::Sequence< uno::Any >& aArguments )
113 	throw ( uno::Exception,
114 			uno::RuntimeException )
115 {
116 	// The request for storage can be done with up to three arguments
117 
118 	// The first argument specifies a source for the storage
119 	// it can be URL, XStream, XInputStream.
120 	// The second value is a mode the storage should be open in.
121 	// And the third value is a media descriptor.
122 
123 	sal_Int32 nArgNum = aArguments.getLength();
124 	OSL_ENSURE( nArgNum < 4, "Wrong parameter number" );
125 
126 	if ( !nArgNum )
127 		return createInstance();
128 
129 	// first try to retrieve storage open mode if any
130 	// by default the storage will be open in readonly mode
131 	sal_Int32 nStorageMode = embed::ElementModes::READ;
132 	if ( nArgNum >= 2 )
133 	{
134 		if( !( aArguments[1] >>= nStorageMode ) )
135 		{
136 			OSL_ENSURE( sal_False, "Wrong second argument!\n" );
137 			throw lang::IllegalArgumentException(); // TODO:
138 		}
139 		// it's allways possible to read written storage in this implementation
140 		nStorageMode |= embed::ElementModes::READ;
141 	}
142 
143 	if ( ( nStorageMode & embed::ElementModes::TRUNCATE ) == embed::ElementModes::TRUNCATE
144 	  && ( nStorageMode & embed::ElementModes::WRITE ) != embed::ElementModes::WRITE )
145 		throw lang::IllegalArgumentException(); // TODO:
146 
147 	// retrieve storage source stream
148 	::rtl::OUString aURL;
149 	uno::Reference< io::XStream > xStream;
150 	uno::Reference< io::XInputStream > xInputStream;
151 
152 	if ( aArguments[0] >>= aURL )
153 	{
154 		if ( !aURL.getLength() )
155 		{
156 			OSL_ENSURE( sal_False, "Empty URL is provided!\n" );
157 			throw lang::IllegalArgumentException(); // TODO:
158 		}
159 
160 		if ( aURL.equalsIgnoreAsciiCaseAsciiL( "vnd.sun.star.pkg", 16 ) )
161 		{
162 			OSL_ENSURE( sal_False, "Packages URL's are not valid for storages!\n" ); // ???
163 			throw lang::IllegalArgumentException(); // TODO:
164 		}
165 
166 		uno::Reference < ::com::sun::star::ucb::XSimpleFileAccess > xTempAccess(
167 				m_xFactory->createInstance (
168 						::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ),
169 				uno::UNO_QUERY );
170 
171 		if ( !xTempAccess.is() )
172 			throw uno::RuntimeException(); // TODO:
173 
174 		if ( nStorageMode & embed::ElementModes::WRITE )
175 			xStream = xTempAccess->openFileReadWrite( aURL );
176 		else
177 			xInputStream = xTempAccess->openFileRead( aURL );
178 	}
179 	else if ( !( aArguments[0] >>= xStream ) && !( aArguments[0] >>= xInputStream ) )
180 	{
181 		OSL_ENSURE( sal_False, "Wrong first argument!\n" );
182 		throw uno::Exception(); // TODO: Illegal argument
183 	}
184 
185 	// retrieve mediadescriptor and set storage properties
186 	uno::Sequence< beans::PropertyValue > aDescr;
187 	uno::Sequence< beans::PropertyValue > aPropsToSet;
188 
189 	sal_Int32 nStorageType = embed::StorageFormats::PACKAGE;
190 
191 	if ( nArgNum >= 3 )
192 	{
193 		if( aArguments[2] >>= aDescr )
194 		{
195 			if ( aURL.getLength() )
196 			{
197 				aPropsToSet.realloc(1);
198 				aPropsToSet[0].Name = ::rtl::OUString::createFromAscii( "URL" );
199 				aPropsToSet[0].Value <<= aURL;
200 			}
201 
202 			for ( sal_Int32 nInd = 0, nNumArgs = 1; nInd < aDescr.getLength(); nInd++ )
203 			{
204 				if ( aDescr[nInd].Name.equalsAscii( "InteractionHandler" )
205 				  || aDescr[nInd].Name.equalsAscii( "Password" )
206 				  || aDescr[nInd].Name.equalsAscii( "RepairPackage" )
207 				  || aDescr[nInd].Name.equalsAscii( "StatusIndicator" ) )
208 				  // || aDescr[nInd].Name.equalsAscii( "Unpacked" ) // TODO:
209 				{
210 					aPropsToSet.realloc( ++nNumArgs );
211 					aPropsToSet[nNumArgs-1].Name = aDescr[nInd].Name;
212 					aPropsToSet[nNumArgs-1].Value = aDescr[nInd].Value;
213 				}
214 				else if ( aDescr[nInd].Name.equalsAscii( "StorageFormat" ) )
215 				{
216 					::rtl::OUString aFormatName;
217                     sal_Int32 nFormatID = 0;
218                     if ( aDescr[nInd].Value >>= aFormatName )
219                     {
220                         if ( aFormatName.equals( PACKAGE_STORAGE_FORMAT_STRING ) )
221                             nStorageType = embed::StorageFormats::PACKAGE;
222                         else if ( aFormatName.equals( ZIP_STORAGE_FORMAT_STRING ) )
223                             nStorageType = embed::StorageFormats::ZIP;
224                         else if ( aFormatName.equals( OFOPXML_STORAGE_FORMAT_STRING ) )
225                             nStorageType = embed::StorageFormats::OFOPXML;
226                         else
227                             throw lang::IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 1 );
228                     }
229                     else if ( aDescr[nInd].Value >>= nFormatID )
230                     {
231                         if ( nFormatID != embed::StorageFormats::PACKAGE
232                           && nFormatID != embed::StorageFormats::ZIP
233                           && nFormatID != embed::StorageFormats::OFOPXML )
234                             throw lang::IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 1 );
235 
236                         nStorageType = nFormatID;
237                     }
238                     else
239                         throw lang::IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 1 );
240 				}
241 				else
242 					OSL_ENSURE( sal_False, "Unacceptable property, will be ignored!\n" );
243 			}
244 		}
245 		else
246 		{
247 			OSL_ENSURE( sal_False, "Wrong third argument!\n" );
248 			throw uno::Exception(); // TODO: Illegal argument
249 		}
250 
251 	}
252 
253 	// create storage based on source
254 	if ( xInputStream.is() )
255 	{
256 		// if xInputStream is set the storage should be open from it
257 		if ( ( nStorageMode & embed::ElementModes::WRITE ) )
258 		  	throw uno::Exception(); // TODO: access denied
259 
260 		uno::Reference< io::XSeekable > xSeekable( xInputStream, uno::UNO_QUERY );
261 		if ( !xSeekable.is() )
262 		{
263 			// TODO: wrap stream to let it be seekable
264 			OSL_ENSURE( sal_False, "Nonseekable streams are not supported for now!\n" );
265 		}
266 
267 		if ( !CheckPackageSignature_Impl( xInputStream, xSeekable ) )
268 			throw io::IOException(); // TODO: this is not a package file
269 
270 		return uno::Reference< uno::XInterface >(
271 					static_cast< OWeakObject* >( new OStorage( xInputStream, nStorageMode, aPropsToSet, m_xFactory, nStorageType ) ),
272 					uno::UNO_QUERY );
273 	}
274 	else if ( xStream.is() )
275 	{
276                if ( ( ( nStorageMode & embed::ElementModes::WRITE ) && !xStream->getOutputStream().is() )
277 		  || !xStream->getInputStream().is() )
278 		  	throw uno::Exception(); // TODO: access denied
279 
280 		uno::Reference< io::XSeekable > xSeekable( xStream, uno::UNO_QUERY );
281 		if ( !xSeekable.is() )
282 		{
283 			// TODO: wrap stream to let it be seekable
284 			OSL_ENSURE( sal_False, "Nonseekable streams are not supported for now!\n" );
285 		}
286 
287 		if ( !CheckPackageSignature_Impl( xStream->getInputStream(), xSeekable ) )
288 			throw io::IOException(); // TODO: this is not a package file
289 
290 		return uno::Reference< uno::XInterface >(
291 					static_cast< OWeakObject* >( new OStorage( xStream, nStorageMode, aPropsToSet, m_xFactory, nStorageType ) ),
292 					uno::UNO_QUERY );
293 	}
294 
295 	throw uno::Exception(); // general error during creation
296 }
297 
298 //-------------------------------------------------------------------------
299 ::rtl::OUString SAL_CALL OStorageFactory::getImplementationName()
300 	throw ( uno::RuntimeException )
301 {
302 	return impl_staticGetImplementationName();
303 }
304 
305 //-------------------------------------------------------------------------
306 sal_Bool SAL_CALL OStorageFactory::supportsService( const ::rtl::OUString& ServiceName )
307 	throw ( uno::RuntimeException )
308 {
309 	uno::Sequence< ::rtl::OUString > aSeq = impl_staticGetSupportedServiceNames();
310 
311 	for ( sal_Int32 nInd = 0; nInd < aSeq.getLength(); nInd++ )
312     	if ( ServiceName.compareTo( aSeq[nInd] ) == 0 )
313         	return sal_True;
314 
315 	return sal_False;
316 }
317 
318 //-------------------------------------------------------------------------
319 uno::Sequence< ::rtl::OUString > SAL_CALL OStorageFactory::getSupportedServiceNames()
320 	throw ( uno::RuntimeException )
321 {
322 	return impl_staticGetSupportedServiceNames();
323 }
324 
325