xref: /trunk/main/filter/source/xmlfilteradaptor/XmlFilterAdaptor.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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_filter.hxx"
26 #include <iostream>
27 #include <stdlib.h>
28 #include <ctype.h>
29 #include <stdio.h>
30 #include <rtl/ustring.hxx>
31 #include <tools/urlobj.hxx>
32 #include "XmlFilterAdaptor.hxx"
33 #include <osl/diagnose.h>
34 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
35 #include <com/sun/star/uno/RuntimeException.hpp>
36 #include <com/sun/star/io/XActiveDataSource.hpp>
37 #include <com/sun/star/io/XOutputStream.hpp>
38 #include <com/sun/star/io/XInputStream.hpp>
39 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
40 #include <com/sun/star/xml/sax/InputSource.hpp>
41 #include <com/sun/star/xml/sax/XParser.hpp>
42 #include <com/sun/star/frame/XConfigManager.hpp>
43 #include <com/sun/star/frame/XConfigManager.hpp>
44 #include <com/sun/star/xml/XImportFilter.hpp>
45 #include <com/sun/star/xml/XExportFilter.hpp>
46 #include <com/sun/star/frame/XModel.hpp>
47 #include <com/sun/star/frame/XController.hpp>
48 #include <com/sun/star/task/XStatusIndicator.hpp>
49 #include <com/sun/star/task/XStatusIndicatorFactory.hpp>
50 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
51 #include <com/sun/star/style/XStyleLoader.hpp>
52 #include <com/sun/star/container/XNameAccess.hpp>
53 #include <comphelper/sequenceashashmap.hxx>
54 #include <comphelper/mediadescriptor.hxx>
55 #include <com/sun/star/beans/PropertyAttribute.hpp>
56 #include <comphelper/genericpropertyset.hxx>
57 #include <comphelper/propertysetinfo.hxx>
58 
59 using namespace rtl;
60 using namespace comphelper;
61 using namespace com::sun::star::uno;
62 using namespace com::sun::star::lang;
63 using namespace com::sun::star::io;
64 using namespace com::sun::star::beans;
65 using namespace com::sun::star::container;
66 using namespace com::sun::star::document;
67 using namespace com::sun::star::style;
68 using namespace com::sun::star::xml;
69 using namespace com::sun::star::xml::sax;
70 using namespace ::com::sun::star::frame;
71 using namespace ::com::sun::star::task;
72 
73 #define MAP_LEN(x) x, sizeof(x) - 1
74 
75 Reference< com::sun::star::frame::XModel > xModel;
76 
importImpl(const Sequence<::com::sun::star::beans::PropertyValue> & aDescriptor)77 sal_Bool SAL_CALL XmlFilterAdaptor::importImpl( const Sequence< ::com::sun::star::beans::PropertyValue >& aDescriptor )
78 {
79     OUString udConvertClass=msUserData[0];
80     OUString udImport =msUserData[2];
81     sal_Int32 nSteps= 0;
82     sal_Int32 nProgressRange = 4;
83 
84     comphelper::MediaDescriptor aMediaMap(aDescriptor);
85     Reference< XStatusIndicator > xStatusIndicator(aMediaMap.getUnpackedValueOrDefault(
86         comphelper::MediaDescriptor::PROP_STATUSINDICATOR(), Reference< XStatusIndicator >()));
87 
88     if (xStatusIndicator.is()){
89         xStatusIndicator->start(OUString(  RTL_CONSTASCII_USTRINGPARAM( "Loading :" )),nProgressRange);
90     }
91 
92     OUString sXMLImportService (  udImport  );
93     const OUString sSaxParser ( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.xml.sax.Parser") );
94     Reference < XParser > xSaxParser( mxMSF->createInstance( sSaxParser ), UNO_QUERY );
95 
96     Sequence< Any > aAnys(1);
97     OUString aBaseURI;
98     if (aMediaMap.find(OUString::createFromAscii("URL"))->second >>= aBaseURI)
99     {
100         INetURLObject aURLObj(aBaseURI);
101         // base URI in this case is the URI of the actual saving location
102         // aURLObj.removeSegment();
103         aBaseURI = aURLObj.GetMainURL(INetURLObject::NO_DECODE);
104     }
105 
106     // create an XProperty set to configure the exporter for pretty printing
107     PropertyMapEntry aImportInfoMap[] =
108     {
109         { MAP_LEN( "BaseURI" ), 0, &::getCppuType((const OUString*)0), PropertyAttribute::MAYBEVOID, 0},
110         { NULL, 0, 0, NULL, 0, 0 }
111     };
112 
113     Reference< XPropertySet > xInfoSet(
114         GenericPropertySet_CreateInstance( new PropertySetInfo( aImportInfoMap ) ) );
115     xInfoSet->setPropertyValue(
116         OUString::createFromAscii( "BaseURI" ), makeAny( aBaseURI ));
117     aAnys[0] <<= xInfoSet;
118 
119 
120     Reference < XDocumentHandler > xHandler( mxMSF->createInstanceWithArguments( sXMLImportService, aAnys ), UNO_QUERY );
121     if(! xHandler.is()) {
122         OSL_ENSURE(sal_False, "XMLReader::Read: %s Unable to create service instance xHandler\n" );
123         return sal_False;
124     }
125     Reference < XImporter > xImporter( xHandler, UNO_QUERY );
126     xImporter->setTargetDocument ( mxDoc );
127 
128     if (xStatusIndicator.is()){
129         xStatusIndicator->setValue(nSteps++);
130     }
131 
132     //*********************
133     // Creating a ConverterBridge instance
134     //*********************
135     Reference< XInterface > xConvBridge(mxMSF->createInstance( udConvertClass ), UNO_QUERY);
136     if(! xConvBridge.is()){
137         OSL_ENSURE( sal_False,"XMLReader::Read: %s service missing\n" );
138         return sal_False;
139     }
140     if (xStatusIndicator.is())
141         xStatusIndicator->setValue(nSteps++);
142 
143     Reference< XImportFilter > xConverter( xConvBridge, UNO_QUERY );
144 
145     //********************
146     //Template Loading if Required
147     //********************
148     if (!msTemplateName.equalsAscii("")){
149         Reference< XStyleFamiliesSupplier > xstylefamiliessupplier(mxDoc, UNO_QUERY);
150 
151         Reference< XNameAccess >xName;
152         if(xstylefamiliessupplier.is()){
153             xName=xstylefamiliessupplier->getStyleFamilies();
154         }
155         Reference< XStyleLoader > xstyleLoader (xstylefamiliessupplier->getStyleFamilies(), UNO_QUERY);
156 
157 
158         if(xstyleLoader.is()){
159             xName=xstylefamiliessupplier->getStyleFamilies();
160         }
161 
162         Sequence < OUString > elementNames = xName->getElementNames();
163         if(xstyleLoader.is()){
164             Sequence<com::sun::star::beans::PropertyValue> pValue=xstyleLoader->getStyleLoaderOptions();
165 
166             //Load the Styles from the Template URL Supplied in the TypeDetection file
167             if(msTemplateName.indexOf(OUString::createFromAscii("file:"))==-1)
168             {
169                 Reference< XConfigManager >xCfgMgr ( mxMSF->createInstance(
170                     OUString::createFromAscii("com.sun.star.config.SpecialConfigManager") ), UNO_QUERY );
171                 OUString PathString=xCfgMgr->substituteVariables(OUString::createFromAscii("$(progurl)"));
172                 PathString=PathString.concat(OUString::createFromAscii("/"));
173                 msTemplateName=PathString.concat(msTemplateName);
174             }
175 
176             xstyleLoader->loadStylesFromURL(msTemplateName,pValue);
177         }
178     }
179 
180 //    sal_Bool xconv_ret = sal_True;
181 
182     if (xStatusIndicator.is()){
183         xStatusIndicator->setValue(nSteps++);
184     }
185     //*********************
186     // Calling Filtering Component
187     //*********************
188     try {
189         if (!xConverter->importer(aDescriptor,xHandler,msUserData)) {
190             if (xStatusIndicator.is())
191                 xStatusIndicator->end();
192             return sal_False;
193         }
194     }
195 #if OSL_DEBUG_LEVEL > 0
196     catch( Exception& e )
197 #else
198     catch( Exception& )
199 #endif
200     {
201         if (xStatusIndicator.is())
202             xStatusIndicator->end();
203 
204         OSL_ENSURE( sal_False, ::rtl::OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US).getStr());
205         return sal_False;
206     }
207     if (xStatusIndicator.is()) {
208         xStatusIndicator->setValue(nSteps++);
209         xStatusIndicator->end();
210     }
211     return sal_True;
212 }
213 
exportImpl(const Sequence<::com::sun::star::beans::PropertyValue> & aDescriptor)214 sal_Bool SAL_CALL XmlFilterAdaptor::exportImpl( const Sequence< ::com::sun::star::beans::PropertyValue >& aDescriptor )
215 {
216 
217     OUString udConvertClass = msUserData[0];
218     OUString udExport = msUserData[3];
219 
220     // Status Bar
221     sal_Int32 nSteps= 1;
222     sal_Int32 nProgressRange(3);
223     comphelper::MediaDescriptor aMediaMap(aDescriptor);
224     Reference< XStatusIndicator > xStatusIndicator(aMediaMap.getUnpackedValueOrDefault(
225         comphelper::MediaDescriptor::PROP_STATUSINDICATOR(), Reference< XStatusIndicator >()));
226 
227     if (xStatusIndicator.is())
228        xStatusIndicator->start(OUString(  RTL_CONSTASCII_USTRINGPARAM( "Saving :" )),nProgressRange);
229 
230     // Set up converter bridge.
231     Reference< com::sun::star::xml::XExportFilter > xConverter(mxMSF->createInstance(udConvertClass ), UNO_QUERY);
232     if(! xConverter.is()){
233       OSL_ENSURE( sal_False, "xml export sub service missing" );
234       return sal_False;
235     }
236 
237     if (xStatusIndicator.is())
238         xStatusIndicator->setValue(nSteps++);
239 
240     //put filter component into exporting state
241     if (!xConverter->exporter(aDescriptor, msUserData)) {
242         if (xStatusIndicator.is())
243             xStatusIndicator->end();
244         return sal_False;
245     }
246     if (xStatusIndicator.is())
247         xStatusIndicator->setValue(nSteps++);
248 
249     try{
250         // create the xml exporter service and supply the converter component
251         // which implements the document handler
252         Sequence < Any > aAnys (2);
253         aAnys[0] <<= xConverter;
254 
255 
256         // pretty printing is confusing for some filters so it is disabled by default
257         sal_Bool bPrettyPrint =
258             (msUserData.getLength() > 6 && msUserData[6].equalsIgnoreAsciiCaseAscii("true"));
259 
260         // --> OD 2008-11-25 #b6761284#
261         // export of <text:number> element for <text:list-item> elements are
262         // needed for certain filters.
263         sal_Bool bExportTextNumberElementForListItems =
264                             ( msUserData.getLength() > 7 &&
265                               msUserData[7].equalsIgnoreAsciiCaseAscii("true") );
266         // <--
267 
268         // get the base URI, so we can use relative links
269         OUString aBaseURI;
270         if (aMediaMap.find(OUString::createFromAscii("URL"))->second >>= aBaseURI)
271         {
272             INetURLObject aURLObj(aBaseURI);
273             // base URI in this case is the URI of the actual saving location
274             // aURLObj.removeSegment();
275             aBaseURI = aURLObj.GetMainURL(INetURLObject::NO_DECODE);
276         }
277 
278         // create an XProperty set to configure the exporter for pretty printing
279         PropertyMapEntry aImportInfoMap[] =
280         {
281             { MAP_LEN( "UsePrettyPrinting" ), 0, &::getCppuType((const sal_Bool*)0), PropertyAttribute::MAYBEVOID, 0},
282             // --> OD 2008-11-25 #b6761284#
283             { MAP_LEN( "ExportTextNumberElement" ), 0, &::getCppuType((const sal_Bool*)0), PropertyAttribute::MAYBEVOID, 0},
284             // <--
285             { MAP_LEN( "BaseURI" ), 0, &::getCppuType((const OUString*)0), PropertyAttribute::MAYBEVOID, 0},
286             { NULL, 0, 0, NULL, 0, 0 }
287         };
288 
289         Reference< XPropertySet > xInfoSet(
290             GenericPropertySet_CreateInstance( new PropertySetInfo( aImportInfoMap ) ) );
291         xInfoSet->setPropertyValue(
292             OUString::createFromAscii( "UsePrettyPrinting" ), makeAny( bPrettyPrint ));
293         // --> OD 2008-11-25 #b6761284#
294         xInfoSet->setPropertyValue(
295                         OUString::createFromAscii( "ExportTextNumberElement" ),
296                         makeAny( bExportTextNumberElementForListItems ));
297         // <--
298         xInfoSet->setPropertyValue(
299             OUString::createFromAscii( "BaseURI" ), makeAny( aBaseURI ));
300         aAnys[1] <<= xInfoSet;
301 
302         Reference< XExporter > xExporter( mxMSF->createInstanceWithArguments (
303                        udExport, aAnys ), UNO_QUERY_THROW );
304 
305         // attach to source document
306         xExporter->setSourceDocument( mxDoc );
307 
308         // get XFilter interface
309         Reference< XFilter > xFilter( xExporter, UNO_QUERY_THROW );
310 
311         if (xStatusIndicator.is())
312             xStatusIndicator->setValue(nSteps++);
313 
314         // call the actual filtering component
315         if (!xFilter->filter(aDescriptor))
316         {
317             if (xStatusIndicator.is())
318                 xStatusIndicator->end();
319             return sal_False;
320         }
321     }
322 #if OSL_DEBUG_LEVEL > 0
323     catch( Exception& exE )
324 #else
325     catch( Exception& )
326 #endif
327     {
328         OSL_ENSURE( sal_False, ::rtl::OUStringToOString( exE.Message, RTL_TEXTENCODING_ASCII_US).getStr());
329         if (xStatusIndicator.is())
330             xStatusIndicator->end();
331         return sal_False;
332     }
333 
334     // done
335     if (xStatusIndicator.is())
336         xStatusIndicator->end();
337     return sal_True;
338 }
339 
filter(const Sequence<::com::sun::star::beans::PropertyValue> & aDescriptor)340 sal_Bool SAL_CALL XmlFilterAdaptor::filter( const Sequence< ::com::sun::star::beans::PropertyValue >& aDescriptor )
341 {
342     return meType == FILTER_EXPORT ? exportImpl ( aDescriptor ) : importImpl ( aDescriptor );
343 }
cancel()344 void SAL_CALL XmlFilterAdaptor::cancel(  )
345 {
346 }
347 // XExporter
setSourceDocument(const Reference<::com::sun::star::lang::XComponent> & xDoc)348 void SAL_CALL XmlFilterAdaptor::setSourceDocument( const Reference< ::com::sun::star::lang::XComponent >& xDoc )
349 {
350     meType = FILTER_EXPORT;
351     mxDoc = xDoc;
352         com::sun::star::uno::Reference< com::sun::star::frame::XModel >rModel ( com::sun::star::uno::Reference< com::sun::star::frame::XModel >::query( xDoc ) );
353     xModel=rModel;
354 
355 }
356 
357 // XImporter
setTargetDocument(const Reference<::com::sun::star::lang::XComponent> & xDoc)358 void SAL_CALL XmlFilterAdaptor::setTargetDocument( const Reference< ::com::sun::star::lang::XComponent >& xDoc )
359 {
360     meType = FILTER_IMPORT;
361     mxDoc = xDoc;
362     //xModel = uno::Reference< frame::XModel >::query( xDoc );
363 }
364 // XInitialization
initialize(const Sequence<Any> & aArguments)365 void SAL_CALL XmlFilterAdaptor::initialize( const Sequence< Any >& aArguments )
366 {
367     Sequence < PropertyValue > aAnySeq;
368     sal_Int32 nLength = aArguments.getLength();
369     if ( nLength && ( aArguments[0] >>= aAnySeq ) )
370     {
371         comphelper::SequenceAsHashMap aMap(aAnySeq);
372         msFilterName = aMap.getUnpackedValueOrDefault(
373             OUString::createFromAscii("Type"), OUString());
374         msUserData = aMap.getUnpackedValueOrDefault(
375             OUString::createFromAscii("UserData"), Sequence< OUString >());
376         msTemplateName = aMap.getUnpackedValueOrDefault(
377             OUString::createFromAscii("TemplateName"), OUString());
378     }
379 }
XmlFilterAdaptor_getImplementationName()380 OUString XmlFilterAdaptor_getImplementationName ()
381 {
382     return OUString ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.comp.Writer.XmlFilterAdaptor" ) );
383 }
384 #define SERVICE_NAME1 "com.sun.star.document.ExportFilter"
385 #define SERVICE_NAME2 "com.sun.star.document.ImportFilter"
XmlFilterAdaptor_supportsService(const OUString & ServiceName)386 sal_Bool SAL_CALL XmlFilterAdaptor_supportsService( const OUString& ServiceName )
387 {
388     return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME1 ) ) ||
389            ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME2 ) );
390 }
XmlFilterAdaptor_getSupportedServiceNames()391 Sequence< OUString > SAL_CALL XmlFilterAdaptor_getSupportedServiceNames(  )
392 {
393     Sequence < OUString > aRet(2);
394     OUString* pArray = aRet.getArray();
395     pArray[0] =  OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME1 ) );
396     pArray[1] =  OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME2 ) );
397     return aRet;
398 }
399 #undef SERVICE_NAME1
400 #undef SERVICE_NAME2
401 
XmlFilterAdaptor_createInstance(const Reference<XMultiServiceFactory> & rSMgr)402 Reference< XInterface > SAL_CALL XmlFilterAdaptor_createInstance( const Reference< XMultiServiceFactory > & rSMgr)
403 {
404     return (cppu::OWeakObject*) new XmlFilterAdaptor( rSMgr );
405 }
406 
407 // XServiceInfo
getImplementationName()408 OUString SAL_CALL XmlFilterAdaptor::getImplementationName(  )
409 {
410     return XmlFilterAdaptor_getImplementationName();
411 }
supportsService(const OUString & rServiceName)412 sal_Bool SAL_CALL XmlFilterAdaptor::supportsService( const OUString& rServiceName )
413 {
414     return XmlFilterAdaptor_supportsService( rServiceName );
415 }
getSupportedServiceNames()416 Sequence< OUString > SAL_CALL XmlFilterAdaptor::getSupportedServiceNames(  )
417 {
418     return XmlFilterAdaptor_getSupportedServiceNames();
419 }
420