diff options
author | Jens-Heiner Rechtien <hr@openoffice.org> | 2004-03-09 09:05:18 +0000 |
---|---|---|
committer | Jens-Heiner Rechtien <hr@openoffice.org> | 2004-03-09 09:05:18 +0000 |
commit | b96709f55195c560d14747f2c4f743a9617dc8fc (patch) | |
tree | 98f19af6ab034bf67d8fc68fec17931a57509adb /filter/source/xsltfilter | |
parent | 7a3ebb2392378b4a99c031825fcebd5b2a4a4939 (diff) |
INTEGRATION: CWS fwkmerge1 (1.1.8); FILE ADDED
2004/02/03 16:46:06 lo 1.1.8.1: #115238# merge up for #113029
Diffstat (limited to 'filter/source/xsltfilter')
-rw-r--r-- | filter/source/xsltfilter/XSLTFilter.cxx | 502 |
1 files changed, 502 insertions, 0 deletions
diff --git a/filter/source/xsltfilter/XSLTFilter.cxx b/filter/source/xsltfilter/XSLTFilter.cxx new file mode 100644 index 000000000000..5ad77385d593 --- /dev/null +++ b/filter/source/xsltfilter/XSLTFilter.cxx @@ -0,0 +1,502 @@ +#include <stdio.h> + +#include <cppuhelper/factory.hxx> +#include <cppuhelper/servicefactory.hxx> +#include <cppuhelper/implbase1.hxx> +#include <cppuhelper/implbase2.hxx> +#include <cppuhelper/implbase3.hxx> +#include <cppuhelper/implbase4.hxx> +#include <cppuhelper/implbase.hxx> + +#include <osl/time.h> +#include <osl/conditn.h> +#include <tools/urlobj.hxx> +#include <osl/module.h> +#include <osl/file.hxx> +#include <osl/process.h> + +#include <com/sun/star/lang/XComponent.hpp> + +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Type.hxx> + +#include <com/sun/star/beans/PropertyValue.hpp> + +#include <com/sun/star/xml/sax/XParser.hpp> +#include <com/sun/star/xml/sax/InputSource.hpp> +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> +#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp> +#include <com/sun/star/xml/sax/SAXException.hpp> +#include <com/sun/star/xml/XImportFilter.hpp> +#include <com/sun/star/xml/XExportFilter.hpp> + +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/io/XActiveDataSource.hpp> +#include <com/sun/star/io/XActiveDataSink.hpp> +#include <com/sun/star/io/XActiveDataControl.hpp> +#include <com/sun/star/io/XStreamListener.hpp> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/lang/EventObject.hpp> +#include <com/sun/star/util/XStringSubstitution.hpp> + +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; +using namespace ::com::sun::star::util; + +namespace XSLT { + +class XSLTFilter : public WeakImplHelper4< XImportFilter, XExportFilter, XDocumentHandler, XStreamListener> +{ +private: + // the UNO ServiceFactory + Reference< XMultiServiceFactory > m_rServiceFactory; + + // DocumentHandler interface of the css::xml::sax::Writer service + Reference < XExtendedDocumentHandler > m_rDocumentHandler; + Reference < XOutputStream > m_rOutputStream; + + // controls pretty-printing + sal_Bool m_bPrettyPrint; + + Reference< XActiveDataControl > m_tcontrol; + oslCondition m_cTransformed; + sal_Bool m_bError; + sal_Bool m_bTerminated; + OUString rel2abs(const OUString&); +public: + + // ctor... + XSLTFilter( const Reference< XMultiServiceFactory > &r ); + + // XStreamListener + virtual void SAL_CALL error(const Any& a) throw (RuntimeException); + virtual void SAL_CALL closed() throw (RuntimeException); + virtual void SAL_CALL terminated() throw (RuntimeException); + virtual void SAL_CALL started() throw (RuntimeException); + virtual void SAL_CALL disposing(const EventObject& e) throw (RuntimeException); + + + // XImportFilter + virtual sal_Bool SAL_CALL importer( + const Sequence<PropertyValue>& aSourceData, + const Reference<XDocumentHandler>& xHandler, + const Sequence<OUString>& msUserData) + throw(RuntimeException); + + // XExportFilter + virtual sal_Bool SAL_CALL exporter( + const Sequence<PropertyValue>& aSourceData, + const Sequence<OUString>& 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<XAttributeList>& 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<XLocator>& doclocator) + throw (SAXException,RuntimeException); +}; + +XSLTFilter::XSLTFilter( const Reference< XMultiServiceFactory > &r ) + : m_rServiceFactory(r) + , m_bPrettyPrint(sal_True) + , m_bTerminated(sal_False) + , m_bError(sal_False) +{ + m_cTransformed = osl_createCondition(); +} + +void XSLTFilter::disposing(const EventObject& e) throw (RuntimeException) +{ +} +void XSLTFilter::started() throw (RuntimeException) +{ + osl_resetCondition(m_cTransformed); +} +void XSLTFilter::error(const Any& a) throw (RuntimeException) +{ + m_bError = sal_True; + osl_setCondition(m_cTransformed); +} +void XSLTFilter::closed() throw (RuntimeException) +{ + osl_setCondition(m_cTransformed); +} +void XSLTFilter::terminated() throw (RuntimeException) +{ + m_bTerminated = sal_True; + osl_setCondition(m_cTransformed); +} + +OUString XSLTFilter::rel2abs(const OUString& s) +{ + + Reference< XStringSubstitution > subs(m_rServiceFactory->createInstance( + OUString::createFromAscii("com.sun.star.util.PathSubstitution")), UNO_QUERY); + OUString aWorkingDir = subs->getSubstituteVariableValue(OUString::createFromAscii("$(progurl)")); + INetURLObject aObj( aWorkingDir ); + aObj.setFinalSlash(); + bool bWasAbsolute; + INetURLObject aURL = aObj.smartRel2Abs( + s, bWasAbsolute, false, INetURLObject::WAS_ENCODED, RTL_TEXTENCODING_UTF8, true ); + return aURL.GetMainURL(INetURLObject::NO_DECODE); +} + + + +sal_Bool XSLTFilter::importer( + const Sequence<PropertyValue>& aSourceData, + const Reference<XDocumentHandler>& xHandler, + const Sequence<OUString>& msUserData) + throw (RuntimeException) +{ + + + OUString udImport = msUserData[2]; + OUString udStyleSheet = rel2abs(msUserData[4]); + + // get information from media descriptor + // the imput 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; + } + OSL_ASSERT(xInputStream.is()); + if (!xInputStream.is()) return sal_False; + + // 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; + + // create transformer + Sequence< Any > args(1); + args[0] <<= udStyleSheet; + m_tcontrol = Reference< XActiveDataControl >(m_rServiceFactory->createInstanceWithArguments( + OUString::createFromAscii("com.sun.star.comp.JAXTHelper"), args), UNO_QUERY); + m_tcontrol->addListener(Reference< XStreamListener >(this)); + + OSL_ASSERT(xHandler.is()); + OSL_ASSERT(xInputStream.is()); + OSL_ASSERT(m_tcontrol.is()); + if (xHandler.is() && xInputStream.is() && m_tcontrol.is()) + { + try + { + // connect input to transformer + Reference< XActiveDataSink > tsink(m_tcontrol, UNO_QUERY); + tsink->setInputStream(xInputStream); + + // create pipe + Reference< XOutputStream > pipeout(m_rServiceFactory->createInstance( + OUString::createFromAscii("com.sun.star.io.Pipe")), UNO_QUERY); + Reference< XInputStream > pipein(pipeout, UNO_QUERY); + + //connect transformer to pipe + Reference< XActiveDataSource > tsource(m_tcontrol, UNO_QUERY); + tsource->setOutputStream(pipeout); + + // connect pipe to sax parser + InputSource aInput; + aInput.sSystemId = aURL; + aInput.sPublicId = aURL; + aInput.aInputStream = pipein; + + // set doc handler + xSaxParser->setDocumentHandler(xHandler); + + // transform + m_tcontrol->start(); + osl_waitCondition(m_cTransformed, 0); + if (!m_bError && !m_bTerminated) + { + // parse the transformed XML buffered in the pipe + xSaxParser->parseStream(aInput); + return sal_True; + } else { + return sal_False; + } + } + catch( Exception &exc) + { + // something went wrong + OSL_ENSURE(0, OUStringToOString(exc.Message, RTL_TEXTENCODING_ASCII_US).getStr()); + return sal_False; + } + } else + { + return sal_False; + } +} + +sal_Bool XSLTFilter::exporter( + const Sequence<PropertyValue>& aSourceData, + const Sequence<OUString>& msUserData) + throw (RuntimeException) +{ + + // get interesting values from user data + OUString udImport = msUserData[2]; + OUString udStyleSheet = rel2abs(msUserData[5]); + + + + // read source data + // we are especialy interested in the output stream + // since that is where our xml-writer will push the data + // from it's data-source interface + OUString aName, sURL; + sal_Bool bIndent = sal_False; + OUString aDoctypePublic; + OUString aDoctypeSystem; + // Reference<XOutputStream> rOutputStream; + sal_Int32 nLength = aSourceData.getLength(); + for ( sal_Int32 i = 0 ; i < nLength; i++) + { + aName = aSourceData[i].Name; + if ( aName.equalsAscii("Indent")) + aSourceData[i].Value >>= bIndent; + if ( aName.equalsAscii("DocType_Public")) + aSourceData[i].Value >>= aDoctypePublic; + if ( aName.equalsAscii("DocType_System")) + aSourceData[i].Value >>= aDoctypeSystem; + if ( aName.equalsAscii("OutputStream")) + aSourceData[i].Value >>= m_rOutputStream; + else if ( aName.equalsAscii("URL" )) + aSourceData[i].Value >>= sURL; + } + + if (!m_rDocumentHandler.is()) { + // get the document writer + m_rDocumentHandler = Reference<XExtendedDocumentHandler>( + m_rServiceFactory->createInstance( + OUString::createFromAscii("com.sun.star.xml.sax.Writer")), + UNO_QUERY); + } + + // create transformer + Sequence< Any > args(3); + args[0] <<= udStyleSheet; + args[1] <<= aDoctypeSystem; + args[2] <<= aDoctypePublic; + m_tcontrol = Reference< XActiveDataControl >(m_rServiceFactory->createInstanceWithArguments( + OUString::createFromAscii("com.sun.star.comp.JAXTHelper"), args), UNO_QUERY); + m_tcontrol->addListener(Reference< XStreamListener >(this)); + + OSL_ASSERT(m_rDocumentHandler.is()); + OSL_ASSERT(m_rOutputStream.is()); + OSL_ASSERT(m_tcontrol.is()); + if (m_tcontrol.is() && m_rOutputStream.is() && m_rDocumentHandler.is()) + { + // create pipe + Reference< XOutputStream > pipeout(m_rServiceFactory->createInstance( + OUString::createFromAscii("com.sun.star.io.Pipe")), UNO_QUERY); + Reference< XInputStream > pipein(pipeout, UNO_QUERY); + + // connect sax writer to pipe + Reference< XActiveDataSource > xmlsource(m_rDocumentHandler, UNO_QUERY); + xmlsource->setOutputStream(pipeout); + + // connect pipe to transformer + Reference< XActiveDataSink > tsink(m_tcontrol, UNO_QUERY); + tsink->setInputStream(pipein); + + // connect transformer to output + Reference< XActiveDataSource > tsource(m_tcontrol, UNO_QUERY); + tsource->setOutputStream(m_rOutputStream); + + // don't start transformer yet but wait for buffer to be filled + //m_tcontrol->start(); + + return sal_True; + } + else + { + return sal_False; + } +} + +// 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 XSLTFilter::startDocument() throw (SAXException,RuntimeException){ + OSL_ASSERT(m_rDocumentHandler.is()); + m_rDocumentHandler->startDocument(); +} + +void XSLTFilter::endDocument() throw (SAXException,RuntimeException){ + OSL_ASSERT(m_rDocumentHandler.is()); + m_rDocumentHandler->endDocument(); + m_tcontrol->start(); + osl_waitCondition(m_cTransformed, 0); + if (!m_bError && !m_bTerminated) + { + return; + } else { + throw RuntimeException(); + } + +} + +void XSLTFilter::startElement(const OUString& str, const Reference<XAttributeList>& attriblist) + throw (SAXException, RuntimeException) +{ + OSL_ASSERT(m_rDocumentHandler.is()); + m_rDocumentHandler->startElement(str, attriblist); +} + +void XSLTFilter::endElement(const OUString& str) + throw (SAXException, RuntimeException) +{ + OSL_ASSERT(m_rDocumentHandler.is()); + m_rDocumentHandler->endElement(str); +} + +void XSLTFilter::characters(const OUString& str) + throw (SAXException, RuntimeException) +{ + OSL_ASSERT(m_rDocumentHandler.is()); + m_rDocumentHandler->characters(str); +} + +void XSLTFilter::ignorableWhitespace(const OUString& str) + throw (SAXException, RuntimeException) +{ + OSL_ASSERT(m_rDocumentHandler.is()); + if (!m_bPrettyPrint) return; + m_rDocumentHandler->ignorableWhitespace(str); +} + +void XSLTFilter::processingInstruction(const OUString& str, const OUString& str2) + throw (SAXException, RuntimeException) +{ + OSL_ASSERT(m_rDocumentHandler.is()); + m_rDocumentHandler->processingInstruction(str, str2); +} + +void XSLTFilter::setDocumentLocator(const Reference<XLocator>& doclocator) + throw (SAXException, RuntimeException) +{ + OSL_ASSERT(m_rDocumentHandler.is()); + m_rDocumentHandler->setDocumentLocator(doclocator); +} + +// -------------------------------------- +// Component management +// -------------------------------------- +#define SERVICE_NAME "com.sun.star.documentconversion.XSLTFilter" +#define IMPLEMENTATION_NAME "com.sun.star.comp.documentconversion.XSLTFilter" + +static Reference< XInterface > SAL_CALL CreateInstance( const Reference< XMultiServiceFactory > &r) +{ + return Reference< XInterface >(( OWeakObject *)new XSLTFilter(r)); +} + +static 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(SERVICE_NAME); + pNames = &seqNames; + } + } + return *pNames; +} + +} + +using namespace XSLT; + +extern "C" +{ +void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** ppEnv ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +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; +} + +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" |