blob: 34c4dd53d3954a67ef0f0ee6ff4b5db0d1b91105 [file] [log] [blame]
/**************************************************************
*
* 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 <cppuhelper/factory.hxx>
#include <cppuhelper/servicefactory.hxx>
#include <cppuhelper/implbase1.hxx>
#include <cppuhelper/implbase2.hxx>
#include <cppuhelper/implbase3.hxx>
#include <cppuhelper/implbase.hxx>
#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/XSeekable.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;
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<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);
};
sal_Bool XFlatXml::importer(
const Sequence<PropertyValue>& aSourceData,
const Reference<XDocumentHandler>& xHandler,
const Sequence<OUString>& msUserData)
throw (RuntimeException)
{
// 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;
}
// 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<PropertyValue>& aSourceData,
const Sequence<OUString>& msUserData)
throw (RuntimeException)
{
// 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;
Reference<XOutputStream> 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<XExtendedDocumentHandler>(
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<XAttributeList>& 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<XLocator>& 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"