blob: 62164ffc80a86e1493e5c94dab5ad104e433a834 [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.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_framework.hxx"
#include <framework/fwedllapi.h>
#include <stdio.h>
//_________________________________________________________________________________________________________________
// my own includes
//_________________________________________________________________________________________________________________
#include <threadhelp/resetableguard.hxx>
#include <xml/eventsdocumenthandler.hxx>
#include <macros/debug.hxx>
//_________________________________________________________________________________________________________________
// interface includes
//_________________________________________________________________________________________________________________
#ifndef __COM_SUN_STAR_XML_SAX_XEXTENDEDDOCUMENTHANDLER_HPP_
#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp>
#endif
//_________________________________________________________________________________________________________________
// other includes
//_________________________________________________________________________________________________________________
#include <sal/config.h>
#include <vcl/svapp.hxx>
#include <vcl/toolbox.hxx>
#include <comphelper/attributelist.hxx>
//_________________________________________________________________________________________________________________
// namespace
//_________________________________________________________________________________________________________________
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::xml::sax;
#define XMLNS_EVENT "http://openoffice.org/2001/event"
#define XMLNS_XLINK "http://www.w3.org/1999/xlink"
#define XMLNS_EVENT_PREFIX "event:"
#define XMLNS_XLINK_PREFIX "xlink:"
#define ATTRIBUTE_XMLNS_EVENT "xmlns:event"
#define ATTRIBUTE_XMLNS_XLINK "xmlns:xlink"
#define XMLNS_FILTER_SEPARATOR "^"
#define ELEMENT_EVENTS "events"
#define ELEMENT_EVENT "event"
#define ATTRIBUTE_LANGUAGE "language"
#define ATTRIBUTE_LIBRARY "library"
#define ATTRIBUTE_NAME "name"
#define ATTRIBUTE_HREF "href"
#define ATTRIBUTE_TYPE "type"
#define ATTRIBUTE_MACRONAME "macro-name"
#define ELEMENT_NS_EVENTS "event:events"
#define ELEMENT_NS_EVENT "event:event"
#define ATTRIBUTE_TYPE_CDATA "CDATA"
#define EVENTS_DOCTYPE "<!DOCTYPE event:events PUBLIC \"-//OpenOffice.org//DTD OfficeDocument 1.0//EN\" \"event.dtd\">"
// Property names for events
#define PROP_EVENT_TYPE "EventType"
#define PROP_LIBRARY "Library"
#define PROP_SCRIPT "Script"
#define PROP_MACRO_NAME "MacroName"
#define STAR_BASIC "StarBasic"
#define JAVA_SCRIPT "JavaScript"
namespace framework
{
struct EventEntryProperty
{
OReadEventsDocumentHandler::Event_XML_Namespace nNamespace;
char aEntryName[20];
};
static EventEntryProperty EventEntries[OReadEventsDocumentHandler::EV_XML_ENTRY_COUNT] =
{
{ OReadEventsDocumentHandler::EV_NS_EVENT, ELEMENT_EVENTS },
{ OReadEventsDocumentHandler::EV_NS_EVENT, ELEMENT_EVENT },
{ OReadEventsDocumentHandler::EV_NS_EVENT, ATTRIBUTE_LANGUAGE },
{ OReadEventsDocumentHandler::EV_NS_EVENT, ATTRIBUTE_NAME },
{ OReadEventsDocumentHandler::EV_NS_XLINK, ATTRIBUTE_HREF },
{ OReadEventsDocumentHandler::EV_NS_XLINK, ATTRIBUTE_TYPE },
{ OReadEventsDocumentHandler::EV_NS_EVENT, ATTRIBUTE_MACRONAME },
{ OReadEventsDocumentHandler::EV_NS_EVENT, ATTRIBUTE_LIBRARY }
};
OReadEventsDocumentHandler::OReadEventsDocumentHandler( EventsConfig& aItems ) :
ThreadHelpBase( &Application::GetSolarMutex() ),
m_aEventItems( aItems )
{
::rtl::OUString aNamespaceEvent( RTL_CONSTASCII_USTRINGPARAM( XMLNS_EVENT ));
::rtl::OUString aNamespaceXLink( RTL_CONSTASCII_USTRINGPARAM( XMLNS_XLINK ));
::rtl::OUString aSeparator( RTL_CONSTASCII_USTRINGPARAM( XMLNS_FILTER_SEPARATOR ));
// create hash map
for ( int i = 0; i < (int)EV_XML_ENTRY_COUNT; i++ )
{
if ( EventEntries[i].nNamespace == EV_NS_EVENT )
{
::rtl::OUString temp( aNamespaceEvent );
temp += aSeparator;
temp += ::rtl::OUString::createFromAscii( EventEntries[i].aEntryName );
m_aEventsMap.insert( EventsHashMap::value_type( temp, (Events_XML_Entry)i ) );
}
else
{
::rtl::OUString temp( aNamespaceXLink );
temp += aSeparator;
temp += ::rtl::OUString::createFromAscii( EventEntries[i].aEntryName );
m_aEventsMap.insert( EventsHashMap::value_type( temp, (Events_XML_Entry)i ) );
}
}
m_bEventsStartFound = sal_False;
m_bEventsEndFound = sal_False;
m_bEventStartFound = sal_False;
}
OReadEventsDocumentHandler::~OReadEventsDocumentHandler()
{
}
// XDocumentHandler
void SAL_CALL OReadEventsDocumentHandler::startDocument(void)
throw ( SAXException, RuntimeException )
{
}
void SAL_CALL OReadEventsDocumentHandler::endDocument(void)
throw( SAXException, RuntimeException )
{
ResetableGuard aGuard( m_aLock );
if (( m_bEventsStartFound && !m_bEventsEndFound ) ||
( !m_bEventsStartFound && m_bEventsEndFound ) )
{
::rtl::OUString aErrorMessage = getErrorLineString();
aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "No matching start or end element 'event:events' found!" ));
throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
}
}
void SAL_CALL OReadEventsDocumentHandler::startElement(
const ::rtl::OUString& aName, const Reference< XAttributeList > &xAttribs )
throw( SAXException, RuntimeException )
{
ResetableGuard aGuard( m_aLock );
EventsHashMap::const_iterator pEventEntry = m_aEventsMap.find( aName );
if ( pEventEntry != m_aEventsMap.end() )
{
switch ( pEventEntry->second )
{
case EV_ELEMENT_EVENTS:
{
if ( m_bEventsStartFound )
{
::rtl::OUString aErrorMessage = getErrorLineString();
aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Element 'event:events' cannot be embeded into 'event:events'!" ));
throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
}
m_bEventsStartFound = sal_True;
}
break;
case EV_ELEMENT_EVENT:
{
if ( !m_bEventsStartFound )
{
::rtl::OUString aErrorMessage = getErrorLineString();
aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Element 'event:event' must be embeded into element 'event:events'!" ));
throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
}
if ( m_bEventStartFound )
{
::rtl::OUString aErrorMessage = getErrorLineString();
aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Element event:event is not a container!" ));
throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
}
::rtl::OUString aLanguage;
::rtl::OUString aURL;
::rtl::OUString aMacroName;
::rtl::OUString aLibrary;
::rtl::OUString aEventName;
m_bEventStartFound = sal_True;
long nIndex = m_aEventItems.aEventNames.getLength();
long nPropCount = 2; // every event config entry needs at least 2 properties
Sequence< PropertyValue > aEventProperties( nPropCount );
m_aEventItems.aEventNames.realloc( nIndex + 1 );
for ( sal_Int16 n = 0; n < xAttribs->getLength(); n++ )
{
pEventEntry = m_aEventsMap.find( xAttribs->getNameByIndex( n ) );
if ( pEventEntry != m_aEventsMap.end() )
{
switch ( pEventEntry->second )
{
case EV_ATTRIBUTE_TYPE:
{
aLanguage = xAttribs->getValueByIndex( n );
}
break;
case EV_ATTRIBUTE_NAME:
{
aEventName = xAttribs->getValueByIndex( n );
}
break;
case XL_ATTRIBUTE_HREF:
{
aURL = xAttribs->getValueByIndex( n );
}
break;
case EV_ATTRIBUTE_MACRONAME:
{
aMacroName = xAttribs->getValueByIndex( n );
}
break;
case EV_ATTRIBUTE_LIBRARY:
{
aLibrary = xAttribs->getValueByIndex( n );
}
break;
default:
break; // nothing to do
}
}
} // for
::rtl::OUString aRequiredAttributeName;
if ( aLanguage.getLength() == 0 )
aRequiredAttributeName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_TYPE ));
else if ( aEventName.getLength() == 0 )
aRequiredAttributeName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_NAME ));
// check for missing attribute values
if ( aRequiredAttributeName.getLength() > 0 )
{
::rtl::OUString aErrorMessage = getErrorLineString();
aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Required attribute "));
aErrorMessage += aRequiredAttributeName;
aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " must have a value!" ));
throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
}
Any a;
// set properties
a <<= aLanguage;
aEventProperties[0].Value <<= a;
aEventProperties[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( PROP_EVENT_TYPE ));
a <<= aMacroName;
aEventProperties[1].Value <<= a;
aEventProperties[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( PROP_MACRO_NAME ));
if ( aLibrary.getLength() > 0 )
{
++nPropCount;
aEventProperties.realloc( nPropCount );
a <<= aLibrary;
aEventProperties[nPropCount-1].Value <<= a;
aEventProperties[nPropCount-1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( PROP_LIBRARY ));
}
if ( aURL.getLength() > 0 )
{
++nPropCount;
aEventProperties.realloc( nPropCount );
a <<= aURL;
aEventProperties[nPropCount-1].Value <<= a;
aEventProperties[nPropCount-1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( PROP_SCRIPT ));
}
// set event name
m_aEventItems.aEventNames[ nIndex ] = aEventName;
m_aEventItems.aEventsProperties.realloc( nIndex + 1 );
a <<= aEventProperties;
m_aEventItems.aEventsProperties[ nIndex ] = a;
}
break;
default:
break;
}
}
}
void SAL_CALL OReadEventsDocumentHandler::endElement(const ::rtl::OUString& aName)
throw( SAXException, RuntimeException )
{
ResetableGuard aGuard( m_aLock );
EventsHashMap::const_iterator pEventEntry = m_aEventsMap.find( aName );
if ( pEventEntry != m_aEventsMap.end() )
{
switch ( pEventEntry->second )
{
case EV_ELEMENT_EVENTS:
{
if ( !m_bEventsStartFound )
{
::rtl::OUString aErrorMessage = getErrorLineString();
aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "End element 'event:events' found, but no start element" ));
throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
}
m_bEventsStartFound = sal_False;
}
break;
case EV_ELEMENT_EVENT:
{
if ( !m_bEventStartFound )
{
::rtl::OUString aErrorMessage = getErrorLineString();
aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "End element 'event:event' found, but no start element" ));
throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
}
m_bEventStartFound = sal_False;
}
break;
default:
break; // impossible case
}
}
}
void SAL_CALL OReadEventsDocumentHandler::characters(const ::rtl::OUString&)
throw( SAXException, RuntimeException )
{
}
void SAL_CALL OReadEventsDocumentHandler::ignorableWhitespace(const ::rtl::OUString&)
throw( SAXException, RuntimeException )
{
}
void SAL_CALL OReadEventsDocumentHandler::processingInstruction(
const ::rtl::OUString& /*aTarget*/, const ::rtl::OUString& /*aData*/ )
throw( SAXException, RuntimeException )
{
}
void SAL_CALL OReadEventsDocumentHandler::setDocumentLocator(
const Reference< XLocator > &xLocator)
throw( SAXException, RuntimeException )
{
ResetableGuard aGuard( m_aLock );
m_xLocator = xLocator;
}
::rtl::OUString OReadEventsDocumentHandler::getErrorLineString()
{
ResetableGuard aGuard( m_aLock );
char buffer[32];
if ( m_xLocator.is() )
{
snprintf( buffer, sizeof(buffer), "Line: %ld - ", static_cast<long>(m_xLocator->getLineNumber() ));
return ::rtl::OUString::createFromAscii( buffer );
}
else
return ::rtl::OUString();
}
//_________________________________________________________________________________________________________________
// OWriteEventsDocumentHandler
//_________________________________________________________________________________________________________________
OWriteEventsDocumentHandler::OWriteEventsDocumentHandler(
const EventsConfig& aItems,
Reference< XDocumentHandler > rWriteDocumentHandler ) :
ThreadHelpBase( &Application::GetSolarMutex() ),
m_aItems( aItems ),
m_xWriteDocumentHandler( rWriteDocumentHandler )
{
::comphelper::AttributeList* pList = new ::comphelper::AttributeList;
m_xEmptyList = Reference< XAttributeList >( (XAttributeList *) pList, UNO_QUERY );
m_aAttributeType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_TYPE_CDATA ));
m_aXMLXlinkNS = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( XMLNS_XLINK_PREFIX ));
m_aXMLEventNS = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( XMLNS_EVENT_PREFIX ));
}
OWriteEventsDocumentHandler::~OWriteEventsDocumentHandler()
{
}
void OWriteEventsDocumentHandler::WriteEventsDocument() throw
( SAXException, RuntimeException )
{
ResetableGuard aGuard( m_aLock );
m_xWriteDocumentHandler->startDocument();
// write DOCTYPE line!
Reference< XExtendedDocumentHandler > xExtendedDocHandler( m_xWriteDocumentHandler, UNO_QUERY );
if ( xExtendedDocHandler.is() )
{
xExtendedDocHandler->unknown( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( EVENTS_DOCTYPE )) );
m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() );
}
::comphelper::AttributeList* pList = new ::comphelper::AttributeList;
Reference< XAttributeList > xList( (XAttributeList *) pList , UNO_QUERY );
pList->AddAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_XMLNS_EVENT )),
m_aAttributeType,
::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( XMLNS_EVENT )) );
pList->AddAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_XMLNS_XLINK )),
m_aAttributeType,
::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( XMLNS_XLINK )) );
m_xWriteDocumentHandler->startElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_EVENTS )), pList );
m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() );
Sequence< PropertyValue > aEventProperties;
for ( int i = 0; i < m_aItems.aEventNames.getLength(); i++ )
{
if ( m_aItems.aEventsProperties[i] >>= aEventProperties )
WriteEvent( m_aItems.aEventNames[i], aEventProperties );
}
m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() );
m_xWriteDocumentHandler->endElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_EVENTS )) );
m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() );
m_xWriteDocumentHandler->endDocument();
}
//_________________________________________________________________________________________________________________
// protected member functions
//_________________________________________________________________________________________________________________
void OWriteEventsDocumentHandler::WriteEvent( const ::rtl::OUString& aEventName, const Sequence< PropertyValue >& aPropertyValues ) throw
( SAXException, RuntimeException )
{
if ( aPropertyValues.getLength() > 0 )
{
::comphelper::AttributeList* pList = new ::comphelper::AttributeList;
Reference< XAttributeList > xList( (XAttributeList *) pList , UNO_QUERY );
if ( m_aAttributeURL.getLength() == 0 )
{
m_aAttributeURL = m_aXMLXlinkNS;
m_aAttributeURL += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_HREF ));
m_aAttributeLinkType = m_aXMLXlinkNS;
m_aAttributeLinkType += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_TYPE ));
m_aAttributeLanguage = m_aXMLEventNS;
m_aAttributeLanguage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_LANGUAGE ));
m_aAttributeMacroName = m_aXMLEventNS;
m_aAttributeMacroName += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_MACRONAME ));
m_aAttributeLibrary = m_aXMLEventNS;
m_aAttributeLibrary += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_LIBRARY ));
m_aAttributeName = m_aXMLEventNS;
m_aAttributeName += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_NAME ));
}
pList->AddAttribute( m_aAttributeName, m_aAttributeType, aEventName );
sal_Bool bURLSet = sal_False;
::rtl::OUString aValue;
::rtl::OUString aName;
// save attributes
for ( int i = 0; i < aPropertyValues.getLength(); i++ )
{
aPropertyValues[i].Value >>= aValue;
if ( aPropertyValues[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( PROP_EVENT_TYPE )))
pList->AddAttribute( m_aAttributeLanguage, m_aAttributeType, aValue );
else if ( aPropertyValues[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( PROP_MACRO_NAME )) &&
aValue.getLength() > 0 )
pList->AddAttribute( m_aAttributeMacroName, m_aAttributeType, aValue );
else if ( aPropertyValues[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( PROP_LIBRARY )) &&
aValue.getLength() > 0 )
pList->AddAttribute( m_aAttributeLibrary, m_aAttributeType, aValue );
else if ( aPropertyValues[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( PROP_SCRIPT )))
{
pList->AddAttribute( m_aAttributeURL, m_aAttributeType, aValue );
bURLSet = sal_True;
}
}
if ( bURLSet )
pList->AddAttribute( m_aAttributeLinkType, m_aAttributeType, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "simple" )) );
m_xWriteDocumentHandler->startElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_EVENT )), xList );
m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() );
m_xWriteDocumentHandler->endElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_EVENT )) );
m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() );
}
}
} // namespace framework