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... 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 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 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 224 void XFlatXml::startDocument() throw (SAXException,RuntimeException){ 225 OSL_ASSERT(m_rDocumentHandler.is()); 226 m_rDocumentHandler->startDocument(); 227 } 228 229 void XFlatXml::endDocument() throw (SAXException,RuntimeException){ 230 OSL_ASSERT(m_rDocumentHandler.is()); 231 m_rDocumentHandler->endDocument(); 232 } 233 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 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 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 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 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 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 // -------------------------------------- 280 Reference< XInterface > SAL_CALL CreateInstance( const Reference< XMultiServiceFactory > &r) 281 { 282 return Reference< XInterface >(( OWeakObject *)new XFlatXml(r)); 283 } 284 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 { 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 // http://wiki.services.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 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