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 #include <cppuhelper/factory.hxx>
25 #include <cppuhelper/servicefactory.hxx>
26 #include <cppuhelper/implbase1.hxx>
27 #include <cppuhelper/implbase2.hxx>
28 #include <cppuhelper/implbase3.hxx>
29 #include <cppuhelper/implbase.hxx>
30
31 #include <com/sun/star/lang/XComponent.hpp>
32
33 #include <com/sun/star/uno/Any.hxx>
34 #include <com/sun/star/uno/Type.hxx>
35
36 #include <com/sun/star/beans/PropertyValue.hpp>
37
38 #include <com/sun/star/xml/sax/XParser.hpp>
39 #include <com/sun/star/xml/sax/InputSource.hpp>
40 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
41 #include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp>
42 #include <com/sun/star/xml/sax/SAXException.hpp>
43 #include <com/sun/star/xml/XImportFilter.hpp>
44 #include <com/sun/star/xml/XExportFilter.hpp>
45
46 #include <com/sun/star/io/XInputStream.hpp>
47 #include <com/sun/star/io/XOutputStream.hpp>
48 #include <com/sun/star/io/XActiveDataSource.hpp>
49 #include <com/sun/star/io/XSeekable.hpp>
50
51 using namespace ::rtl;
52 using namespace ::cppu;
53 using namespace ::osl;
54 using namespace ::com::sun::star::beans;
55 using namespace ::com::sun::star::io;
56 using namespace ::com::sun::star::uno;
57 using namespace ::com::sun::star::lang;
58 using namespace ::com::sun::star::registry;
59 using namespace ::com::sun::star::xml;
60 using namespace ::com::sun::star::xml::sax;
61
62 namespace XFlatXml {
63
64 class XFlatXml : public WeakImplHelper3< XImportFilter, XExportFilter, XDocumentHandler>
65 {
66 private:
67 // the UNO ServiceFactory
68 Reference< XMultiServiceFactory > m_rServiceFactory;
69
70 // DocumentHandler interface of the css::xml::sax::Writer service
71 Reference < XExtendedDocumentHandler > m_rDocumentHandler;
72
73 // controls pretty-printing
74 sal_Bool m_bPrettyPrint;
75
76 public:
77
78 // ctor...
XFlatXml(const Reference<XMultiServiceFactory> & r)79 XFlatXml( const Reference< XMultiServiceFactory > &r )
80 : m_rServiceFactory(r)
81 , m_bPrettyPrint(sal_True)
82 {}
83
84 // XImportFilter
85 virtual sal_Bool SAL_CALL importer(
86 const Sequence<PropertyValue>& aSourceData,
87 const Reference<XDocumentHandler>& xHandler,
88 const Sequence<OUString>& msUserData)
89 throw(RuntimeException);
90
91 // XExportFilter
92 virtual sal_Bool SAL_CALL exporter(
93 const Sequence<PropertyValue>& aSourceData,
94 const Sequence<OUString>& msUserData)
95 throw(RuntimeException);
96
97 // XDocumentHandler
98 virtual void SAL_CALL startDocument()
99 throw (SAXException,RuntimeException);
100 virtual void SAL_CALL endDocument()
101 throw (SAXException, RuntimeException);
102 virtual void SAL_CALL startElement(const OUString& str, const Reference<XAttributeList>& attriblist)
103 throw (SAXException,RuntimeException);
104 virtual void SAL_CALL endElement(const OUString& str)
105 throw (SAXException, RuntimeException);
106 virtual void SAL_CALL characters(const OUString& str)
107 throw (SAXException, RuntimeException);
108 virtual void SAL_CALL ignorableWhitespace(const OUString& str)
109 throw (SAXException, RuntimeException);
110 virtual void SAL_CALL processingInstruction(const OUString& str, const OUString& str2)
111 throw (com::sun::star::xml::sax::SAXException,RuntimeException);
112 virtual void SAL_CALL setDocumentLocator(const Reference<XLocator>& doclocator)
113 throw (SAXException,RuntimeException);
114 };
115
importer(const Sequence<PropertyValue> & aSourceData,const Reference<XDocumentHandler> & xHandler,const Sequence<OUString> & msUserData)116 sal_Bool XFlatXml::importer(
117 const Sequence<PropertyValue>& aSourceData,
118 const Reference<XDocumentHandler>& xHandler,
119 const Sequence<OUString>& msUserData)
120 throw (RuntimeException)
121 {
122 // get information from media descriptor
123 // the input stream that represents the imported file
124 // is most important here since we need to supply it to
125 // the sax parser that drives the supplied document handler
126 sal_Int32 nLength = aSourceData.getLength();
127 OUString aName, aFileName, aURL;
128 Reference< XInputStream > xInputStream;
129 for ( sal_Int32 i = 0 ; i < nLength; i++)
130 {
131 aName = aSourceData[i].Name;
132 if (aName.equalsAscii("InputStream"))
133 aSourceData[i].Value >>= xInputStream;
134 else if ( aName.equalsAscii("FileName"))
135 aSourceData[i].Value >>= aFileName;
136 else if ( aName.equalsAscii("URL"))
137 aSourceData[i].Value >>= aURL;
138 }
139
140 // we need an input stream
141 OSL_ASSERT(xInputStream.is());
142 if (!xInputStream.is()) return sal_False;
143
144 // rewind seekable stream
145 Reference< XSeekable > xSeek(xInputStream, UNO_QUERY);
146 if (xSeek.is())
147 xSeek->seek(0);
148
149
150 // create SAX parser that will read the document file
151 // and provide events to xHandler passed to this call
152 Reference < XParser > xSaxParser( m_rServiceFactory->createInstance(
153 OUString::createFromAscii("com.sun.star.xml.sax.Parser")), UNO_QUERY );
154 OSL_ASSERT(xSaxParser.is());
155 if(!xSaxParser.is())return sal_False;
156
157 // let the parser try to send the sax event to the document handler
158 try
159 {
160 InputSource aInput;
161 aInput.sSystemId = aURL;
162 aInput.sPublicId = aURL;
163 aInput.aInputStream = xInputStream;
164 xSaxParser->setDocumentHandler(xHandler);
165 xSaxParser->parseStream(aInput);
166 }
167 catch( Exception &exc)
168 {
169 // something went wrong
170 OSL_ENSURE(0, rtl::OUStringToOString(exc.Message,RTL_TEXTENCODING_UTF8).getStr());
171 return sal_False;
172 }
173
174 // done
175 return sal_True;
176 }
177
exporter(const Sequence<PropertyValue> & aSourceData,const Sequence<OUString> & msUserData)178 sal_Bool XFlatXml::exporter(
179 const Sequence<PropertyValue>& aSourceData,
180 const Sequence<OUString>& msUserData)
181 throw (RuntimeException)
182 {
183
184 // read source data
185 // we are especially interested in the output stream
186 // since that is where our xml-writer will push the data
187 // from its data-source interface
188 OUString aName, sURL;
189 Reference<XOutputStream> rOutputStream;
190 sal_Int32 nLength = aSourceData.getLength();
191 for ( sal_Int32 i = 0 ; i < nLength; i++)
192 {
193 aName = aSourceData[i].Name;
194 if ( aName.equalsAscii("OutputStream"))
195 aSourceData[i].Value >>= rOutputStream;
196 else if ( aName.equalsAscii("URL" ))
197 aSourceData[i].Value >>= sURL;
198 }
199
200 if (!m_rDocumentHandler.is()) {
201 // get the document writer
202 m_rDocumentHandler = Reference<XExtendedDocumentHandler>(
203 m_rServiceFactory->createInstance(
204 OUString::createFromAscii("com.sun.star.xml.sax.Writer")),
205 UNO_QUERY);
206 OSL_ASSERT(m_rDocumentHandler.is());
207 if (!m_rDocumentHandler.is()) return sal_False;
208 }
209 // get data source interface ...
210 Reference< XActiveDataSource > rDataSource(m_rDocumentHandler, UNO_QUERY);
211 OSL_ASSERT(rDataSource.is());
212 if (!rDataSource.is()) return sal_False;
213 OSL_ASSERT(rOutputStream.is());
214 if (!rOutputStream.is()) return sal_False;
215 // ... and set output stream
216 rDataSource->setOutputStream(rOutputStream);
217
218 return sal_True;
219 }
220
221 // for the DocumentHandler implementation, we just proxy the the
222 // events to the XML writer that we created upon the output stream
223 // that was provided by the XMLFilterAdapter
startDocument()224 void XFlatXml::startDocument() throw (SAXException,RuntimeException){
225 OSL_ASSERT(m_rDocumentHandler.is());
226 m_rDocumentHandler->startDocument();
227 }
228
endDocument()229 void XFlatXml::endDocument() throw (SAXException,RuntimeException){
230 OSL_ASSERT(m_rDocumentHandler.is());
231 m_rDocumentHandler->endDocument();
232 }
233
startElement(const OUString & str,const Reference<XAttributeList> & attriblist)234 void XFlatXml::startElement(const OUString& str, const Reference<XAttributeList>& attriblist)
235 throw (SAXException, RuntimeException)
236 {
237 OSL_ASSERT(m_rDocumentHandler.is());
238 m_rDocumentHandler->startElement(str, attriblist);
239 }
240
endElement(const OUString & str)241 void XFlatXml::endElement(const OUString& str)
242 throw (SAXException, RuntimeException)
243 {
244 OSL_ASSERT(m_rDocumentHandler.is());
245 m_rDocumentHandler->endElement(str);
246 }
247
characters(const OUString & str)248 void XFlatXml::characters(const OUString& str)
249 throw (SAXException, RuntimeException)
250 {
251 OSL_ASSERT(m_rDocumentHandler.is());
252 m_rDocumentHandler->characters(str);
253 }
254
ignorableWhitespace(const OUString & str)255 void XFlatXml::ignorableWhitespace(const OUString& str)
256 throw (SAXException, RuntimeException)
257 {
258 OSL_ASSERT(m_rDocumentHandler.is());
259 if (!m_bPrettyPrint) return;
260 m_rDocumentHandler->ignorableWhitespace(str);
261 }
262
processingInstruction(const OUString & str,const OUString & str2)263 void XFlatXml::processingInstruction(const OUString& str, const OUString& str2)
264 throw (SAXException, RuntimeException)
265 {
266 OSL_ASSERT(m_rDocumentHandler.is());
267 m_rDocumentHandler->processingInstruction(str, str2);
268 }
269
setDocumentLocator(const Reference<XLocator> & doclocator)270 void XFlatXml::setDocumentLocator(const Reference<XLocator>& doclocator)
271 throw (SAXException, RuntimeException)
272 {
273 OSL_ASSERT(m_rDocumentHandler.is());
274 m_rDocumentHandler->setDocumentLocator(doclocator);
275 }
276
277 // --------------------------------------
278 // Component management
279 // --------------------------------------
CreateInstance(const Reference<XMultiServiceFactory> & r)280 Reference< XInterface > SAL_CALL CreateInstance( const Reference< XMultiServiceFactory > &r)
281 {
282 return Reference< XInterface >(( OWeakObject *)new XFlatXml(r));
283 }
284
getSupportedServiceNames()285 Sequence< OUString > getSupportedServiceNames()
286 {
287 static Sequence < OUString > *pNames = 0;
288 if( ! pNames )
289 {
290 MutexGuard guard( Mutex::getGlobalMutex() );
291 if( !pNames )
292 {
293 static Sequence< OUString > seqNames(1);
294 seqNames.getArray()[0] = OUString::createFromAscii(
295 "devguide.officedev.samples.filter.FlatXmlCpp");
296 pNames = &seqNames;
297 }
298 }
299 return *pNames;
300 }
301
302 }
303
304 using namespace XFlatXml;
305 #define IMPLEMENTATION_NAME "devguide.officedev.samples.filter.FlatXmlCpp"
306
307
308 extern "C"
309 {
component_getImplementationEnvironment(const sal_Char ** ppEnvTypeName,uno_Environment ** ppEnv)310 SAL_DLLPUBLIC_EXPORT void SAL_CALL component_getImplementationEnvironment(
311 const sal_Char ** ppEnvTypeName, uno_Environment ** ppEnv )
312 {
313 *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
314 }
315
316 // This method not longer necessary since OOo 3.4 where the component registration was
317 // was changed to passive component registration. For more details see
318 // https://wiki.openoffice.org/wiki/Passive_Component_Registration
319 //
320 // SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL component_writeInfo(void * pServiceManager, void * pRegistryKey )
321 // {
322 // if (pRegistryKey)
323 // {
324 // try
325 // {
326 // Reference< XRegistryKey > xNewKey(
327 // reinterpret_cast< XRegistryKey * >( pRegistryKey )->createKey(
328 // OUString::createFromAscii( "/" IMPLEMENTATION_NAME "/UNO/SERVICES" ) ) );
329
330 // const Sequence< OUString > & rSNL = getSupportedServiceNames();
331 // const OUString * pArray = rSNL.getConstArray();
332 // for ( sal_Int32 nPos = rSNL.getLength(); nPos--; )
333 // xNewKey->createKey( pArray[nPos] );
334
335 // return sal_True;
336 // }
337 // catch (InvalidRegistryException &)
338 // {
339 // OSL_ENSURE( sal_False, "### InvalidRegistryException!" );
340 // }
341 // }
342 // return sal_False;
343 // }
344
component_getFactory(const sal_Char * pImplName,void * pServiceManager,void * pRegistryKey)345 SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory(
346 const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
347 {
348 void * pRet = 0;
349
350 if (pServiceManager && rtl_str_compare( pImplName, IMPLEMENTATION_NAME ) == 0)
351 {
352 Reference< XSingleServiceFactory > xFactory( createSingleFactory(
353 reinterpret_cast< XMultiServiceFactory * >( pServiceManager ),
354 OUString::createFromAscii( pImplName ),
355 CreateInstance, getSupportedServiceNames() ) );
356
357 if (xFactory.is())
358 {
359 xFactory->acquire();
360 pRet = xFactory.get();
361 }
362 }
363 return pRet;
364 }
365
366 } // extern "C"
367
368