1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: eventsdocumenthandler.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_framework.hxx"
36 //_________________________________________________________________________________________________________________
38 //_________________________________________________________________________________________________________________
40 #include <threadhelp/resetableguard.hxx>
41 #include <xml/eventsdocumenthandler.hxx>
42 #include <macros/debug.hxx>
44 //_________________________________________________________________________________________________________________
46 //_________________________________________________________________________________________________________________
48 #ifndef __COM_SUN_STAR_XML_SAX_XEXTENDEDDOCUMENTHANDLER_HPP_
49 #include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp>
52 //_________________________________________________________________________________________________________________
54 //_________________________________________________________________________________________________________________
56 #include <sal/config.h>
57 #include <vcl/svapp.hxx>
58 #include <vcl/toolbox.hxx>
60 #include <comphelper/attributelist.hxx>
62 //_________________________________________________________________________________________________________________
64 //_________________________________________________________________________________________________________________
66 using namespace ::com::sun::star::uno
;
67 using namespace ::com::sun::star::beans
;
68 using namespace ::com::sun::star::xml::sax
;
71 #define XMLNS_EVENT "http://openoffice.org/2001/event"
72 #define XMLNS_XLINK "http://www.w3.org/1999/xlink"
73 #define XMLNS_EVENT_PREFIX "event:"
74 #define XMLNS_XLINK_PREFIX "xlink:"
76 #define ATTRIBUTE_XMLNS_EVENT "xmlns:event"
77 #define ATTRIBUTE_XMLNS_XLINK "xmlns:xlink"
79 #define XMLNS_FILTER_SEPARATOR "^"
81 #define ELEMENT_EVENTS "events"
82 #define ELEMENT_EVENT "event"
84 #define ATTRIBUTE_LANGUAGE "language"
85 #define ATTRIBUTE_LIBRARY "library"
86 #define ATTRIBUTE_NAME "name"
87 #define ATTRIBUTE_HREF "href"
88 #define ATTRIBUTE_TYPE "type"
89 #define ATTRIBUTE_MACRONAME "macro-name"
91 #define ELEMENT_NS_EVENTS "event:events"
92 #define ELEMENT_NS_EVENT "event:event"
94 #define ATTRIBUTE_TYPE_CDATA "CDATA"
96 #define EVENTS_DOCTYPE "<!DOCTYPE event:events PUBLIC \"-//OpenOffice.org//DTD OfficeDocument 1.0//EN\" \"event.dtd\">"
98 // Property names for events
99 #define PROP_EVENT_TYPE "EventType"
100 #define PROP_LIBRARY "Library"
101 #define PROP_SCRIPT "Script"
102 #define PROP_MACRO_NAME "MacroName"
103 #define STAR_BASIC "StarBasic"
104 #define JAVA_SCRIPT "JavaScript"
110 struct EventEntryProperty
112 OReadEventsDocumentHandler::Event_XML_Namespace nNamespace
;
116 static EventEntryProperty EventEntries
[OReadEventsDocumentHandler::EV_XML_ENTRY_COUNT
] =
118 { OReadEventsDocumentHandler::EV_NS_EVENT
, ELEMENT_EVENTS
},
119 { OReadEventsDocumentHandler::EV_NS_EVENT
, ELEMENT_EVENT
},
120 { OReadEventsDocumentHandler::EV_NS_EVENT
, ATTRIBUTE_LANGUAGE
},
121 { OReadEventsDocumentHandler::EV_NS_EVENT
, ATTRIBUTE_NAME
},
122 { OReadEventsDocumentHandler::EV_NS_XLINK
, ATTRIBUTE_HREF
},
123 { OReadEventsDocumentHandler::EV_NS_XLINK
, ATTRIBUTE_TYPE
},
124 { OReadEventsDocumentHandler::EV_NS_EVENT
, ATTRIBUTE_MACRONAME
},
125 { OReadEventsDocumentHandler::EV_NS_EVENT
, ATTRIBUTE_LIBRARY
}
129 OReadEventsDocumentHandler::OReadEventsDocumentHandler( EventsConfig
& aItems
) :
130 ThreadHelpBase( &Application::GetSolarMutex() ),
131 m_aEventItems( aItems
)
133 ::rtl::OUString
aNamespaceEvent( RTL_CONSTASCII_USTRINGPARAM( XMLNS_EVENT
));
134 ::rtl::OUString
aNamespaceXLink( RTL_CONSTASCII_USTRINGPARAM( XMLNS_XLINK
));
135 ::rtl::OUString
aSeparator( RTL_CONSTASCII_USTRINGPARAM( XMLNS_FILTER_SEPARATOR
));
138 for ( int i
= 0; i
< (int)EV_XML_ENTRY_COUNT
; i
++ )
140 if ( EventEntries
[i
].nNamespace
== EV_NS_EVENT
)
142 ::rtl::OUString
temp( aNamespaceEvent
);
144 temp
+= ::rtl::OUString::createFromAscii( EventEntries
[i
].aEntryName
);
145 m_aEventsMap
.insert( EventsHashMap::value_type( temp
, (Events_XML_Entry
)i
) );
149 ::rtl::OUString
temp( aNamespaceXLink
);
151 temp
+= ::rtl::OUString::createFromAscii( EventEntries
[i
].aEntryName
);
152 m_aEventsMap
.insert( EventsHashMap::value_type( temp
, (Events_XML_Entry
)i
) );
156 m_bEventsStartFound
= sal_False
;
157 m_bEventsEndFound
= sal_False
;
158 m_bEventStartFound
= sal_False
;
161 OReadEventsDocumentHandler::~OReadEventsDocumentHandler()
166 void SAL_CALL
OReadEventsDocumentHandler::startDocument(void)
167 throw ( SAXException
, RuntimeException
)
171 void SAL_CALL
OReadEventsDocumentHandler::endDocument(void)
172 throw( SAXException
, RuntimeException
)
174 ResetableGuard
aGuard( m_aLock
);
176 if (( m_bEventsStartFound
&& !m_bEventsEndFound
) ||
177 ( !m_bEventsStartFound
&& m_bEventsEndFound
) )
179 ::rtl::OUString aErrorMessage
= getErrorLineString();
180 aErrorMessage
+= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "No matching start or end element 'event:events' found!" ));
181 throw SAXException( aErrorMessage
, Reference
< XInterface
>(), Any() );
185 void SAL_CALL
OReadEventsDocumentHandler::startElement(
186 const ::rtl::OUString
& aName
, const Reference
< XAttributeList
> &xAttribs
)
187 throw( SAXException
, RuntimeException
)
189 ResetableGuard
aGuard( m_aLock
);
191 EventsHashMap::const_iterator pEventEntry
= m_aEventsMap
.find( aName
);
192 if ( pEventEntry
!= m_aEventsMap
.end() )
194 switch ( pEventEntry
->second
)
196 case EV_ELEMENT_EVENTS
:
198 if ( m_bEventsStartFound
)
200 ::rtl::OUString aErrorMessage
= getErrorLineString();
201 aErrorMessage
+= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Element 'event:events' cannot be embeded into 'event:events'!" ));
202 throw SAXException( aErrorMessage
, Reference
< XInterface
>(), Any() );
205 m_bEventsStartFound
= sal_True
;
209 case EV_ELEMENT_EVENT
:
211 if ( !m_bEventsStartFound
)
213 ::rtl::OUString aErrorMessage
= getErrorLineString();
214 aErrorMessage
+= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Element 'event:event' must be embeded into element 'event:events'!" ));
215 throw SAXException( aErrorMessage
, Reference
< XInterface
>(), Any() );
218 if ( m_bEventStartFound
)
220 ::rtl::OUString aErrorMessage
= getErrorLineString();
221 aErrorMessage
+= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Element event:event is not a container!" ));
222 throw SAXException( aErrorMessage
, Reference
< XInterface
>(), Any() );
225 ::rtl::OUString aLanguage
;
226 ::rtl::OUString aURL
;
227 ::rtl::OUString aMacroName
;
228 ::rtl::OUString aLibrary
;
229 ::rtl::OUString aEventName
;
231 m_bEventStartFound
= sal_True
;
233 long nIndex
= m_aEventItems
.aEventNames
.getLength();
234 long nPropCount
= 2; // every event config entry needs at least 2 properties
235 Sequence
< PropertyValue
> aEventProperties( nPropCount
);
237 m_aEventItems
.aEventNames
.realloc( nIndex
+ 1 );
239 for ( sal_Int16 n
= 0; n
< xAttribs
->getLength(); n
++ )
241 pEventEntry
= m_aEventsMap
.find( xAttribs
->getNameByIndex( n
) );
242 if ( pEventEntry
!= m_aEventsMap
.end() )
244 switch ( pEventEntry
->second
)
246 case EV_ATTRIBUTE_TYPE
:
248 aLanguage
= xAttribs
->getValueByIndex( n
);
252 case EV_ATTRIBUTE_NAME
:
254 aEventName
= xAttribs
->getValueByIndex( n
);
258 case XL_ATTRIBUTE_HREF
:
260 aURL
= xAttribs
->getValueByIndex( n
);
264 case EV_ATTRIBUTE_MACRONAME
:
266 aMacroName
= xAttribs
->getValueByIndex( n
);
270 case EV_ATTRIBUTE_LIBRARY
:
272 aLibrary
= xAttribs
->getValueByIndex( n
);
277 break; // nothing to do
282 ::rtl::OUString aRequiredAttributeName
;
283 if ( aLanguage
.getLength() == 0 )
284 aRequiredAttributeName
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_TYPE
));
285 else if ( aEventName
.getLength() == 0 )
286 aRequiredAttributeName
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_NAME
));
288 // check for missing attribute values
289 if ( aRequiredAttributeName
.getLength() > 0 )
291 ::rtl::OUString aErrorMessage
= getErrorLineString();
292 aErrorMessage
+= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Required attribute "));
293 aErrorMessage
+= aRequiredAttributeName
;
294 aErrorMessage
+= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " must have a value!" ));
295 throw SAXException( aErrorMessage
, Reference
< XInterface
>(), Any() );
302 aEventProperties
[0].Value
<<= a
;
303 aEventProperties
[0].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( PROP_EVENT_TYPE
));
306 aEventProperties
[1].Value
<<= a
;
307 aEventProperties
[1].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( PROP_MACRO_NAME
));
309 if ( aLibrary
.getLength() > 0 )
312 aEventProperties
.realloc( nPropCount
);
314 aEventProperties
[nPropCount
-1].Value
<<= a
;
315 aEventProperties
[nPropCount
-1].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( PROP_LIBRARY
));
318 if ( aURL
.getLength() > 0 )
321 aEventProperties
.realloc( nPropCount
);
323 aEventProperties
[nPropCount
-1].Value
<<= a
;
324 aEventProperties
[nPropCount
-1].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( PROP_SCRIPT
));
328 m_aEventItems
.aEventNames
[ nIndex
] = aEventName
;
330 m_aEventItems
.aEventsProperties
.realloc( nIndex
+ 1 );
331 a
<<= aEventProperties
;
332 m_aEventItems
.aEventsProperties
[ nIndex
] = a
;
342 void SAL_CALL
OReadEventsDocumentHandler::endElement(const ::rtl::OUString
& aName
)
343 throw( SAXException
, RuntimeException
)
345 ResetableGuard
aGuard( m_aLock
);
347 EventsHashMap::const_iterator pEventEntry
= m_aEventsMap
.find( aName
);
348 if ( pEventEntry
!= m_aEventsMap
.end() )
350 switch ( pEventEntry
->second
)
352 case EV_ELEMENT_EVENTS
:
354 if ( !m_bEventsStartFound
)
356 ::rtl::OUString aErrorMessage
= getErrorLineString();
357 aErrorMessage
+= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "End element 'event:events' found, but no start element" ));
358 throw SAXException( aErrorMessage
, Reference
< XInterface
>(), Any() );
361 m_bEventsStartFound
= sal_False
;
365 case EV_ELEMENT_EVENT
:
367 if ( !m_bEventStartFound
)
369 ::rtl::OUString aErrorMessage
= getErrorLineString();
370 aErrorMessage
+= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "End element 'event:event' found, but no start element" ));
371 throw SAXException( aErrorMessage
, Reference
< XInterface
>(), Any() );
374 m_bEventStartFound
= sal_False
;
379 break; // impossible case
384 void SAL_CALL
OReadEventsDocumentHandler::characters(const ::rtl::OUString
&)
385 throw( SAXException
, RuntimeException
)
389 void SAL_CALL
OReadEventsDocumentHandler::ignorableWhitespace(const ::rtl::OUString
&)
390 throw( SAXException
, RuntimeException
)
394 void SAL_CALL
OReadEventsDocumentHandler::processingInstruction(
395 const ::rtl::OUString
& /*aTarget*/, const ::rtl::OUString
& /*aData*/ )
396 throw( SAXException
, RuntimeException
)
400 void SAL_CALL
OReadEventsDocumentHandler::setDocumentLocator(
401 const Reference
< XLocator
> &xLocator
)
402 throw( SAXException
, RuntimeException
)
404 ResetableGuard
aGuard( m_aLock
);
406 m_xLocator
= xLocator
;
409 ::rtl::OUString
OReadEventsDocumentHandler::getErrorLineString()
411 ResetableGuard
aGuard( m_aLock
);
415 if ( m_xLocator
.is() )
417 snprintf( buffer
, sizeof(buffer
), "Line: %ld - ", static_cast<long>(m_xLocator
->getLineNumber() ));
418 return ::rtl::OUString::createFromAscii( buffer
);
421 return ::rtl::OUString();
425 //_________________________________________________________________________________________________________________
426 // OWriteEventsDocumentHandler
427 //_________________________________________________________________________________________________________________
429 OWriteEventsDocumentHandler::OWriteEventsDocumentHandler(
430 const EventsConfig
& aItems
,
431 Reference
< XDocumentHandler
> rWriteDocumentHandler
) :
432 ThreadHelpBase( &Application::GetSolarMutex() ),
434 m_xWriteDocumentHandler( rWriteDocumentHandler
)
436 ::comphelper::AttributeList
* pList
= new ::comphelper::AttributeList
;
437 m_xEmptyList
= Reference
< XAttributeList
>( (XAttributeList
*) pList
, UNO_QUERY
);
438 m_aAttributeType
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_TYPE_CDATA
));
439 m_aXMLXlinkNS
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( XMLNS_XLINK_PREFIX
));
440 m_aXMLEventNS
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( XMLNS_EVENT_PREFIX
));
443 OWriteEventsDocumentHandler::~OWriteEventsDocumentHandler()
447 void OWriteEventsDocumentHandler::WriteEventsDocument() throw
448 ( SAXException
, RuntimeException
)
450 ResetableGuard
aGuard( m_aLock
);
452 m_xWriteDocumentHandler
->startDocument();
454 // write DOCTYPE line!
455 Reference
< XExtendedDocumentHandler
> xExtendedDocHandler( m_xWriteDocumentHandler
, UNO_QUERY
);
456 if ( xExtendedDocHandler
.is() )
458 xExtendedDocHandler
->unknown( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( EVENTS_DOCTYPE
)) );
459 m_xWriteDocumentHandler
->ignorableWhitespace( ::rtl::OUString() );
462 ::comphelper::AttributeList
* pList
= new ::comphelper::AttributeList
;
463 Reference
< XAttributeList
> xList( (XAttributeList
*) pList
, UNO_QUERY
);
465 pList
->AddAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_XMLNS_EVENT
)),
467 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( XMLNS_EVENT
)) );
468 pList
->AddAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_XMLNS_XLINK
)),
470 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( XMLNS_XLINK
)) );
472 m_xWriteDocumentHandler
->startElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_EVENTS
)), pList
);
473 m_xWriteDocumentHandler
->ignorableWhitespace( ::rtl::OUString() );
475 Sequence
< PropertyValue
> aEventProperties
;
477 for ( int i
= 0; i
< m_aItems
.aEventNames
.getLength(); i
++ )
479 if ( m_aItems
.aEventsProperties
[i
] >>= aEventProperties
)
480 WriteEvent( m_aItems
.aEventNames
[i
], aEventProperties
);
483 m_xWriteDocumentHandler
->ignorableWhitespace( ::rtl::OUString() );
484 m_xWriteDocumentHandler
->endElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_EVENTS
)) );
486 m_xWriteDocumentHandler
->ignorableWhitespace( ::rtl::OUString() );
487 m_xWriteDocumentHandler
->endDocument();
490 //_________________________________________________________________________________________________________________
491 // protected member functions
492 //_________________________________________________________________________________________________________________
494 void OWriteEventsDocumentHandler::WriteEvent( const ::rtl::OUString
& aEventName
, const Sequence
< PropertyValue
>& aPropertyValues
) throw
495 ( SAXException
, RuntimeException
)
497 if ( aPropertyValues
.getLength() > 0 )
499 ::comphelper::AttributeList
* pList
= new ::comphelper::AttributeList
;
500 Reference
< XAttributeList
> xList( (XAttributeList
*) pList
, UNO_QUERY
);
502 if ( m_aAttributeURL
.getLength() == 0 )
504 m_aAttributeURL
= m_aXMLXlinkNS
;
505 m_aAttributeURL
+= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_HREF
));
506 m_aAttributeLinkType
= m_aXMLXlinkNS
;
507 m_aAttributeLinkType
+= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_TYPE
));
508 m_aAttributeLanguage
= m_aXMLEventNS
;
509 m_aAttributeLanguage
+= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_LANGUAGE
));
510 m_aAttributeMacroName
= m_aXMLEventNS
;
511 m_aAttributeMacroName
+= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_MACRONAME
));
512 m_aAttributeLibrary
= m_aXMLEventNS
;
513 m_aAttributeLibrary
+= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_LIBRARY
));
514 m_aAttributeName
= m_aXMLEventNS
;
515 m_aAttributeName
+= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_NAME
));
518 pList
->AddAttribute( m_aAttributeName
, m_aAttributeType
, aEventName
);
520 sal_Bool bURLSet
= sal_False
;
521 ::rtl::OUString aValue
;
522 ::rtl::OUString aName
;
525 for ( int i
= 0; i
< aPropertyValues
.getLength(); i
++ )
527 aPropertyValues
[i
].Value
>>= aValue
;
528 if ( aPropertyValues
[i
].Name
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( PROP_EVENT_TYPE
)))
529 pList
->AddAttribute( m_aAttributeLanguage
, m_aAttributeType
, aValue
);
530 else if ( aPropertyValues
[i
].Name
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( PROP_MACRO_NAME
)) &&
531 aValue
.getLength() > 0 )
532 pList
->AddAttribute( m_aAttributeMacroName
, m_aAttributeType
, aValue
);
533 else if ( aPropertyValues
[i
].Name
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( PROP_LIBRARY
)) &&
534 aValue
.getLength() > 0 )
535 pList
->AddAttribute( m_aAttributeLibrary
, m_aAttributeType
, aValue
);
536 else if ( aPropertyValues
[i
].Name
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( PROP_SCRIPT
)))
538 pList
->AddAttribute( m_aAttributeURL
, m_aAttributeType
, aValue
);
544 pList
->AddAttribute( m_aAttributeLinkType
, m_aAttributeType
, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "simple" )) );
546 m_xWriteDocumentHandler
->startElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_EVENT
)), xList
);
547 m_xWriteDocumentHandler
->ignorableWhitespace( ::rtl::OUString() );
549 m_xWriteDocumentHandler
->endElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_EVENT
)) );
550 m_xWriteDocumentHandler
->ignorableWhitespace( ::rtl::OUString() );
554 } // namespace framework