/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace ::rtl; using namespace ::cppu; using namespace ::osl; using namespace ::com::sun::star::beans; using namespace ::com::sun::star::io; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::lang; using namespace ::com::sun::star::registry; using namespace ::com::sun::star::xml; using namespace ::com::sun::star::xml::sax; namespace XFlatXml { class XFlatXml : public WeakImplHelper3< XImportFilter, XExportFilter, XDocumentHandler> { private: // the UNO ServiceFactory Reference< XMultiServiceFactory > m_rServiceFactory; // DocumentHandler interface of the css::xml::sax::Writer service Reference < XExtendedDocumentHandler > m_rDocumentHandler; // controls pretty-printing sal_Bool m_bPrettyPrint; public: // ctor... XFlatXml( const Reference< XMultiServiceFactory > &r ) : m_rServiceFactory(r) , m_bPrettyPrint(sal_True) {} // XImportFilter virtual sal_Bool SAL_CALL importer( const Sequence& aSourceData, const Reference& xHandler, const Sequence& msUserData) throw(RuntimeException); // XExportFilter virtual sal_Bool SAL_CALL exporter( const Sequence& aSourceData, const Sequence& msUserData) throw(RuntimeException); // XDocumentHandler virtual void SAL_CALL startDocument() throw (SAXException,RuntimeException); virtual void SAL_CALL endDocument() throw (SAXException, RuntimeException); virtual void SAL_CALL startElement(const OUString& str, const Reference& attriblist) throw (SAXException,RuntimeException); virtual void SAL_CALL endElement(const OUString& str) throw (SAXException, RuntimeException); virtual void SAL_CALL characters(const OUString& str) throw (SAXException, RuntimeException); virtual void SAL_CALL ignorableWhitespace(const OUString& str) throw (SAXException, RuntimeException); virtual void SAL_CALL processingInstruction(const OUString& str, const OUString& str2) throw (com::sun::star::xml::sax::SAXException,RuntimeException); virtual void SAL_CALL setDocumentLocator(const Reference& doclocator) throw (SAXException,RuntimeException); }; sal_Bool XFlatXml::importer( const Sequence& aSourceData, const Reference& xHandler, const Sequence& msUserData) throw (RuntimeException) { // get information from media descriptor // the input stream that represents the imported file // is most important here since we need to supply it to // the sax parser that drives the supplied document handler sal_Int32 nLength = aSourceData.getLength(); OUString aName, aFileName, aURL; Reference< XInputStream > xInputStream; for ( sal_Int32 i = 0 ; i < nLength; i++) { aName = aSourceData[i].Name; if (aName.equalsAscii("InputStream")) aSourceData[i].Value >>= xInputStream; else if ( aName.equalsAscii("FileName")) aSourceData[i].Value >>= aFileName; else if ( aName.equalsAscii("URL")) aSourceData[i].Value >>= aURL; } // we need an input stream OSL_ASSERT(xInputStream.is()); if (!xInputStream.is()) return sal_False; // rewind seekable stream Reference< XSeekable > xSeek(xInputStream, UNO_QUERY); if (xSeek.is()) xSeek->seek(0); // create SAX parser that will read the document file // and provide events to xHandler passed to this call Reference < XParser > xSaxParser( m_rServiceFactory->createInstance( OUString::createFromAscii("com.sun.star.xml.sax.Parser")), UNO_QUERY ); OSL_ASSERT(xSaxParser.is()); if(!xSaxParser.is())return sal_False; // let the parser try to send the sax event to the document handler try { InputSource aInput; aInput.sSystemId = aURL; aInput.sPublicId = aURL; aInput.aInputStream = xInputStream; xSaxParser->setDocumentHandler(xHandler); xSaxParser->parseStream(aInput); } catch( Exception &exc) { // something went wrong OSL_ENSURE(0, rtl::OUStringToOString(exc.Message,RTL_TEXTENCODING_UTF8).getStr()); return sal_False; } // done return sal_True; } sal_Bool XFlatXml::exporter( const Sequence& aSourceData, const Sequence& msUserData) throw (RuntimeException) { // read source data // we are especially interested in the output stream // since that is where our xml-writer will push the data // from its data-source interface OUString aName, sURL; Reference rOutputStream; sal_Int32 nLength = aSourceData.getLength(); for ( sal_Int32 i = 0 ; i < nLength; i++) { aName = aSourceData[i].Name; if ( aName.equalsAscii("OutputStream")) aSourceData[i].Value >>= rOutputStream; else if ( aName.equalsAscii("URL" )) aSourceData[i].Value >>= sURL; } if (!m_rDocumentHandler.is()) { // get the document writer m_rDocumentHandler = Reference( m_rServiceFactory->createInstance( OUString::createFromAscii("com.sun.star.xml.sax.Writer")), UNO_QUERY); OSL_ASSERT(m_rDocumentHandler.is()); if (!m_rDocumentHandler.is()) return sal_False; } // get data source interface ... Reference< XActiveDataSource > rDataSource(m_rDocumentHandler, UNO_QUERY); OSL_ASSERT(rDataSource.is()); if (!rDataSource.is()) return sal_False; OSL_ASSERT(rOutputStream.is()); if (!rOutputStream.is()) return sal_False; // ... and set output stream rDataSource->setOutputStream(rOutputStream); return sal_True; } // for the DocumentHandler implementation, we just proxy the the // events to the XML writer that we created upon the output stream // that was provided by the XMLFilterAdapter void XFlatXml::startDocument() throw (SAXException,RuntimeException){ OSL_ASSERT(m_rDocumentHandler.is()); m_rDocumentHandler->startDocument(); } void XFlatXml::endDocument() throw (SAXException,RuntimeException){ OSL_ASSERT(m_rDocumentHandler.is()); m_rDocumentHandler->endDocument(); } void XFlatXml::startElement(const OUString& str, const Reference& attriblist) throw (SAXException, RuntimeException) { OSL_ASSERT(m_rDocumentHandler.is()); m_rDocumentHandler->startElement(str, attriblist); } void XFlatXml::endElement(const OUString& str) throw (SAXException, RuntimeException) { OSL_ASSERT(m_rDocumentHandler.is()); m_rDocumentHandler->endElement(str); } void XFlatXml::characters(const OUString& str) throw (SAXException, RuntimeException) { OSL_ASSERT(m_rDocumentHandler.is()); m_rDocumentHandler->characters(str); } void XFlatXml::ignorableWhitespace(const OUString& str) throw (SAXException, RuntimeException) { OSL_ASSERT(m_rDocumentHandler.is()); if (!m_bPrettyPrint) return; m_rDocumentHandler->ignorableWhitespace(str); } void XFlatXml::processingInstruction(const OUString& str, const OUString& str2) throw (SAXException, RuntimeException) { OSL_ASSERT(m_rDocumentHandler.is()); m_rDocumentHandler->processingInstruction(str, str2); } void XFlatXml::setDocumentLocator(const Reference& doclocator) throw (SAXException, RuntimeException) { OSL_ASSERT(m_rDocumentHandler.is()); m_rDocumentHandler->setDocumentLocator(doclocator); } // -------------------------------------- // Component management // -------------------------------------- Reference< XInterface > SAL_CALL CreateInstance( const Reference< XMultiServiceFactory > &r) { return Reference< XInterface >(( OWeakObject *)new XFlatXml(r)); } Sequence< OUString > getSupportedServiceNames() { static Sequence < OUString > *pNames = 0; if( ! pNames ) { MutexGuard guard( Mutex::getGlobalMutex() ); if( !pNames ) { static Sequence< OUString > seqNames(1); seqNames.getArray()[0] = OUString::createFromAscii( "devguide.officedev.samples.filter.FlatXmlCpp"); pNames = &seqNames; } } return *pNames; } } using namespace XFlatXml; #define IMPLEMENTATION_NAME "devguide.officedev.samples.filter.FlatXmlCpp" extern "C" { SAL_DLLPUBLIC_EXPORT void SAL_CALL component_getImplementationEnvironment( const sal_Char ** ppEnvTypeName, uno_Environment ** ppEnv ) { *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; } // This method not longer necessary since OOo 3.4 where the component registration was // was changed to passive component registration. For more details see // http://wiki.services.openoffice.org/wiki/Passive_Component_Registration // // SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL component_writeInfo(void * pServiceManager, void * pRegistryKey ) // { // if (pRegistryKey) // { // try // { // Reference< XRegistryKey > xNewKey( // reinterpret_cast< XRegistryKey * >( pRegistryKey )->createKey( // OUString::createFromAscii( "/" IMPLEMENTATION_NAME "/UNO/SERVICES" ) ) ); // const Sequence< OUString > & rSNL = getSupportedServiceNames(); // const OUString * pArray = rSNL.getConstArray(); // for ( sal_Int32 nPos = rSNL.getLength(); nPos--; ) // xNewKey->createKey( pArray[nPos] ); // return sal_True; // } // catch (InvalidRegistryException &) // { // OSL_ENSURE( sal_False, "### InvalidRegistryException!" ); // } // } // return sal_False; // } SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory( const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey ) { void * pRet = 0; if (pServiceManager && rtl_str_compare( pImplName, IMPLEMENTATION_NAME ) == 0) { Reference< XSingleServiceFactory > xFactory( createSingleFactory( reinterpret_cast< XMultiServiceFactory * >( pServiceManager ), OUString::createFromAscii( pImplName ), CreateInstance, getSupportedServiceNames() ) ); if (xFactory.is()) { xFactory->acquire(); pRet = xFactory.get(); } } return pRet; } } // extern "C"